diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index cc16fd3c0eb69..c9d62c7558b2c 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: @@ -2020,6 +2021,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 @@ -2195,51 +2217,17 @@ 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: - 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) - 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 + #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: - 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