summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorLemonBoy <LemonBoy@users.noreply.github.com>2018-08-22 09:40:31 +0200
committerAndreas Rumpf <rumpf_a@web.de>2018-08-22 09:40:31 +0200
commita87341775aa424f252e9e17d58119b0758b58693 (patch)
tree86a2ba9d2936c65d7fc16d58a9c2198bd36955f6
parent3e7aaa70878d6eda0dfb2737243efae6daa6e26c (diff)
downloadNim-a87341775aa424f252e9e17d58119b0758b58693.tar.gz
Don't consider tyAnd/tyNot/tyOr/tyAnything as generic (#8700)
* Don't consider tyAnd/tyNot/tyOr/tyAnything as generic

`containsGenericType` was too shallow and didn't check all the branches.
The resulting half-processed nodes are often simplified by the constant
folding pass but when that's not possible we get a nasty error during
codegen.

Fixes #8693

* Move the blame onto the semFold pass

Slightly better evaluation of `is` forms.
-rw-r--r--compiler/semexprs.nim5
-rw-r--r--compiler/semfold.nim46
-rw-r--r--tests/magics/t8693.nim29
3 files changed, 63 insertions, 17 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index c9f9eb33f..91bee54ac 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -352,6 +352,11 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
       res = t.kind == tyProc and
             t.callConv == ccClosure and
             tfIterator notin t.flags
+    of "iterator":
+      let t = skipTypes(t1, abstractRange)
+      res = t.kind == tyProc and
+            t.callConv == ccClosure and
+            tfIterator in t.flags
     else:
       res = false
   else:
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index a6c185fdc..0a33fea7a 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -173,32 +173,41 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
   result.n = n
   addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
 
-proc evalIs(n, a: PNode): PNode =
+proc evalIs(n: PNode, lhs: PSym, g: ModuleGraph): PNode =
   # XXX: This should use the standard isOpImpl
-  #internalAssert a.kind == nkSym and a.sym.kind == skType
-  #internalAssert n.sonsLen == 3 and
-  #  n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
+  internalAssert g.config,
+    n.sonsLen == 3 and
+    lhs.typ != nil and
+    n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
 
-  let t1 = a.sym.typ
+  var
+    res = false
+    t1 = lhs.typ
+    t2 = n[2].typ
+
+  if t1.kind == tyTypeDesc and t2.kind != tyTypeDesc:
+    t1 = t1.base
 
   if n[2].kind in {nkStrLit..nkTripleStrLit}:
     case n[2].strVal.normalize
     of "closure":
       let t = skipTypes(t1, abstractRange)
-      result = newIntNode(nkIntLit, ord(t.kind == tyProc and
-                                        t.callConv == ccClosure and
-                                        tfIterator notin t.flags))
+      res = t.kind == tyProc and
+            t.callConv == ccClosure and
+            tfIterator notin t.flags
     of "iterator":
       let t = skipTypes(t1, abstractRange)
-      result = newIntNode(nkIntLit, ord(t.kind == tyProc and
-                                        t.callConv == ccClosure and
-                                        tfIterator in t.flags))
-    else: discard
+      res = t.kind == tyProc and
+            t.callConv == ccClosure and
+            tfIterator in t.flags
+    else:
+      res = false
   else:
     # XXX semexprs.isOpImpl is slightly different and requires a context. yay.
     let t2 = n[2].typ
-    var match = sameType(t1, t2)
-    result = newIntNode(nkIntLit, ord(match))
+    res = sameType(t1, t2)
+
+  result = newIntNode(nkIntLit, ord(res))
   result.typ = n.typ
 
 proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
@@ -584,6 +593,9 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
         result = copyTree(s.ast)
     of skProc, skFunc, skMethod:
       result = n
+    of skParam:
+      if s.typ != nil and s.typ.kind == tyTypeDesc:
+        result = newSymNodeTypeDesc(s, n.info)
     of skType:
       # XXX gensym'ed symbols can come here and cannot be resolved. This is
       # dirty, but correct.
@@ -651,9 +663,9 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
       of mConStrStr:
         result = foldConStrStr(m, n, g)
       of mIs:
-        let a = getConstExpr(m, n[1], g)
-        if a != nil and a.kind == nkSym and a.sym.kind == skType:
-          result = evalIs(n, a)
+        let lhs = getConstExpr(m, n[1], g)
+        if lhs != nil and lhs.kind == nkSym:
+          result = evalIs(n, lhs.sym, g)
       else:
         result = magicCall(m, n, g)
     except OverflowError:
diff --git a/tests/magics/t8693.nim b/tests/magics/t8693.nim
new file mode 100644
index 000000000..554244de4
--- /dev/null
+++ b/tests/magics/t8693.nim
@@ -0,0 +1,29 @@
+discard """
+  output: '''true
+false
+true
+false
+false
+true
+true
+false
+true
+true
+'''
+"""
+
+type Foo = int | float
+
+proc bar(t1, t2: typedesc): bool =
+  echo (t1 is t2)
+  (t2 is t1)
+
+proc bar[T](x: T, t2: typedesc): bool =
+  echo (T is t2)
+  (t2 is T)
+
+echo bar(int, Foo)
+echo bar(4, Foo)
+echo bar(any, int)
+echo bar(int, any)
+echo bar(Foo, Foo)