mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-11 22:08:54 +00:00
remove fauxMatch for tyFromExpr, remove tyProxy and tyUnknown aliases (#24018)
updated version of #22193 After #22029 and the followups #23983 and #24005 which fixed issues with it, `tyFromExpr` no longer match any proc params in generic type bodies but delay all non-matching calls until the type is instantiated. Previously the mechanism `fauxMatch` was used to pretend that any failing match against `tyFromExpr` actually matched, but prevented the instantiation of the type until later. Since this mechanism is not needed anymore for `tyFromExpr`, it is now only used for `tyError` to prevent cascading errors and changed to a bool field for simplicity. A change in `semtypes` was also needed to prevent calling `fitNode` on default param values resolving to type `tyFromExpr` in generic procs for params with non-generic types, as this would try to coerce the expression into a concrete type when it can't be instantiated yet. The aliases `tyProxy` and `tyUnknown` for `tyError` and `tyFromExpr` are also removed for uniformity.
This commit is contained in:
@@ -214,7 +214,8 @@ type
|
||||
tyUncheckedArray
|
||||
# An array with boundaries [0,+∞]
|
||||
|
||||
tyProxy # used as errornous type (for idetools)
|
||||
tyError # used as erroneous type (for idetools)
|
||||
# as an erroneous node should match everything
|
||||
|
||||
tyBuiltInTypeClass
|
||||
# Type such as the catch-all object, tuple, seq, etc
|
||||
@@ -276,10 +277,6 @@ static:
|
||||
const
|
||||
tyPureObject* = tyTuple
|
||||
GcTypeKinds* = {tyRef, tySequence, tyString}
|
||||
tyError* = tyProxy # as an errornous node should match everything
|
||||
tyUnknown* = tyFromExpr
|
||||
|
||||
tyUnknownTypes* = {tyError, tyFromExpr}
|
||||
|
||||
tyTypeClasses* = {tyBuiltInTypeClass, tyCompositeTypeClass,
|
||||
tyUserTypeClass, tyUserTypeClassInst,
|
||||
|
||||
@@ -96,7 +96,7 @@ proc specializeResetT(p: BProc, accessor: Rope, typ: PType) =
|
||||
raiseAssert "unexpected set type kind"
|
||||
of tyNone, tyEmpty, tyNil, tyUntyped, tyTyped, tyGenericInvocation,
|
||||
tyGenericParam, tyOrdinal, tyOpenArray, tyForward, tyVarargs,
|
||||
tyUncheckedArray, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
||||
tyUncheckedArray, tyError, tyBuiltInTypeClass, tyUserTypeClass,
|
||||
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot,
|
||||
tyAnything, tyStatic, tyFromExpr, tyConcept, tyVoid, tyIterable:
|
||||
discard
|
||||
|
||||
@@ -125,7 +125,7 @@ proc expandDefault(t: PType; info: TLineInfo): PNode =
|
||||
of tyString:
|
||||
result = newZero(t, info, nkStrLit)
|
||||
of tyNone, tyEmpty, tyUntyped, tyTyped, tyTypeDesc,
|
||||
tyNil, tyGenericInvocation, tyProxy, tyBuiltInTypeClass,
|
||||
tyNil, tyGenericInvocation, tyError, tyBuiltInTypeClass,
|
||||
tyUserTypeClass, tyUserTypeClassInst, tyCompositeTypeClass,
|
||||
tyAnd, tyOr, tyNot, tyAnything, tyConcept, tyIterable, tyForward:
|
||||
result = newZero(t, info, nkEmpty) # bug indicator
|
||||
|
||||
@@ -195,7 +195,7 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||
of tyPointer:
|
||||
# treat a tyPointer like a typed pointer to an array of bytes
|
||||
result = etyBaseIndex
|
||||
of tyRange, tyDistinct, tyOrdinal, tyProxy, tyLent:
|
||||
of tyRange, tyDistinct, tyOrdinal, tyError, tyLent:
|
||||
# tyLent is no-op as JS has pass-by-reference semantics
|
||||
result = mapType(skipModifier t)
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyChar: result = etyInt
|
||||
|
||||
@@ -1040,7 +1040,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
else:
|
||||
discard "cannot copy openArray"
|
||||
|
||||
of tyFromExpr, tyProxy, tyBuiltInTypeClass, tyUserTypeClass,
|
||||
of tyFromExpr, tyError, tyBuiltInTypeClass, tyUserTypeClass,
|
||||
tyUserTypeClassInst, tyCompositeTypeClass, tyAnd, tyOr, tyNot, tyAnything,
|
||||
tyGenericParam, tyGenericBody, tyNil, tyUntyped, tyTyped,
|
||||
tyTypeDesc, tyGenericInvocation, tyForward, tyStatic:
|
||||
|
||||
@@ -696,12 +696,12 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
markUsed(c, info, finalCallee)
|
||||
onUse(info, finalCallee)
|
||||
assert finalCallee.ast != nil
|
||||
if x.hasFauxMatch:
|
||||
if x.matchedErrorType:
|
||||
result = x.call
|
||||
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
|
||||
if containsGenericType(result.typ) or x.fauxMatch == tyUnknown:
|
||||
result.typ = newTypeS(x.fauxMatch, c)
|
||||
if result.typ.kind == tyError: incl result.typ.flags, tfCheckedForDestructor
|
||||
if containsGenericType(result.typ):
|
||||
result.typ = newTypeS(tyError, c)
|
||||
incl result.typ.flags, tfCheckedForDestructor
|
||||
return
|
||||
let gp = finalCallee.ast[genericParamsPos]
|
||||
if gp.isGenericParams:
|
||||
|
||||
@@ -2859,7 +2859,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType =
|
||||
let verdict = semConstExpr(c, n[i])
|
||||
if verdict == nil or verdict.kind != nkIntLit or verdict.intVal == 0:
|
||||
localError(c.config, result.info, "concept predicate failed")
|
||||
of tyUnknown: continue
|
||||
of tyFromExpr: continue
|
||||
else: discard
|
||||
if n[i].typ == c.enforceVoidContext: #or usesResult(n[i]):
|
||||
voidContext = true
|
||||
|
||||
@@ -1385,7 +1385,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
typ = newTypeS(tyTypeDesc, c, newTypeS(tyNone, c))
|
||||
typ.flags.incl tfCheckedForDestructor
|
||||
|
||||
else:
|
||||
elif def.typ.kind != tyFromExpr:
|
||||
# if def.typ != nil and def.typ.kind != tyNone:
|
||||
# example code that triggers it:
|
||||
# proc sort[T](cmp: proc(a, b: T): int = cmp)
|
||||
|
||||
@@ -59,8 +59,8 @@ type
|
||||
magic*: TMagic # magic of operation
|
||||
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
||||
# for example
|
||||
fauxMatch*: TTypeKind # the match was successful only due to the use
|
||||
# of error or wildcard (unknown) types.
|
||||
matchedErrorType*: bool # match is considered successful after matching
|
||||
# error type to avoid cascading errors
|
||||
# this is used to prevent instantiations.
|
||||
genericConverter*: bool # true if a generic converter needs to
|
||||
# be instantiated
|
||||
@@ -101,8 +101,6 @@ const
|
||||
proc markUsed*(c: PContext; info: TLineInfo, s: PSym; checkStyle = true)
|
||||
proc markOwnerModuleAsUsed*(c: PContext; s: PSym)
|
||||
|
||||
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
|
||||
|
||||
proc initCandidateAux(ctx: PContext,
|
||||
callee: PType): TCandidate {.inline.} =
|
||||
result = TCandidate(c: ctx, exactMatches: 0, subtypeMatches: 0,
|
||||
@@ -813,7 +811,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||
param.typ.flags.incl tfInferrableStatic
|
||||
else:
|
||||
param.ast = typ.n
|
||||
of tyUnknown:
|
||||
of tyFromExpr:
|
||||
param = paramSym skVar
|
||||
param.typ = typ.exactReplica
|
||||
#copyType(typ, c.idgen, typ.owner)
|
||||
@@ -1971,7 +1969,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
if aOrig != nil:
|
||||
put(c, f, aOrig)
|
||||
result = isGeneric
|
||||
of tyProxy:
|
||||
of tyError:
|
||||
result = isEqual
|
||||
of tyFromExpr:
|
||||
# fix the expression, so it contains the already instantiated types
|
||||
@@ -2037,7 +2035,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||
c: PContext): PNode =
|
||||
result = newNodeI(kind, arg.info)
|
||||
if containsGenericType(f):
|
||||
if not m.hasFauxMatch:
|
||||
if not m.matchedErrorType:
|
||||
result.typ = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
else:
|
||||
result.typ = errorType(c)
|
||||
@@ -2329,13 +2327,10 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
|
||||
of isNone:
|
||||
# do not do this in ``typeRel`` as it then can't infer T in ``ref T``:
|
||||
if a.kind in {tyProxy, tyUnknown}:
|
||||
if a.kind == tyUnknown and c.inGenericContext > 0:
|
||||
# don't bother with fauxMatch mechanism in generic type,
|
||||
# reject match, typechecking will be delayed to instantiation
|
||||
return nil
|
||||
if a.kind == tyFromExpr: return nil
|
||||
elif a.kind == tyError:
|
||||
inc(m.genericMatches)
|
||||
m.fauxMatch = a.kind
|
||||
m.matchedErrorType = true
|
||||
return arg
|
||||
elif a.kind == tyVoid and f.matchesVoidProc and argOrig.kind == nkStmtList:
|
||||
# lift do blocks without params to lambdas
|
||||
@@ -2505,7 +2500,7 @@ proc setSon(father: PNode, at: int, son: PNode) =
|
||||
# we are allowed to modify the calling node in the 'prepare*' procs:
|
||||
proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
|
||||
if formal.kind == tyUntyped and formal.len != 1:
|
||||
# {tyTypeDesc, tyUntyped, tyTyped, tyProxy}:
|
||||
# {tyTypeDesc, tyUntyped, tyTyped, tyError}:
|
||||
# a.typ == nil is valid
|
||||
result = a
|
||||
elif a.typ.isNil:
|
||||
|
||||
@@ -200,7 +200,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
||||
result = typeAllowedNode(marker, t.n, kind, c, flags)
|
||||
of tyEmpty:
|
||||
if kind in {skVar, skLet}: result = t
|
||||
of tyProxy:
|
||||
of tyError:
|
||||
# for now same as error node; we say it's a valid type as it should
|
||||
# prevent cascading errors:
|
||||
result = nil
|
||||
|
||||
@@ -776,7 +776,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
|
||||
proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
case t.kind
|
||||
of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
|
||||
of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyError:
|
||||
result = Zero
|
||||
of tySet, tyVar: result = firstOrd(conf, t.elementType)
|
||||
of tyArray: result = firstOrd(conf, t.indexType)
|
||||
@@ -909,7 +909,7 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
|
||||
result = lastOrd(conf, skipModifier(t))
|
||||
of tyUserTypeClasses:
|
||||
result = lastOrd(conf, last(t))
|
||||
of tyProxy: result = Zero
|
||||
of tyError: result = Zero
|
||||
of tyOrdinal:
|
||||
if t.hasElementType: result = lastOrd(conf, skipModifier(t))
|
||||
else:
|
||||
|
||||
@@ -282,7 +282,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
of tyUInt32: result = atomicType("uint32", mUInt32)
|
||||
of tyUInt64: result = atomicType("uint64", mUInt64)
|
||||
of tyVarargs: result = mapTypeToBracket("varargs", mVarargs, t, info)
|
||||
of tyProxy: result = atomicType("error", mNone)
|
||||
of tyError: result = atomicType("error", mNone)
|
||||
of tyBuiltInTypeClass:
|
||||
result = mapTypeToBracket("builtinTypeClass", mNone, t, info)
|
||||
of tyUserTypeClass, tyUserTypeClassInst:
|
||||
|
||||
@@ -59,7 +59,7 @@ type
|
||||
tyOwned, tyUnused1, tyUnused2,
|
||||
tyVarargsHidden,
|
||||
tyUncheckedArray,
|
||||
tyProxyHidden,
|
||||
tyErrorHidden,
|
||||
tyBuiltInTypeClassHidden,
|
||||
tyUserTypeClassHidden,
|
||||
tyUserTypeClassInstHidden,
|
||||
|
||||
@@ -8,7 +8,7 @@ but expected: <T: float or string, Y>
|
||||
tstatic_constrained.nim(44, 22) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(30, 5)]
|
||||
got: <typedesc[int], int literal(10)>
|
||||
but expected: <T: float or string, Y>
|
||||
tstatic_constrained.nim(44, 31) Error: object constructor needs an object type [proxy]
|
||||
tstatic_constrained.nim(44, 31) Error: object constructor needs an object type [error]
|
||||
tstatic_constrained.nim(44, 31) Error: expression '' has no type (or is ambiguous)
|
||||
tstatic_constrained.nim(45, 22) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(30, 5)]
|
||||
got: <typedesc[byte], uint8>
|
||||
@@ -16,7 +16,7 @@ but expected: <T: float or string, Y>
|
||||
tstatic_constrained.nim(45, 22) Error: cannot instantiate MyOtherType [type declared in tstatic_constrained.nim(30, 5)]
|
||||
got: <typedesc[byte], uint8>
|
||||
but expected: <T: float or string, Y>
|
||||
tstatic_constrained.nim(45, 34) Error: object constructor needs an object type [proxy]
|
||||
tstatic_constrained.nim(45, 34) Error: object constructor needs an object type [error]
|
||||
tstatic_constrained.nim(45, 34) Error: expression '' has no type (or is ambiguous)
|
||||
tstatic_constrained.nim(77, 14) Error: cannot instantiate MyType [type declared in tstatic_constrained.nim(71, 5)]
|
||||
got: <typedesc[float], float64>
|
||||
@@ -76,4 +76,4 @@ block:
|
||||
b: MyType[string, "hello"]
|
||||
c: MyType[float, 10d]
|
||||
d: MyOtherType[MyOtherConstraint[float],MyOtherConstraint[float]()]
|
||||
e: MyOtherType[MyOtherConstraint[int], MyOtherConstraint[int]()]
|
||||
e: MyOtherType[MyOtherConstraint[int], MyOtherConstraint[int]()]
|
||||
|
||||
@@ -4,11 +4,11 @@ discard """
|
||||
nimout:'''
|
||||
tinheritgenericparameter.nim(36, 15) Error: Cannot inherit from: 'MyObject'
|
||||
tinheritgenericparameter.nim(36, 15) Error: Cannot inherit from: 'MyObject'
|
||||
tinheritgenericparameter.nim(36, 23) Error: object constructor needs an object type [proxy]
|
||||
tinheritgenericparameter.nim(36, 23) Error: object constructor needs an object type [error]
|
||||
tinheritgenericparameter.nim(36, 23) Error: expression '' has no type (or is ambiguous)
|
||||
tinheritgenericparameter.nim(37, 15) Error: Cannot inherit from: 'int'
|
||||
tinheritgenericparameter.nim(37, 15) Error: Cannot inherit from: 'int'
|
||||
tinheritgenericparameter.nim(37, 23) Error: object constructor needs an object type [proxy]
|
||||
tinheritgenericparameter.nim(37, 23) Error: object constructor needs an object type [error]
|
||||
tinheritgenericparameter.nim(37, 23) Error: expression '' has no type (or is ambiguous)
|
||||
'''
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user