summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/semexprs.nim10
-rwxr-xr-xcompiler/semgnrc.nim9
-rwxr-xr-xcompiler/semstmts.nim11
-rw-r--r--tests/run/tmixin.nim27
4 files changed, 47 insertions, 10 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index adcd67ea3..2c98d9de6 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -471,7 +471,8 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
   result = n
   case n.kind
   of nkSym: 
-    if skipTypes(n.sym.typ, abstractInst).kind != tyVar: 
+    # n.sym.typ can be nil in 'check' mode ...
+    if n.sym.typ != nil and skipTypes(n.sym.typ, abstractInst).kind != tyVar: 
       incl(n.sym.flags, sfAddrTaken)
       result = newHiddenAddrTaken(c, n)
   of nkDotExpr: 
@@ -722,9 +723,6 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
   addSon(result, semExpr(c, arg))
 
 proc discardCheck(result: PNode) =
-  proc ImplicitelyDiscardable(n: PNode): bool {.inline.} =
-    result = isCallExpr(n) and n.sons[0].kind == nkSym and 
-             sfDiscardable in n.sons[0].sym.flags
   if result.typ != nil and result.typ.kind notin {tyStmt, tyEmpty}:
     if result.kind == nkNilLit:
       # XXX too much work and fixing would break bootstrapping:
@@ -1104,7 +1102,9 @@ proc semProcBody(c: PContext, n: PNode): PNode =
     # ``result``:
     if result.kind == nkSym and result.sym == c.p.resultSym:
       nil
-    elif result.kind == nkNilLit:
+    elif result.kind == nkNilLit or ImplicitelyDiscardable(result):
+      # intended semantic: if it's 'discardable' and the context allows for it,
+      # discard it. This is bad for chaining but nicer for C wrappers. 
       # ambiguous :-(
       result.typ = nil
     else:
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index dc0be54cb..4eaa5f39b 100755
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -87,7 +87,7 @@ proc Lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
     if ident.id notin ctx and withinMixin notin flags:
       localError(n.info, errUndeclaredIdentifier, ident.s)
   else:
-    if withinMixin in flags:
+    if withinBind in flags:
       result = symChoice(c, n, s, scClosed)
     elif s.name.id in ctx:
       result = symChoice(c, n, s, scForceOpen)
@@ -134,26 +134,27 @@ proc semGenericStmt(c: PContext, n: PNode,
     if s != nil: 
       incl(s.flags, sfUsed)
       isDefinedMagic = s.magic in {mDefined, mDefinedInScope, mCompiles}
+      let scOption = if s.name.id in ctx: scForceOpen else: scOpen
       case s.kind
       of skMacro:
         if macroToExpand(s):
           result = semMacroExpr(c, n, n, s, false)
         else:
-          n.sons[0] = symChoice(c, n.sons[0], s, scOpen)
+          n.sons[0] = symChoice(c, n.sons[0], s, scOption)
           result = n
       of skTemplate: 
         if macroToExpand(s):
           let n = fixImmediateParams(n)
           result = semTemplateExpr(c, n, s, false)
         else:
-          n.sons[0] = symChoice(c, n.sons[0], s, scOpen)
+          n.sons[0] = symChoice(c, n.sons[0], s, scOption)
           result = n
         # BUGFIX: we must not return here, we need to do first phase of
         # symbol lookup ...
       of skUnknown, skParam: 
         # Leave it as an identifier.
       of skProc, skMethod, skIterator, skConverter: 
-        result.sons[0] = symChoice(c, n.sons[0], s, scOpen)
+        result.sons[0] = symChoice(c, n.sons[0], s, scOption)
         first = 1
       of skGenericParam: 
         result.sons[0] = newSymNode(s, n.sons[0].info)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 5c0060e20..2d36015a7 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1088,6 +1088,10 @@ proc insertDestructors(c: PContext, varSection: PNode):
 
       return
 
+proc ImplicitelyDiscardable(n: PNode): bool =
+  result = isCallExpr(n) and n.sons[0].kind == nkSym and 
+           sfDiscardable in n.sons[0].sym.flags
+
 proc semStmtList(c: PContext, n: PNode): PNode =
   # these must be last statements in a block:
   const
@@ -1134,7 +1138,12 @@ proc semStmtList(c: PContext, n: PNode): PNode =
   
   # a statement list (s; e) has the type 'e':
   if result.kind == nkStmtList and result.len > 0:
-    result.typ = lastSon(result).typ
+    var lastStmt = lastSon(result)
+    if not ImplicitelyDiscardable(lastStmt):
+      result.typ = lastStmt.typ
+      #localError(lastStmt.info, errGenerated,
+      #  "Last expression must be explicitly returned if it " &
+      #  "is discardable or discarded")
 
 proc SemStmt(c: PContext, n: PNode): PNode = 
   # now: simply an alias:
diff --git a/tests/run/tmixin.nim b/tests/run/tmixin.nim
new file mode 100644
index 000000000..d841326a5
--- /dev/null
+++ b/tests/run/tmixin.nim
@@ -0,0 +1,27 @@
+discard """
+  output: "1\n2"
+"""
+
+type
+  TFoo1 = object of TObject
+    v: int
+  TFoo2 = object of TFoo1
+    v2: int
+
+proc test(f: TFoo1) =
+  echo "1"
+
+proc Foo[T](f: T) =
+  mixin test
+  test(f)
+
+var
+  a: TFoo1
+  b: TFoo2
+
+
+proc test(f: TFoo2) =
+  echo "2"
+
+Foo(a)
+Foo(b)