From 4fd4d5326a5656084ada4f387d95259967116c5d Mon Sep 17 00:00:00 2001 From: metagn Date: Wed, 21 Aug 2024 13:13:46 +0300 Subject: [PATCH] generate symchoice for ambiguous types in templates + allow types in symchoices fixes #23898 --- compiler/semtempl.nim | 19 +++++++++++++++++-- compiler/sigmatch.nim | 5 ++--- .../{mqualifiedamb1.nim => mambtype1.nim} | 0 tests/lookups/mambtype2.nim | 4 ++++ tests/lookups/mqualifiedamb2.nim | 4 ---- tests/lookups/tambtype.nim | 13 +++++++++++++ tests/lookups/tqualifiedamb.nim | 4 ---- 7 files changed, 36 insertions(+), 13 deletions(-) rename tests/lookups/{mqualifiedamb1.nim => mambtype1.nim} (100%) create mode 100644 tests/lookups/mambtype2.nim delete mode 100644 tests/lookups/mqualifiedamb2.nim create mode 100644 tests/lookups/tambtype.nim delete mode 100644 tests/lookups/tqualifiedamb.nim diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index f521de7e399e..fdfc25ae1da0 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -66,7 +66,10 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule; # (s.kind notin routineKinds or s.magic != mNone): # for instance 'nextTry' is both in tables.nim and astalgo.nim ... if not isField or sfGenSym notin s.flags: - result = newSymNode(s, info) + if s.kind == skType: + result = newSymNodeTypeDesc(s, c.idgen, info) + else: + result = newSymNode(s, info) markUsed(c, info, s) onUse(info, s) else: @@ -85,7 +88,10 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule; if a.kind != skModule and (not isField or sfGenSym notin a.flags): incl(a.flags, sfUsed) markOwnerModuleAsUsed(c, a) - result.add newSymNode(a, info) + if a.kind == skType: + result.add newSymNodeTypeDesc(a, c.idgen, info) + else: + result.add newSymNode(a, info) onUse(info, a) a = nextOverloadIter(o, c, n) @@ -245,6 +251,11 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode = result = n of skType: if isField and sfGenSym in s.flags: result = n + elif c.isAmbiguous: + # ambiguous types should be symchoices since lookup behaves differently + # for them in regular expressions, + # make sure c.isAmbiguous is set correctly before calling this proc + result = symChoice(c, n, s, scOpen, isField) else: result = newSymNodeTypeDesc(s, c.idgen, n.info) else: if isField and sfGenSym in s.flags: result = n @@ -345,6 +356,8 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = case n.kind of nkIdent: if n.ident.id in c.toInject: return n + # used in `semTemplSymbol`: + c.c.isAmbiguous = false let s = qualifiedLookUp(c.c, n, {}) if s != nil: if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags: @@ -558,6 +571,8 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = of nkDotExpr, nkAccQuoted: # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam', # so we use the generic code for nkDotExpr too + # used in `semTemplSymbol`: + c.c.isAmbiguous = false let s = qualifiedLookUp(c.c, n, {}) if s != nil: # mirror the nkIdent case diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index f68bac2f0bfc..6318091a85bb 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -2426,9 +2426,8 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, if arg[i].sym.kind in matchSet: copyCandidate(z, m) z.callee = arg[i].typ - if arg[i].sym.kind == skType and z.callee.kind != tyTypeDesc: - z.callee = newType(tyTypeDesc, c.idgen, arg[i].sym.owner) - z.callee.addSonSkipIntLit(arg[i].sym.typ, c.idgen) + # should read like "if symbol is type, type should be typedesc": + assert arg[i].sym.kind != skType or z.callee.kind == tyTypeDesc if tfUnresolved in z.callee.flags: continue z.calleeSym = arg[i].sym z.calleeScope = cmpScopes(m.c, arg[i].sym) diff --git a/tests/lookups/mqualifiedamb1.nim b/tests/lookups/mambtype1.nim similarity index 100% rename from tests/lookups/mqualifiedamb1.nim rename to tests/lookups/mambtype1.nim diff --git a/tests/lookups/mambtype2.nim b/tests/lookups/mambtype2.nim new file mode 100644 index 000000000000..cf622466b168 --- /dev/null +++ b/tests/lookups/mambtype2.nim @@ -0,0 +1,4 @@ +import ./mambtype1 +export mambtype1 +template K*(kind: static int): auto = typedesc[mambtype1.K] +template B*(kind: static int): auto = typedesc[mambtype1.K] diff --git a/tests/lookups/mqualifiedamb2.nim b/tests/lookups/mqualifiedamb2.nim deleted file mode 100644 index 3ea5bd04fd6a..000000000000 --- a/tests/lookups/mqualifiedamb2.nim +++ /dev/null @@ -1,4 +0,0 @@ -import ./mqualifiedamb1 -export mqualifiedamb1 -template K*(kind: static int): auto = typedesc[mqualifiedamb1.K] -template B*(kind: static int): auto = typedesc[mqualifiedamb1.K] diff --git a/tests/lookups/tambtype.nim b/tests/lookups/tambtype.nim new file mode 100644 index 000000000000..977a4528049b --- /dev/null +++ b/tests/lookups/tambtype.nim @@ -0,0 +1,13 @@ +import ./mambtype2 + +block: # issue #23893 + discard default(K(0)) # works + discard default(mambtype2.B(0)) # works + discard default(mambtype2.K(0)) # doesn't work + +block: # issue #23898, in template + template r() = + discard default(B(0)) # compiles + discard default(mambtype2.B(0)) # compiles + discard default(K(0)) # does not compile + r() diff --git a/tests/lookups/tqualifiedamb.nim b/tests/lookups/tqualifiedamb.nim deleted file mode 100644 index a5e1955f3e99..000000000000 --- a/tests/lookups/tqualifiedamb.nim +++ /dev/null @@ -1,4 +0,0 @@ -import ./mqualifiedamb2 -discard default(K(0)) # works -discard default(mqualifiedamb2.B(0)) # works -discard default(mqualifiedamb2.K(0)) # doesn't work