From d9141174142c05b7e95bbb1255733646c73baf61 Mon Sep 17 00:00:00 2001 From: metagn Date: Wed, 12 Feb 2025 18:42:38 +0300 Subject: [PATCH 1/3] test treating qualified dot expr types same as idents fixes #18095 --- compiler/semtypes.nim | 71 +++++++++++--------------- tests/lookups/mqualifiedtypeclass.nim | 8 +++ tests/lookups/tqualifiedtypeclass1.nim | 19 +++++++ tests/lookups/tqualifiedtypeclass2.nim | 12 +++++ 4 files changed, 68 insertions(+), 42 deletions(-) create mode 100644 tests/lookups/mqualifiedtypeclass.nim create mode 100644 tests/lookups/tqualifiedtypeclass1.nim create mode 100644 tests/lookups/tqualifiedtypeclass2.nim diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index cc16fd3c0eb69..0bfdef7364e38 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -2020,6 +2020,27 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = localError(c.config, n.info, "identifier expected") result = errorSym(c, n) +proc identSymToType(c: PContext; n: PNode; prev: PType; s: PSym): PType = + assert s.typ != nil + if s.kind == skParam and s.typ.kind == tyTypeDesc: + internalAssert c.config, s.typ.base.kind != tyNone + result = s.typ.base + elif prev == nil: + result = s.typ + else: + let alias = maybeAliasType(c, s.typ, prev) + if alias != nil: + result = alias + elif prev.kind == tyGenericBody: + result = s.typ + else: + assignType(prev, s.typ) + # bugfix: keep the fresh id for aliases to integral types: + if s.typ.kind notin {tyBool, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, + tyUInt..tyUInt64}: + prev.itemId = s.typ.itemId + result = prev + proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = nil inc c.inTypeContext @@ -2196,50 +2217,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = else: result = semGeneric(c, n, s, prev) else: result = semGeneric(c, n, s, prev) of nkDotExpr: - let typeExpr = semExpr(c, n) - if typeExpr.typ.isNil: - localError(c.config, n.info, "object constructor needs an object type;" & - " for named arguments use '=' instead of ':'") - result = errorType(c) - elif typeExpr.typ.kind == tyFromExpr: - result = typeExpr.typ - elif typeExpr.typ.kind != tyTypeDesc: - localError(c.config, n.info, errTypeExpected) - result = errorType(c) + var s = qualifiedLookUp(c, n, {}) + if s != nil: + s = semTypeIdent(c, n) + if s == nil or s.typ == nil: + result = semTypeExpr(c, n, prev) else: - result = typeExpr.typ.base - if result.isMetaType and - result.kind != tyUserTypeClass: - # the dot expression may refer to a concept type in - # a different module. allow a normal alias then. - let preprocessed = semGenericStmt(c, n) - result = makeTypeFromExpr(c, preprocessed.copyTree) - else: - let alias = maybeAliasType(c, result, prev) - if alias != nil: result = alias + result = identSymToType(c, n, prev, s) of nkIdent, nkAccQuoted: - var s = semTypeIdent(c, n) - if s.typ == nil: - if s.kind != skError: localError(c.config, n.info, errTypeExpected) - result = newOrPrevType(tyError, prev, c) - elif s.kind == skParam and s.typ.kind == tyTypeDesc: - internalAssert c.config, s.typ.base.kind != tyNone - result = s.typ.base - elif prev == nil: - result = s.typ - else: - let alias = maybeAliasType(c, s.typ, prev) - if alias != nil: - result = alias - elif prev.kind == tyGenericBody: - result = s.typ - else: - assignType(prev, s.typ) - # bugfix: keep the fresh id for aliases to integral types: - if s.typ.kind notin {tyBool, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, - tyUInt..tyUInt64}: - prev.itemId = s.typ.itemId - result = prev + let s = semTypeIdent(c, n) + result = identSymToType(c, n, prev, s) of nkSym: let s = getGenSym(c, n.sym) if s.typ != nil and (s.kind == skType or s.typ.kind == tyTypeDesc): diff --git a/tests/lookups/mqualifiedtypeclass.nim b/tests/lookups/mqualifiedtypeclass.nim new file mode 100644 index 0000000000000..3cf0a5d523e04 --- /dev/null +++ b/tests/lookups/mqualifiedtypeclass.nim @@ -0,0 +1,8 @@ +type + A* = object + discard + + B* = object + discard + + C* = A | B diff --git a/tests/lookups/tqualifiedtypeclass1.nim b/tests/lookups/tqualifiedtypeclass1.nim new file mode 100644 index 0000000000000..440ef2752b668 --- /dev/null +++ b/tests/lookups/tqualifiedtypeclass1.nim @@ -0,0 +1,19 @@ +# issue #18095 + +import mqualifiedtypeclass + +when true: + # These work fine. + discard default(mqualifiedtypeclass.A) + proc f1(x: mqualifiedtypeclass.A) = discard + discard default(mqualifiedtypeclass.B) + proc f2(x: mqualifiedtypeclass.B) = discard + discard default(A) + proc f3(x: A) = discard + discard default(B) + proc f4(x: B) = discard + proc f5(x: C) = discard + proc f6(x: mqualifiedtypeclass.C | C) = discard + +# Doesn't compile. +proc f(x: mqualifiedtypeclass.C) = discard diff --git a/tests/lookups/tqualifiedtypeclass2.nim b/tests/lookups/tqualifiedtypeclass2.nim new file mode 100644 index 0000000000000..6968783e114c7 --- /dev/null +++ b/tests/lookups/tqualifiedtypeclass2.nim @@ -0,0 +1,12 @@ +# issue #18095 + +type + A* = object + B* = object + C* = A | B +type B2 = tqualifiedtypeclass2.B +type C2 = tqualifiedtypeclass2.C +proc fn1(a: tqualifiedtypeclass2.B) = discard +proc fn2(a: C) = discard +proc f3(a: C2) = discard # Error: invalid type: 'C2' in this context: 'proc (a: C2)' for proc +proc fn4(a: tqualifiedtypeclass2.C) = discard # ditto From 057f5f1d883c7efc325670548274d6afee1e3d10 Mon Sep 17 00:00:00 2001 From: metagn Date: Wed, 12 Feb 2025 19:27:19 +0300 Subject: [PATCH 2/3] fix style check --- compiler/semtypes.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 0bfdef7364e38..a68c36bc95af4 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -1961,8 +1961,9 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = if result.isNil: result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared}) if result != nil: - markUsed(c, n.info, result) - onUse(n.info, result) + let symInfo = getCallLineInfo(n) + markUsed(c, symInfo, result) + onUse(symInfo, result) # alias syntax, see semSym for skTemplate, skMacro if result.kind in {skTemplate, skMacro} and sfNoalias notin result.flags: From 09ff8a709fd3b16b328dbbeca8d61ea5714fb734 Mon Sep 17 00:00:00 2001 From: metagn Date: Sat, 15 Feb 2025 08:51:44 +0300 Subject: [PATCH 3/3] test just deferring to `semTypeExpr` --- compiler/semtypes.nim | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a68c36bc95af4..c9d62c7558b2c 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -2217,14 +2217,14 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = of "owned": result = semAnyRef(c, n, tyOwned, prev) else: result = semGeneric(c, n, s, prev) else: result = semGeneric(c, n, s, prev) - of nkDotExpr: - var s = qualifiedLookUp(c, n, {}) - if s != nil: - s = semTypeIdent(c, n) - if s == nil or s.typ == nil: - result = semTypeExpr(c, n, prev) - else: - result = identSymToType(c, n, prev, s) + #of nkDotExpr: + # var s = qualifiedLookUp(c, n, {}) + # if s != nil: + # s = semTypeIdent(c, n) + # if s == nil or s.typ == nil: + # result = semTypeExpr(c, n, prev) + # else: + # result = identSymToType(c, n, prev, s) of nkIdent, nkAccQuoted: let s = semTypeIdent(c, n) result = identSymToType(c, n, prev, s)