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.
This commit is contained in:
parent
3e7aaa7087
commit
a87341775a
3 changed files with 63 additions and 17 deletions
|
|
@ -352,6 +352,11 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
res = t.kind == tyProc and
|
res = t.kind == tyProc and
|
||||||
t.callConv == ccClosure and
|
t.callConv == ccClosure and
|
||||||
tfIterator notin t.flags
|
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:
|
else:
|
||||||
res = false
|
res = false
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -173,32 +173,41 @@ proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
|
||||||
result.n = n
|
result.n = n
|
||||||
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
|
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
|
# XXX: This should use the standard isOpImpl
|
||||||
#internalAssert a.kind == nkSym and a.sym.kind == skType
|
internalAssert g.config,
|
||||||
#internalAssert n.sonsLen == 3 and
|
n.sonsLen == 3 and
|
||||||
# n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
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}:
|
if n[2].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
case n[2].strVal.normalize
|
case n[2].strVal.normalize
|
||||||
of "closure":
|
of "closure":
|
||||||
let t = skipTypes(t1, abstractRange)
|
let t = skipTypes(t1, abstractRange)
|
||||||
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
|
res = t.kind == tyProc and
|
||||||
t.callConv == ccClosure and
|
t.callConv == ccClosure and
|
||||||
tfIterator notin t.flags))
|
tfIterator notin t.flags
|
||||||
of "iterator":
|
of "iterator":
|
||||||
let t = skipTypes(t1, abstractRange)
|
let t = skipTypes(t1, abstractRange)
|
||||||
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
|
res = t.kind == tyProc and
|
||||||
t.callConv == ccClosure and
|
t.callConv == ccClosure and
|
||||||
tfIterator in t.flags))
|
tfIterator in t.flags
|
||||||
else: discard
|
else:
|
||||||
|
res = false
|
||||||
else:
|
else:
|
||||||
# XXX semexprs.isOpImpl is slightly different and requires a context. yay.
|
# XXX semexprs.isOpImpl is slightly different and requires a context. yay.
|
||||||
let t2 = n[2].typ
|
let t2 = n[2].typ
|
||||||
var match = sameType(t1, t2)
|
res = sameType(t1, t2)
|
||||||
result = newIntNode(nkIntLit, ord(match))
|
|
||||||
|
result = newIntNode(nkIntLit, ord(res))
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
|
|
||||||
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
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)
|
result = copyTree(s.ast)
|
||||||
of skProc, skFunc, skMethod:
|
of skProc, skFunc, skMethod:
|
||||||
result = n
|
result = n
|
||||||
|
of skParam:
|
||||||
|
if s.typ != nil and s.typ.kind == tyTypeDesc:
|
||||||
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
of skType:
|
of skType:
|
||||||
# XXX gensym'ed symbols can come here and cannot be resolved. This is
|
# XXX gensym'ed symbols can come here and cannot be resolved. This is
|
||||||
# dirty, but correct.
|
# dirty, but correct.
|
||||||
|
|
@ -651,9 +663,9 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
|
||||||
of mConStrStr:
|
of mConStrStr:
|
||||||
result = foldConStrStr(m, n, g)
|
result = foldConStrStr(m, n, g)
|
||||||
of mIs:
|
of mIs:
|
||||||
let a = getConstExpr(m, n[1], g)
|
let lhs = getConstExpr(m, n[1], g)
|
||||||
if a != nil and a.kind == nkSym and a.sym.kind == skType:
|
if lhs != nil and lhs.kind == nkSym:
|
||||||
result = evalIs(n, a)
|
result = evalIs(n, lhs.sym, g)
|
||||||
else:
|
else:
|
||||||
result = magicCall(m, n, g)
|
result = magicCall(m, n, g)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
|
|
|
||||||
29
tests/magics/t8693.nim
Normal file
29
tests/magics/t8693.nim
Normal file
|
|
@ -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)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue