mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-17 06:21:18 +00:00
introduce tyInferred for the unbound concept type params
* Why is tyInferred needed? The bindings in TCandidate are capable of inferring types within a single call expression. In concepts, we need to infer types in the same way, but across the whole body of the concept. Previously, once a concept type param was inferred, it was destructively mutated using t.assignType, but this proved to be problematic in the presence of overloads, because the bindings established while a non-matching overload is tested must be reverted/forgotten. tyInferred offers a non-destructive way to keep track of the inference progress. While introducing new types usually requires a lot of code paths in the compiler to updated, currently tyInferred is only a short-lived type within the concept body pass and it's unlikely to introduce breakage elsewhere in the compiler.
This commit is contained in:
@@ -354,44 +354,52 @@ type
|
|||||||
tyUnused,
|
tyUnused,
|
||||||
tyProxy # used as errornous type (for idetools)
|
tyProxy # used as errornous type (for idetools)
|
||||||
|
|
||||||
tyBuiltInTypeClass #\
|
tyBuiltInTypeClass
|
||||||
# Type such as the catch-all object, tuple, seq, etc
|
# Type such as the catch-all object, tuple, seq, etc
|
||||||
|
|
||||||
tyUserTypeClass #\
|
tyUserTypeClass
|
||||||
# the body of a user-defined type class
|
# the body of a user-defined type class
|
||||||
|
|
||||||
tyUserTypeClassInst #\
|
tyUserTypeClassInst
|
||||||
# Instance of a parametric user-defined type class.
|
# Instance of a parametric user-defined type class.
|
||||||
# Structured similarly to tyGenericInst.
|
# Structured similarly to tyGenericInst.
|
||||||
# tyGenericInst represents concrete types, while
|
# tyGenericInst represents concrete types, while
|
||||||
# this is still a "generic param" that will bind types
|
# this is still a "generic param" that will bind types
|
||||||
# and resolves them during sigmatch and instantiation.
|
# and resolves them during sigmatch and instantiation.
|
||||||
|
|
||||||
tyCompositeTypeClass #\
|
tyCompositeTypeClass
|
||||||
# Type such as seq[Number]
|
# Type such as seq[Number]
|
||||||
# The notes for tyUserTypeClassInst apply here as well
|
# The notes for tyUserTypeClassInst apply here as well
|
||||||
# sons[0]: the original expression used by the user.
|
# sons[0]: the original expression used by the user.
|
||||||
# sons[1]: fully expanded and instantiated meta type
|
# sons[1]: fully expanded and instantiated meta type
|
||||||
# (potentially following aliases)
|
# (potentially following aliases)
|
||||||
|
|
||||||
tyAnd, tyOr, tyNot #\
|
tyInferred
|
||||||
|
# In the initial state `base` stores a type class constraining
|
||||||
|
# the types that can be inferred. After a candidate type is
|
||||||
|
# selected, it's stored in `lastSon`. Between `base` and `lastSon`
|
||||||
|
# there may be 0, 2 or more types that were also considered as
|
||||||
|
# possible candidates in the inference process (i.e. lastSon will
|
||||||
|
# be updated to store a type best conforming to all candidates)
|
||||||
|
|
||||||
|
tyAnd, tyOr, tyNot
|
||||||
# boolean type classes such as `string|int`,`not seq`,
|
# boolean type classes such as `string|int`,`not seq`,
|
||||||
# `Sortable and Enumable`, etc
|
# `Sortable and Enumable`, etc
|
||||||
|
|
||||||
tyAnything #\
|
tyAnything
|
||||||
# a type class matching any type
|
# a type class matching any type
|
||||||
|
|
||||||
tyStatic #\
|
tyStatic
|
||||||
# a value known at compile type (the underlying type is .base)
|
# a value known at compile type (the underlying type is .base)
|
||||||
|
|
||||||
tyFromExpr #\
|
tyFromExpr
|
||||||
# This is a type representing an expression that depends
|
# This is a type representing an expression that depends
|
||||||
# on generic parameters (the expression is stored in t.n)
|
# on generic parameters (the expression is stored in t.n)
|
||||||
# It will be converted to a real type only during generic
|
# It will be converted to a real type only during generic
|
||||||
# instantiation and prior to this it has the potential to
|
# instantiation and prior to this it has the potential to
|
||||||
# be any type.
|
# be any type.
|
||||||
|
|
||||||
tyFieldAccessor #\
|
tyFieldAccessor
|
||||||
# Expressions such as Type.field (valid in contexts such
|
# Expressions such as Type.field (valid in contexts such
|
||||||
# as the `is` operator and magics like `high` and `low`).
|
# as the `is` operator and magics like `high` and `low`).
|
||||||
# Could be lifted to a single argument proc returning the
|
# Could be lifted to a single argument proc returning the
|
||||||
@@ -400,7 +408,7 @@ type
|
|||||||
# sons[1]: field type
|
# sons[1]: field type
|
||||||
# .n: nkDotExpr storing the field name
|
# .n: nkDotExpr storing the field name
|
||||||
|
|
||||||
tyVoid #\
|
tyVoid
|
||||||
# now different from tyEmpty, hurray!
|
# now different from tyEmpty, hurray!
|
||||||
|
|
||||||
static:
|
static:
|
||||||
@@ -482,7 +490,6 @@ type
|
|||||||
tfHasStatic
|
tfHasStatic
|
||||||
tfGenericTypeParam
|
tfGenericTypeParam
|
||||||
tfImplicitTypeParam
|
tfImplicitTypeParam
|
||||||
tfInferrableTypeClassTypeParam
|
|
||||||
tfWildcard # consider a proc like foo[T, I](x: Type[T, I])
|
tfWildcard # consider a proc like foo[T, I](x: Type[T, I])
|
||||||
# T and I here can bind to both typedesc and static types
|
# T and I here can bind to both typedesc and static types
|
||||||
# before this is determined, we'll consider them to be a
|
# before this is determined, we'll consider them to be a
|
||||||
@@ -1037,6 +1044,9 @@ proc newStrNode*(kind: TNodeKind, strVal: string): PNode =
|
|||||||
result = newNode(kind)
|
result = newNode(kind)
|
||||||
result.strVal = strVal
|
result.strVal = strVal
|
||||||
|
|
||||||
|
template previouslyInferred*(t: PType): PType =
|
||||||
|
if t.sons.len > 1: t.lastSon else: nil
|
||||||
|
|
||||||
proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
|
proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
|
||||||
info: TLineInfo): PSym =
|
info: TLineInfo): PSym =
|
||||||
# generates a symbol and initializes the hash field too
|
# generates a symbol and initializes the hash field too
|
||||||
@@ -1279,6 +1289,8 @@ proc copyType*(t: PType, owner: PSym, keepId: bool): PType =
|
|||||||
when debugIds: registerId(result)
|
when debugIds: registerId(result)
|
||||||
result.sym = t.sym # backend-info should not be copied
|
result.sym = t.sym # backend-info should not be copied
|
||||||
|
|
||||||
|
proc exactReplica*(t: PType): PType = copyType(t, t.owner, true)
|
||||||
|
|
||||||
proc copySym*(s: PSym, keepId: bool = false): PSym =
|
proc copySym*(s: PSym, keepId: bool = false): PSym =
|
||||||
result = newSym(s.kind, s.name, s.owner, s.info)
|
result = newSym(s.kind, s.name, s.owner, s.info)
|
||||||
#result.ast = nil # BUGFIX; was: s.ast which made problems
|
#result.ast = nil # BUGFIX; was: s.ast which made problems
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ proc mapType(typ: PType): TCTypeKind =
|
|||||||
of tyOpenArray, tyArray, tyVarargs: result = ctArray
|
of tyOpenArray, tyArray, tyVarargs: result = ctArray
|
||||||
of tyObject, tyTuple: result = ctStruct
|
of tyObject, tyTuple: result = ctStruct
|
||||||
of tyGenericBody, tyGenericInst, tyGenericParam, tyDistinct, tyOrdinal,
|
of tyGenericBody, tyGenericInst, tyGenericParam, tyDistinct, tyOrdinal,
|
||||||
tyTypeDesc, tyAlias:
|
tyTypeDesc, tyAlias, tyInferred:
|
||||||
result = mapType(lastSon(typ))
|
result = mapType(lastSon(typ))
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
if firstOrd(typ) < 0:
|
if firstOrd(typ) < 0:
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ proc getUniqueType*(key: PType): PType =
|
|||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
if key.deepCopy != nil: result = key
|
if key.deepCopy != nil: result = key
|
||||||
else: result = getUniqueType(lastSon(key))
|
else: result = getUniqueType(lastSon(key))
|
||||||
of tyGenericInst, tyOrdinal, tyStatic, tyAlias:
|
of tyGenericInst, tyOrdinal, tyStatic, tyAlias, tyInferred:
|
||||||
result = getUniqueType(lastSon(key))
|
result = getUniqueType(lastSon(key))
|
||||||
#let obj = lastSon(key)
|
#let obj = lastSon(key)
|
||||||
#if obj.sym != nil and obj.sym.name.s == "TOption":
|
#if obj.sym != nil and obj.sym.name.s == "TOption":
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ proc mapType(typ: PType): TJSTypeKind =
|
|||||||
tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
|
tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
|
||||||
tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid, tyAlias:
|
tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid, tyAlias:
|
||||||
result = etyNone
|
result = etyNone
|
||||||
|
of tyInferred:
|
||||||
|
result = mapType(typ.lastSon)
|
||||||
of tyStatic:
|
of tyStatic:
|
||||||
if t.n != nil: result = mapType(lastSon t)
|
if t.n != nil: result = mapType(lastSon t)
|
||||||
else: result = etyNone
|
else: result = etyNone
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
|||||||
tyGenericParam, tyGenericBody, tyNil, tyExpr, tyStmt,
|
tyGenericParam, tyGenericBody, tyNil, tyExpr, tyStmt,
|
||||||
tyTypeDesc, tyGenericInvocation, tyForward:
|
tyTypeDesc, tyGenericInvocation, tyForward:
|
||||||
internalError(c.info, "assignment requested for type: " & typeToString(t))
|
internalError(c.info, "assignment requested for type: " & typeToString(t))
|
||||||
of tyOrdinal, tyRange,
|
of tyOrdinal, tyRange, tyInferred,
|
||||||
tyGenericInst, tyFieldAccessor, tyStatic, tyVar, tyAlias:
|
tyGenericInst, tyFieldAccessor, tyStatic, tyVar, tyAlias:
|
||||||
liftBodyAux(c, lastSon(t), body, x, y)
|
liftBodyAux(c, lastSon(t), body, x, y)
|
||||||
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("liftBodyAux")
|
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("liftBodyAux")
|
||||||
|
|||||||
@@ -323,7 +323,6 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
|
|||||||
maybeLiftType(t2, c, n.info)
|
maybeLiftType(t2, c, n.info)
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
initCandidate(c, m, t2)
|
initCandidate(c, m, t2)
|
||||||
discard inferTypeClassParam(m, t1, rhsOrigType)
|
|
||||||
let match = typeRel(m, t2, t1) >= isSubtype # isNone
|
let match = typeRel(m, t2, t1) >= isSubtype # isNone
|
||||||
result = newIntNode(nkIntLit, ord(match))
|
result = newIntNode(nkIntLit, ord(match))
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ type
|
|||||||
# a distrinct type
|
# a distrinct type
|
||||||
typedescMatched*: bool
|
typedescMatched*: bool
|
||||||
isNoCall*: bool # misused for generic type instantiations C[T]
|
isNoCall*: bool # misused for generic type instantiations C[T]
|
||||||
|
inferredTypes: seq[PType] # inferred types during the current signature
|
||||||
|
# matching. they will be reset if the matching
|
||||||
|
# is not successful. may replace the bindings
|
||||||
|
# table in the future.
|
||||||
mutabilityProblem*: uint8 # tyVar mismatch
|
mutabilityProblem*: uint8 # tyVar mismatch
|
||||||
inheritancePenalty: int # to prefer closest father object type
|
inheritancePenalty: int # to prefer closest father object type
|
||||||
errors*: CandidateErrors # additional clarifications to be displayed to the
|
errors*: CandidateErrors # additional clarifications to be displayed to the
|
||||||
@@ -600,17 +604,17 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
|||||||
case typ.kind
|
case typ.kind
|
||||||
of tyStatic:
|
of tyStatic:
|
||||||
param = paramSym skConst
|
param = paramSym skConst
|
||||||
param.typ = typ.base
|
param.typ = typ.exactReplica
|
||||||
param.ast = typ.n
|
param.ast = typ.n
|
||||||
of tyUnknown:
|
of tyUnknown:
|
||||||
param = paramSym skVar
|
param = paramSym skVar
|
||||||
param.typ = typ
|
param.typ = typ.exactReplica
|
||||||
else:
|
else:
|
||||||
param = paramSym skType
|
param = paramSym skType
|
||||||
param.typ = makeTypeDesc(c, typ)
|
param.typ = if typ.isMetaType:
|
||||||
|
c.newTypeWithSons(tyInferred, @[typ])
|
||||||
if typ.isMetaType:
|
else:
|
||||||
param.typ.flags.incl tfInferrableTypeClassTypeParam
|
makeTypeDesc(c, typ)
|
||||||
|
|
||||||
addDecl(c, param)
|
addDecl(c, param)
|
||||||
typeParams.safeAdd((param, typ))
|
typeParams.safeAdd((param, typ))
|
||||||
@@ -718,8 +722,51 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||||||
|
|
||||||
assert(aOrig != nil)
|
assert(aOrig != nil)
|
||||||
|
|
||||||
|
var
|
||||||
|
useTypeLoweringRuleInTypeClass = c.c.inTypeClass > 0 and
|
||||||
|
not c.isNoCall and
|
||||||
|
f.kind != tyTypeDesc
|
||||||
|
|
||||||
|
aOrig = if useTypeLoweringRuleInTypeClass:
|
||||||
|
aOrig.skipTypes({tyTypeDesc, tyFieldAccessor})
|
||||||
|
else:
|
||||||
|
aOrig
|
||||||
|
|
||||||
|
if aOrig.kind == tyInferred:
|
||||||
|
# echo "INFER A"
|
||||||
|
# debug f
|
||||||
|
# debug aOrig
|
||||||
|
let prev = aOrig.previouslyInferred
|
||||||
|
if prev != nil:
|
||||||
|
return typeRel(c, f, prev)
|
||||||
|
else:
|
||||||
|
var candidate = f
|
||||||
|
|
||||||
|
case f.kind
|
||||||
|
of tyGenericParam:
|
||||||
|
var prev = PType(idTableGet(c.bindings, f))
|
||||||
|
if prev != nil: candidate = prev
|
||||||
|
of tyFromExpr:
|
||||||
|
let computedType = tryResolvingStaticExpr(c, f.n).typ
|
||||||
|
case computedType.kind
|
||||||
|
of tyTypeDesc:
|
||||||
|
candidate = computedType.base
|
||||||
|
of tyStatic:
|
||||||
|
candidate = computedType
|
||||||
|
else:
|
||||||
|
localError(f.n.info, errTypeExpected)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
|
result = typeRel(c, aOrig.base, candidate)
|
||||||
|
if result != isNone:
|
||||||
|
c.inferredTypes.safeAdd aOrig
|
||||||
|
aOrig.sons.add candidate
|
||||||
|
result = isEqual
|
||||||
|
return
|
||||||
|
|
||||||
# var and static arguments match regular modifier-free types
|
# var and static arguments match regular modifier-free types
|
||||||
let a = aOrig.skipTypes({tyStatic, tyVar}).maybeSkipDistinct(c.calleeSym)
|
var a = aOrig.skipTypes({tyStatic, tyVar}).maybeSkipDistinct(c.calleeSym)
|
||||||
# XXX: Theoretically, maybeSkipDistinct could be called before we even
|
# XXX: Theoretically, maybeSkipDistinct could be called before we even
|
||||||
# start the param matching process. This could be done in `prepareOperand`
|
# start the param matching process. This could be done in `prepareOperand`
|
||||||
# for example, but unfortunately `prepareOperand` is not called in certain
|
# for example, but unfortunately `prepareOperand` is not called in certain
|
||||||
@@ -1258,6 +1305,20 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
|||||||
# XXX endless recursion?
|
# XXX endless recursion?
|
||||||
#result = typeRel(c, prev, aOrig)
|
#result = typeRel(c, prev, aOrig)
|
||||||
result = isNone
|
result = isNone
|
||||||
|
|
||||||
|
of tyInferred:
|
||||||
|
# echo "INFER F"
|
||||||
|
# debug f
|
||||||
|
# debug a
|
||||||
|
let prev = f.previouslyInferred
|
||||||
|
if prev != nil:
|
||||||
|
result = typeRel(c, prev, a)
|
||||||
|
else:
|
||||||
|
result = typeRel(c, f.base, a)
|
||||||
|
if result != isNone:
|
||||||
|
c.inferredTypes.safeAdd f
|
||||||
|
f.sons.add a
|
||||||
|
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
var prev = PType(idTableGet(c.bindings, f))
|
var prev = PType(idTableGet(c.bindings, f))
|
||||||
if prev == nil:
|
if prev == nil:
|
||||||
@@ -1401,59 +1462,14 @@ proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) =
|
|||||||
of isEqual: inc(m.exactMatches)
|
of isEqual: inc(m.exactMatches)
|
||||||
of isNone: discard
|
of isNone: discard
|
||||||
|
|
||||||
proc skipToInferrableParam(tt: PType): PType =
|
proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||||
var t = tt
|
|
||||||
while t != nil:
|
|
||||||
if tfInferrableTypeClassTypeParam in t.flags:
|
|
||||||
return t
|
|
||||||
if t.sonsLen > 0 and t.kind == tyTypeDesc:
|
|
||||||
t = t.base
|
|
||||||
else:
|
|
||||||
return nil
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
proc inferTypeClassParam*(m: var TCandidate, f, a: PType): bool =
|
|
||||||
var c = m.c
|
|
||||||
if c.inTypeClass == 0: return false
|
|
||||||
|
|
||||||
var inferrableType = a.skipToInferrableParam
|
|
||||||
if inferrableType == nil: return false
|
|
||||||
|
|
||||||
var inferAs = f
|
|
||||||
|
|
||||||
case f.kind
|
|
||||||
of tyGenericParam:
|
|
||||||
var prev = PType(idTableGet(m.bindings, f))
|
|
||||||
if prev != nil: inferAs = prev
|
|
||||||
|
|
||||||
of tyFromExpr:
|
|
||||||
let computedType = tryResolvingStaticExpr(m, f.n).typ
|
|
||||||
case computedType.kind
|
|
||||||
of tyTypeDesc:
|
|
||||||
inferAs = computedType.base
|
|
||||||
of tyStatic:
|
|
||||||
inferAs = computedType
|
|
||||||
else:
|
|
||||||
localError(f.n.info, errTypeExpected)
|
|
||||||
|
|
||||||
else:
|
|
||||||
discard
|
|
||||||
|
|
||||||
inferrableType.assignType inferAs
|
|
||||||
return true
|
|
||||||
|
|
||||||
proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
|
||||||
argSemantized, argOrig: PNode): PNode =
|
argSemantized, argOrig: PNode): PNode =
|
||||||
var
|
var
|
||||||
fMaybeStatic = f.skipTypes({tyDistinct})
|
fMaybeStatic = f.skipTypes({tyDistinct})
|
||||||
arg = argSemantized
|
arg = argSemantized
|
||||||
argType = argType
|
a = a
|
||||||
c = m.c
|
c = m.c
|
||||||
|
|
||||||
if inferTypeClassParam(m, f, argType):
|
|
||||||
return argSemantized
|
|
||||||
|
|
||||||
if tfHasStatic in fMaybeStatic.flags:
|
if tfHasStatic in fMaybeStatic.flags:
|
||||||
# XXX: When implicit statics are the default
|
# XXX: When implicit statics are the default
|
||||||
# this will be done earlier - we just have to
|
# this will be done earlier - we just have to
|
||||||
@@ -1461,12 +1477,12 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
|||||||
|
|
||||||
# XXX: weaken tyGenericParam and call it tyGenericPlaceholder
|
# XXX: weaken tyGenericParam and call it tyGenericPlaceholder
|
||||||
# and finally start using tyTypedesc for generic types properly.
|
# and finally start using tyTypedesc for generic types properly.
|
||||||
if argType.kind == tyGenericParam and tfWildcard in argType.flags:
|
if a.kind == tyGenericParam and tfWildcard in a.flags:
|
||||||
argType.assignType(f)
|
a.assignType(f)
|
||||||
# put(m.bindings, f, argType)
|
# put(m.bindings, f, a)
|
||||||
return argSemantized
|
return argSemantized
|
||||||
|
|
||||||
if argType.kind == tyStatic:
|
if a.kind == tyStatic:
|
||||||
if m.callee.kind == tyGenericBody and
|
if m.callee.kind == tyGenericBody and
|
||||||
argType.n == nil and
|
argType.n == nil and
|
||||||
tfGenericTypeParam notin argType.flags:
|
tfGenericTypeParam notin argType.flags:
|
||||||
@@ -1477,20 +1493,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
|||||||
arg.typ = newTypeS(tyStatic, c)
|
arg.typ = newTypeS(tyStatic, c)
|
||||||
arg.typ.sons = @[evaluated.typ]
|
arg.typ.sons = @[evaluated.typ]
|
||||||
arg.typ.n = evaluated
|
arg.typ.n = evaluated
|
||||||
argType = arg.typ
|
a = arg.typ
|
||||||
|
|
||||||
var
|
var r = typeRel(m, f, a)
|
||||||
useTypeLoweringRuleInTypeClass = argType != nil and
|
|
||||||
c.inTypeClass > 0 and
|
|
||||||
not m.isNoCall and
|
|
||||||
f.kind != tyTypeDesc
|
|
||||||
|
|
||||||
a = if useTypeLoweringRuleInTypeClass:
|
|
||||||
argType.skipTypes({tyTypeDesc, tyFieldAccessor})
|
|
||||||
else:
|
|
||||||
argType
|
|
||||||
|
|
||||||
r = typeRel(m, f, a)
|
|
||||||
|
|
||||||
if r != isNone and m.calleeSym != nil and
|
if r != isNone and m.calleeSym != nil and
|
||||||
m.calleeSym.kind in {skMacro, skTemplate}:
|
m.calleeSym.kind in {skMacro, skTemplate}:
|
||||||
@@ -1931,6 +1936,10 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
|||||||
def = implicitConv(nkHiddenStdConv, formal.typ, def, m, c)
|
def = implicitConv(nkHiddenStdConv, formal.typ, def, m, c)
|
||||||
setSon(m.call, formal.position + 1, def)
|
setSon(m.call, formal.position + 1, def)
|
||||||
inc(f)
|
inc(f)
|
||||||
|
# forget all inferred types if the overload matching failed
|
||||||
|
if m.state == csNoMatch:
|
||||||
|
for t in m.inferredTypes:
|
||||||
|
if t.sonsLen > 1: t.sons.setLen 1
|
||||||
|
|
||||||
proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
|
|||||||
@@ -55,16 +55,17 @@ const
|
|||||||
# TODO: Remove tyTypeDesc from each abstractX and (where necessary)
|
# TODO: Remove tyTypeDesc from each abstractX and (where necessary)
|
||||||
# replace with typedescX
|
# replace with typedescX
|
||||||
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
||||||
tyTypeDesc, tyAlias}
|
tyTypeDesc, tyAlias, tyInferred}
|
||||||
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc,
|
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc,
|
||||||
tyAlias}
|
tyAlias, tyInferred}
|
||||||
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc,
|
abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc,
|
||||||
tyAlias}
|
tyAlias, tyInferred}
|
||||||
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
||||||
tyTypeDesc, tyAlias}
|
tyTypeDesc, tyAlias, tyInferred}
|
||||||
abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias}
|
abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias,
|
||||||
|
tyInferred}
|
||||||
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias}
|
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias,
|
||||||
|
tyInferred}
|
||||||
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
|
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
|
||||||
typedescPtrs* = abstractPtrs + {tyTypeDesc}
|
typedescPtrs* = abstractPtrs + {tyTypeDesc}
|
||||||
typedescInst* = abstractInst + {tyTypeDesc}
|
typedescInst* = abstractInst + {tyTypeDesc}
|
||||||
@@ -410,7 +411,7 @@ const
|
|||||||
"unused0", "unused1",
|
"unused0", "unused1",
|
||||||
"unused2", "varargs[$1]", "unused", "Error Type",
|
"unused2", "varargs[$1]", "unused", "Error Type",
|
||||||
"BuiltInTypeClass", "UserTypeClass",
|
"BuiltInTypeClass", "UserTypeClass",
|
||||||
"UserTypeClassInst", "CompositeTypeClass",
|
"UserTypeClassInst", "CompositeTypeClass", "inferred",
|
||||||
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
|
"and", "or", "not", "any", "static", "TypeFromExpr", "FieldAccessor",
|
||||||
"void"]
|
"void"]
|
||||||
|
|
||||||
@@ -476,6 +477,10 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
|||||||
of tyTuple: "tuple"
|
of tyTuple: "tuple"
|
||||||
of tyOpenArray: "openarray"
|
of tyOpenArray: "openarray"
|
||||||
else: typeToStr[t.base.kind]
|
else: typeToStr[t.base.kind]
|
||||||
|
of tyInferred:
|
||||||
|
let concrete = t.previouslyInferred
|
||||||
|
if concrete != nil: result = typeToString(concrete)
|
||||||
|
else: result = "inferred[" & typeToString(t.base) & "]"
|
||||||
of tyUserTypeClassInst:
|
of tyUserTypeClassInst:
|
||||||
let body = t.base
|
let body = t.base
|
||||||
result = body.sym.name.s & "["
|
result = body.sym.name.s & "["
|
||||||
@@ -971,7 +976,9 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
|
|||||||
result = sameTypeOrNilAux(a.sons[0], b.sons[0], c) and
|
result = sameTypeOrNilAux(a.sons[0], b.sons[0], c) and
|
||||||
sameValue(a.n.sons[0], b.n.sons[0]) and
|
sameValue(a.n.sons[0], b.n.sons[0]) and
|
||||||
sameValue(a.n.sons[1], b.n.sons[1])
|
sameValue(a.n.sons[1], b.n.sons[1])
|
||||||
of tyGenericInst, tyAlias: discard
|
of tyGenericInst, tyAlias, tyInferred:
|
||||||
|
cycleCheck()
|
||||||
|
result = sameTypeAux(a.lastSon, b.lastSon, c)
|
||||||
of tyNone: result = false
|
of tyNone: result = false
|
||||||
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("sameFlags")
|
of tyUnused, tyUnused0, tyUnused1, tyUnused2: internalError("sameFlags")
|
||||||
|
|
||||||
@@ -1118,7 +1125,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
|
|||||||
result = nil
|
result = nil
|
||||||
of tyOrdinal:
|
of tyOrdinal:
|
||||||
if kind != skParam: result = t
|
if kind != skParam: result = t
|
||||||
of tyGenericInst, tyDistinct, tyAlias:
|
of tyGenericInst, tyDistinct, tyAlias, tyInferred:
|
||||||
result = typeAllowedAux(marker, lastSon(t), kind, flags)
|
result = typeAllowedAux(marker, lastSon(t), kind, flags)
|
||||||
of tyRange:
|
of tyRange:
|
||||||
if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin
|
if skipTypes(t.sons[0], abstractInst-{tyTypeDesc}).kind notin
|
||||||
|
|||||||
@@ -294,6 +294,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
|
|||||||
of tyOr: result = mapTypeToBracket("or", mOr, t, info)
|
of tyOr: result = mapTypeToBracket("or", mOr, t, info)
|
||||||
of tyNot: result = mapTypeToBracket("not", mNot, t, info)
|
of tyNot: result = mapTypeToBracket("not", mNot, t, info)
|
||||||
of tyAnything: result = atomicType("anything", mNone)
|
of tyAnything: result = atomicType("anything", mNone)
|
||||||
|
of tyInferred: internalAssert false
|
||||||
of tyStatic, tyFromExpr, tyFieldAccessor:
|
of tyStatic, tyFromExpr, tyFieldAccessor:
|
||||||
if inst:
|
if inst:
|
||||||
if t.n != nil: result = t.n.copyTree
|
if t.n != nil: result = t.n.copyTree
|
||||||
|
|||||||
Reference in New Issue
Block a user