Fixed generic distinct conversions for 'var' (#18837)

* SameTypeAux now properly traverses generic distincts

* Smarter traversal of distincts

* Removed redundant check

* Fixed nkConv for jsgen

* Added test for non distinct nkConv

* using skiptypes for distinct now

* Fixed genaddr for nkconv

(cherry picked from commit 83a2515af7)
This commit is contained in:
Jason Beetham
2021-10-26 03:27:11 -06:00
committed by narimiran
parent 2f247ed1a7
commit 5bb626d4b1
4 changed files with 104 additions and 67 deletions

View File

@@ -1297,75 +1297,89 @@ template isIndirect(x: PSym): bool =
v.kind notin {skProc, skFunc, skConverter, skMethod, skIterator,
skConst, skTemp, skLet})
proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
case n[0].kind
of nkSym:
let s = n[0].sym
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
case s.kind
of skParam:
r.res = s.loc.r
r.address = nil
r.typ = etyNone
of skVar, skLet, skResult:
r.kind = resExpr
let jsType = mapType(p, n.typ)
if jsType == etyObject:
# make addr() a no-op:
r.typ = etyNone
if isIndirect(s):
r.res = s.loc.r & "[0]"
else:
r.res = s.loc.r
r.address = nil
elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex:
# for ease of code generation, we do not distinguish between
# sfAddrTaken and sfGlobal.
r.typ = etyBaseIndex
r.address = s.loc.r
r.res = rope("0")
proc genSymAddr(p: PProc, n: PNode, typ: PType, r: var TCompRes) =
let s = n.sym
if s.loc.r == nil: internalError(p.config, n.info, "genAddr: 3")
case s.kind
of skParam:
r.res = s.loc.r
r.address = nil
r.typ = etyNone
of skVar, skLet, skResult:
r.kind = resExpr
let jsType = mapType(p):
if typ.isNil:
n.typ
else:
# 'var openArray' for instance produces an 'addr' but this is harmless:
gen(p, n[0], r)
#internalError(p.config, n.info, "genAddr: 4 " & renderTree(n))
else: internalError(p.config, n.info, $("genAddr: 2", s.kind))
of nkCheckedFieldExpr:
genCheckedFieldOp(p, n[0], n.typ, r)
of nkDotExpr:
if mapType(p, n.typ) == etyBaseIndex:
genFieldAddr(p, n[0], r)
typ
if jsType == etyObject:
# make addr() a no-op:
r.typ = etyNone
if isIndirect(s):
r.res = s.loc.r & "[0]"
else:
r.res = s.loc.r
r.address = nil
elif {sfGlobal, sfAddrTaken} * s.flags != {} or jsType == etyBaseIndex:
# for ease of code generation, we do not distinguish between
# sfAddrTaken and sfGlobal.
r.typ = etyBaseIndex
r.address = s.loc.r
r.res = rope("0")
else:
genFieldAccess(p, n[0], r)
of nkBracketExpr:
var ty = skipTypes(n[0].typ, abstractVarRange)
if ty.kind in MappedToObject:
gen(p, n[0], r)
else:
let kindOfIndexedExpr = skipTypes(n[0][0].typ, abstractVarRange).kind
case kindOfIndexedExpr
of tyArray, tyOpenArray, tySequence, tyString, tyCstring, tyVarargs:
genArrayAddr(p, n[0], r)
of tyTuple:
genFieldAddr(p, n[0], r)
else: internalError(p.config, n[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
of nkObjDownConv:
gen(p, n[0], r)
of nkHiddenDeref:
gen(p, n[0], r)
of nkHiddenAddr:
gen(p, n[0], r)
of nkStmtListExpr:
if n.len == 1: gen(p, n[0], r)
else: internalError(p.config, n[0].info, "genAddr for complex nkStmtListExpr")
of nkCallKinds:
if n[0].typ.kind == tyOpenArray:
# 'var openArray' for instance produces an 'addr' but this is harmless:
# namely toOpenArray(a, 1, 3)
gen(p, n, r)
#internalError(p.config, n.info, "genAddr: 4 " & renderTree(n))
else: internalError(p.config, n.info, $("genAddr: 2", s.kind))
proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
if n.kind == nkSym:
genSymAddr(p, n, nil, r)
else:
case n[0].kind
of nkSym:
genSymAddr(p, n[0], n.typ, r)
of nkCheckedFieldExpr:
genCheckedFieldOp(p, n[0], n.typ, r)
of nkDotExpr:
if mapType(p, n.typ) == etyBaseIndex:
genFieldAddr(p, n[0], r)
else:
genFieldAccess(p, n[0], r)
of nkBracketExpr:
var ty = skipTypes(n[0].typ, abstractVarRange)
if ty.kind in MappedToObject:
gen(p, n[0], r)
else:
let kindOfIndexedExpr = skipTypes(n[0][0].typ, abstractVarRange).kind
case kindOfIndexedExpr
of tyArray, tyOpenArray, tySequence, tyString, tyCstring, tyVarargs:
genArrayAddr(p, n[0], r)
of tyTuple:
genFieldAddr(p, n[0], r)
of tyGenericBody:
genAddr(p, n[^1], r)
else: internalError(p.config, n[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
of nkObjDownConv:
gen(p, n[0], r)
of nkHiddenDeref:
gen(p, n[0], r)
of nkHiddenAddr:
gen(p, n[0], r)
of nkConv:
genAddr(p, n[0], r)
of nkStmtListExpr:
if n.len == 1: gen(p, n[0], r)
else: internalError(p.config, n[0].info, "genAddr for complex nkStmtListExpr")
of nkCallKinds:
if n[0].typ.kind == tyOpenArray:
# 'var openArray' for instance produces an 'addr' but this is harmless:
# namely toOpenArray(a, 1, 3)
gen(p, n[0], r)
else:
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
else:
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
else:
internalError(p.config, n[0].info, "genAddr: " & $n[0].kind)
proc attachProc(p: PProc; content: Rope; s: PSym) =
p.g.code.add(content)

View File

@@ -1121,15 +1121,15 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
case c.cmp
of dcEq: return false
of dcEqIgnoreDistinct:
while a.kind == tyDistinct: a = a[0]
while b.kind == tyDistinct: b = b[0]
a = a.skipTypes({tyDistinct, tyGenericInst})
b = b.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
of dcEqOrDistinctOf:
while a.kind == tyDistinct: a = a[0]
a = a.skipTypes({tyDistinct, tyGenericInst})
if a.kind != b.kind: return false
# this is required by tunique_type but makes no sense really:
if x.kind == tyGenericInst and IgnoreTupleFields notin c.flags:
if tyDistinct notin {x.kind, y.kind} and x.kind == tyGenericInst and IgnoreTupleFields notin c.flags:
let
lhs = x.skipGenericAlias
rhs = y.skipGenericAlias

View File

@@ -11,3 +11,9 @@ converter toInt(s: string): int =
let x = (int)"234"
echo x
block: # Test for nkconv
proc foo(o: var int) =
assert o == 0
var a = 0
foo(int(a))

View File

@@ -8,6 +8,7 @@ false
false
false
Foo
foo
'''
"""
@@ -140,6 +141,22 @@ block tRequiresInit:
let s = "test"
doAssert s == "test"
block: #17322
type
A[T] = distinct string
proc foo(a: var A) =
a.string.add "foo"
type
B = distinct A[int]
var b: B
foo(A[int](b))
echo A[int](b).string
b.string.add "bar"
assert b.string == "foobar"
type Foo = distinct string
template main() =