mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-19 07:21:19 +00:00
integrate the logic of fixupProcType into ReplaceTypeVars
This commit is contained in:
@@ -351,9 +351,12 @@ const
|
||||
tyPureObject* = tyTuple
|
||||
GcTypeKinds* = {tyRef, tySequence, tyString}
|
||||
tyError* = tyProxy # as an errornous node should match everything
|
||||
|
||||
tyTypeClasses* = {tyTypeClass, tyBuiltInTypeClass, tyCompositeTypeClass,
|
||||
tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
|
||||
|
||||
tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyStatic, tyExpr} + tyTypeClasses
|
||||
|
||||
type
|
||||
TTypeKinds* = set[TTypeKind]
|
||||
|
||||
@@ -397,7 +400,8 @@ type
|
||||
tfNeedsInit, # type constains a "not nil" constraint somewhere or some
|
||||
# other type so that it requires inititalization
|
||||
tfHasShared, # type constains a "shared" constraint modifier somewhere
|
||||
tfHasMeta, # type has "typedesc" or "expr" somewhere; or uses '|'
|
||||
tfHasMeta, # type contains "wildcard" sub-types such as generic params
|
||||
# or other type classes
|
||||
tfHasGCedMem, # type contains GC'ed memory
|
||||
tfGenericTypeParam
|
||||
tfHasStatic
|
||||
@@ -777,9 +781,11 @@ const
|
||||
|
||||
GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody,
|
||||
tyGenericParam}
|
||||
|
||||
StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray,
|
||||
tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray,
|
||||
tyVarargs}
|
||||
|
||||
ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in::
|
||||
# var x = expr
|
||||
tyBool, tyChar, tyEnum, tyArray, tyObject,
|
||||
@@ -1222,7 +1228,7 @@ proc newSons(father: PNode, length: int) =
|
||||
proc propagateToOwner*(owner, elem: PType) =
|
||||
const HaveTheirOwnEmpty = {tySequence, tySet}
|
||||
owner.flags = owner.flags + (elem.flags * {tfHasShared, tfHasMeta,
|
||||
tfHasGCedMem})
|
||||
tfHasStatic, tfHasGCedMem})
|
||||
if tfNotNil in elem.flags:
|
||||
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}:
|
||||
owner.flags.incl tfNotNil
|
||||
@@ -1235,10 +1241,14 @@ proc propagateToOwner*(owner, elem: PType) =
|
||||
|
||||
if tfShared in elem.flags:
|
||||
owner.flags.incl tfHasShared
|
||||
|
||||
if elem.kind in {tyExpr, tyStatic, tyTypeDesc}:
|
||||
|
||||
if elem.kind in tyMetaTypes:
|
||||
owner.flags.incl tfHasMeta
|
||||
elif elem.kind in {tyString, tyRef, tySequence} or
|
||||
|
||||
if elem.kind == tyStatic:
|
||||
owner.flags.incl tfHasStatic
|
||||
|
||||
if elem.kind in {tyString, tyRef, tySequence} or
|
||||
elem.kind == tyProc and elem.callConv == ccClosure:
|
||||
owner.flags.incl tfHasGCedMem
|
||||
|
||||
|
||||
@@ -217,23 +217,21 @@ proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
|
||||
proc makeAndType*(c: PContext, t1, t2: PType): PType =
|
||||
result = newTypeS(tyAnd, c)
|
||||
result.sons = @[t1, t2]
|
||||
result.flags.incl tfHasMeta
|
||||
if tfHasStatic in t1.flags or tfHasStatic in t2.flags:
|
||||
result.flags.incl tfHasStatic
|
||||
propagateToOwner(result, t1)
|
||||
propagateToOwner(result, t2)
|
||||
|
||||
proc makeOrType*(c: PContext, t1, t2: PType): PType =
|
||||
result = newTypeS(tyOr, c)
|
||||
result.sons = @[t1, t2]
|
||||
result.flags.incl tfHasMeta
|
||||
if tfHasStatic in t1.flags or tfHasStatic in t2.flags:
|
||||
result.flags.incl tfHasStatic
|
||||
propagateToOwner(result, t1)
|
||||
propagateToOwner(result, t2)
|
||||
|
||||
proc makeNotType*(c: PContext, t1: PType): PType =
|
||||
result = newTypeS(tyNot, c)
|
||||
result.sons = @[t1]
|
||||
result.flags.incl tfHasMeta
|
||||
propagateToOwner(result, t1)
|
||||
|
||||
proc newTypeS(kind: TTypeKind, c: PContext): PType =
|
||||
proc newTypeS(kind: TTypeKind, c: PContext): PType =
|
||||
result = newType(kind, getCurrOwner())
|
||||
|
||||
proc newTypeWithSons*(c: PContext, kind: TTypeKind,
|
||||
|
||||
@@ -310,7 +310,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
var entry = TInstantiation.new
|
||||
entry.sym = result
|
||||
instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[])
|
||||
result.typ = fixupProcType(c, fn.typ, entry[])
|
||||
# let t1 = fixupProcType(c, fn.typ, entry[])
|
||||
result.typ = generateTypeInstance(c, pt, info, fn.typ)
|
||||
n.sons[genericParamsPos] = ast.emptyNode
|
||||
var oldPrc = GenericCacheGet(fn, entry[])
|
||||
if oldPrc == nil:
|
||||
|
||||
@@ -591,6 +591,10 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||
|
||||
let typedescId = getIdent"typedesc"
|
||||
|
||||
template shouldHaveMeta(t) =
|
||||
InternalAssert tfHasMeta in result.lastSon.flags
|
||||
# result.lastSon.flags.incl tfHasMeta
|
||||
|
||||
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
paramType: PType, paramName: string,
|
||||
info: TLineInfo, anon = false): PType =
|
||||
@@ -615,7 +619,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
s.position = genericParams.len
|
||||
genericParams.addSon(newSymNode(s))
|
||||
result = typeClass
|
||||
|
||||
|
||||
# XXX: There are codegen errors if this is turned into a nested proc
|
||||
template liftingWalk(typ: PType, anonFlag = false): expr =
|
||||
liftParamType(c, procKind, genericParams, typ, paramName, info, anonFlag)
|
||||
@@ -674,24 +678,22 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
|
||||
result = instGenericContainer(c, paramType.sym.info, result,
|
||||
allowMetaTypes = true)
|
||||
result.lastSon.flags.incl tfHasMeta
|
||||
result.lastSon.shouldHaveMeta
|
||||
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
|
||||
result = addImplicitGeneric(result)
|
||||
|
||||
of tyGenericInst:
|
||||
# XXX: It should be possible to set tfHasMeta in semtypinst, when the
|
||||
# instance was generated
|
||||
for i in 1 .. (paramType.sons.len - 2):
|
||||
var lifted = liftingWalk(paramType.sons[i])
|
||||
if lifted != nil:
|
||||
paramType.sons[i] = lifted
|
||||
result = paramType
|
||||
paramType.lastSon.flags.incl tfHasMeta
|
||||
result.lastSon.shouldHaveMeta
|
||||
|
||||
let liftBody = liftingWalk(paramType.lastSon)
|
||||
if liftBody != nil:
|
||||
result = liftBody
|
||||
result.flags.incl tfHasMeta
|
||||
result.shouldHaveMeta
|
||||
|
||||
of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
|
||||
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
|
||||
@@ -884,7 +886,10 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
|
||||
when oUseLateInstantiation:
|
||||
result = lateInstantiateGeneric(c, result, n.info)
|
||||
else:
|
||||
result = instGenericContainer(c, n, result)
|
||||
result = instGenericContainer(c, n.info, result,
|
||||
allowMetaTypes = not isConcrete)
|
||||
if not isConcrete and result.kind == tyGenericInst:
|
||||
result.lastSon.shouldHaveMeta
|
||||
|
||||
proc semTypeExpr(c: PContext, n: PNode): PType =
|
||||
var n = semExprWithType(c, n, {efDetermineType})
|
||||
|
||||
@@ -135,7 +135,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
|
||||
proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
|
||||
result = PType(idTableGet(cl.typeMap, t))
|
||||
if result == nil:
|
||||
if cl.allowMetaTypes: return
|
||||
if cl.allowMetaTypes or tfRetType in t.flags: return
|
||||
LocalError(t.sym.info, errCannotInstantiateX, typeToString(t))
|
||||
result = errorType(cl.c)
|
||||
elif result.kind == tyGenericParam and not cl.allowMetaTypes:
|
||||
@@ -184,7 +184,7 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType =
|
||||
# if one of the params is not concrete, we cannot do anything
|
||||
# but we already raised an error!
|
||||
rawAddSon(result, header.sons[i])
|
||||
|
||||
|
||||
var newbody = ReplaceTypeVarsT(cl, lastSon(body))
|
||||
newbody.flags = newbody.flags + t.flags + body.flags
|
||||
result.flags = result.flags + newbody.flags
|
||||
@@ -205,20 +205,29 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
|
||||
return if s != nil: s else: t
|
||||
|
||||
case t.kind
|
||||
of tyTypeClass, tyBuiltInTypeClass: nil
|
||||
of tyGenericParam, tyCompositeTypeClass:
|
||||
result = lookupTypeVar(cl, t)
|
||||
if result == nil: return t
|
||||
if result.kind == tyGenericInvokation:
|
||||
result = handleGenericInvokation(cl, result)
|
||||
of tyGenericInvokation:
|
||||
of tyGenericParam, tyTypeClasses:
|
||||
let lookup = lookupTypeVar(cl, t)
|
||||
if lookup != nil:
|
||||
result = lookup
|
||||
if result.kind == tyGenericInvokation:
|
||||
result = handleGenericInvokation(cl, result)
|
||||
of tyGenericInvokation:
|
||||
result = handleGenericInvokation(cl, t)
|
||||
of tyGenericBody:
|
||||
InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody")
|
||||
InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody" )
|
||||
result = ReplaceTypeVarsT(cl, lastSon(t))
|
||||
of tyInt:
|
||||
result = skipIntLit(t)
|
||||
# XXX now there are also float literals
|
||||
of tyTypeDesc:
|
||||
let lookup = PType(idTableGet(cl.typeMap, t)) # lookupTypeVar(cl, t)
|
||||
if lookup != nil:
|
||||
result = lookup
|
||||
if tfUnresolved in t.flags: result = result.base
|
||||
of tyGenericInst:
|
||||
result = copyType(t, t.owner, true)
|
||||
for i in 1 .. <result.sonsLen:
|
||||
result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i])
|
||||
else:
|
||||
if t.kind == tyArray:
|
||||
let idxt = t.sons[0]
|
||||
@@ -238,15 +247,18 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
|
||||
if result.kind == tyProc and result.sons[0] != nil:
|
||||
if result.sons[0].kind == tyEmpty:
|
||||
result.sons[0] = nil
|
||||
|
||||
proc generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode,
|
||||
t: PType): PType =
|
||||
|
||||
proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
|
||||
t: PType): PType =
|
||||
var cl: TReplTypeVars
|
||||
InitIdTable(cl.symMap)
|
||||
copyIdTable(cl.typeMap, pt)
|
||||
cl.info = arg.info
|
||||
cl.info = info
|
||||
cl.c = p
|
||||
pushInfoContext(arg.info)
|
||||
pushInfoContext(info)
|
||||
result = ReplaceTypeVarsT(cl, t)
|
||||
popInfoContext()
|
||||
|
||||
template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode,
|
||||
t: PType): expr =
|
||||
generateTypeInstance(p, pt, arg.info, t)
|
||||
|
||||
@@ -418,7 +418,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
if a.kind == tyGenericInst and
|
||||
skipTypes(f, {tyVar}).kind notin {
|
||||
tyGenericBody, tyGenericInvokation,
|
||||
tyGenericParam} + tyTypeClasses:
|
||||
tyGenericInst, tyGenericParam} + tyTypeClasses:
|
||||
return typeRel(c, f, lastSon(a))
|
||||
|
||||
template bindingRet(res) =
|
||||
@@ -649,7 +649,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
if a.kind == tyEmpty: result = isEqual
|
||||
|
||||
of tyGenericInst:
|
||||
result = typeRel(c, lastSon(f), a)
|
||||
if a.kind == tyGenericInst:
|
||||
if a.base != f.base: return isNone
|
||||
for i in 1 .. f.sonsLen-2:
|
||||
result = typeRel(c, f.sons[i], a.sons[i])
|
||||
if result == isNone: return
|
||||
result = isGeneric
|
||||
else:
|
||||
result = typeRel(c, lastSon(f), a)
|
||||
|
||||
of tyGenericBody:
|
||||
if a.kind == tyGenericInst and a.sons[0] == f:
|
||||
@@ -937,9 +944,9 @@ proc ParamTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||
var
|
||||
fMaybeStatic = f.skipTypes({tyDistinct})
|
||||
arg = argSemantized
|
||||
c = m.c
|
||||
argType = argType
|
||||
|
||||
c = m.c
|
||||
|
||||
if tfHasStatic in fMaybeStatic.flags:
|
||||
# XXX: When implicit statics are the default
|
||||
# this will be done earlier - we just have to
|
||||
|
||||
@@ -1220,8 +1220,9 @@ proc getSize(typ: PType): biggestInt =
|
||||
result = computeSize(typ)
|
||||
if result < 0: InternalError("getSize: " & $typ.kind)
|
||||
|
||||
proc containsGenericTypeIter(t: PType, closure: PObject): bool =
|
||||
result = t.kind in GenericTypes
|
||||
proc containsGenericTypeIter(t: PType, closure: PObject): bool =
|
||||
result = t.kind in GenericTypes + tyTypeClasses +
|
||||
{tyTypeDesc, tyStatic}
|
||||
|
||||
proc containsGenericType*(t: PType): bool =
|
||||
result = iterOverType(t, containsGenericTypeIter, nil)
|
||||
|
||||
@@ -16,10 +16,10 @@ type
|
||||
TBar = tuple
|
||||
x, y: int
|
||||
|
||||
template good(e: expr) =
|
||||
template accept(e: expr) =
|
||||
static: assert(compiles(e))
|
||||
|
||||
template bad(e: expr) =
|
||||
template reject(e: expr) =
|
||||
static: assert(not compiles(e))
|
||||
|
||||
proc genericParamRepeated[T: typedesc](a: T, b: T) =
|
||||
@@ -27,61 +27,61 @@ proc genericParamRepeated[T: typedesc](a: T, b: T) =
|
||||
echo a.name
|
||||
echo b.name
|
||||
|
||||
good(genericParamRepeated(int, int))
|
||||
good(genericParamRepeated(float, float))
|
||||
accept genericParamRepeated(int, int)
|
||||
accept genericParamRepeated(float, float)
|
||||
|
||||
bad(genericParamRepeated(string, int))
|
||||
bad(genericParamRepeated(int, float))
|
||||
reject genericParamRepeated(string, int)
|
||||
reject genericParamRepeated(int, float)
|
||||
|
||||
proc genericParamOnce[T: typedesc](a, b: T) =
|
||||
static:
|
||||
echo a.name
|
||||
echo b.name
|
||||
|
||||
good(genericParamOnce(int, int))
|
||||
good(genericParamOnce(TFoo, TFoo))
|
||||
accept genericParamOnce(int, int)
|
||||
accept genericParamOnce(TFoo, TFoo)
|
||||
|
||||
bad(genericParamOnce(string, int))
|
||||
bad(genericParamOnce(TFoo, float))
|
||||
reject genericParamOnce(string, int)
|
||||
reject genericParamOnce(TFoo, float)
|
||||
|
||||
proc typePairs(A, B: type1; C, D: type2) = nil
|
||||
|
||||
good(typePairs(int, int, TFoo, TFOO))
|
||||
good(typePairs(TBAR, TBar, TBAR, TBAR))
|
||||
good(typePairs(int, int, string, string))
|
||||
accept typePairs(int, int, TFoo, TFOO)
|
||||
accept typePairs(TBAR, TBar, TBAR, TBAR)
|
||||
accept typePairs(int, int, string, string)
|
||||
|
||||
bad(typePairs(TBAR, TBar, TBar, TFoo))
|
||||
bad(typePairs(string, int, TBAR, TBAR))
|
||||
reject typePairs(TBAR, TBar, TBar, TFoo)
|
||||
reject typePairs(string, int, TBAR, TBAR)
|
||||
|
||||
proc typePairs2[T: typedesc, U: typedesc](A, B: T; C, D: U) = nil
|
||||
|
||||
good(typePairs2(int, int, TFoo, TFOO))
|
||||
good(typePairs2(TBAR, TBar, TBAR, TBAR))
|
||||
good(typePairs2(int, int, string, string))
|
||||
accept typePairs2(int, int, TFoo, TFOO)
|
||||
accept typePairs2(TBAR, TBar, TBAR, TBAR)
|
||||
accept typePairs2(int, int, string, string)
|
||||
|
||||
bad(typePairs2(TBAR, TBar, TBar, TFoo))
|
||||
bad(typePairs2(string, int, TBAR, TBAR))
|
||||
reject typePairs2(TBAR, TBar, TBar, TFoo)
|
||||
reject typePairs2(string, int, TBAR, TBAR)
|
||||
|
||||
proc dontBind(a: typedesc, b: typedesc) =
|
||||
static:
|
||||
echo a.name
|
||||
echo b.name
|
||||
|
||||
good(dontBind(int, float))
|
||||
good(dontBind(TFoo, TFoo))
|
||||
accept dontBind(int, float)
|
||||
accept dontBind(TFoo, TFoo)
|
||||
|
||||
proc dontBind2(a, b: typedesc) = nil
|
||||
|
||||
good(dontBind2(int, float))
|
||||
good(dontBind2(TBar, int))
|
||||
accept dontBind2(int, float)
|
||||
accept dontBind2(TBar, int)
|
||||
|
||||
proc bindArg(T: typedesc, U: typedesc, a, b: T, c, d: U) = nil
|
||||
|
||||
good(bindArg(int, string, 10, 20, "test", "nest"))
|
||||
good(bindArg(int, int, 10, 20, 30, 40))
|
||||
accept bindArg(int, string, 10, 20, "test", "nest")
|
||||
accept bindArg(int, int, 10, 20, 30, 40)
|
||||
|
||||
bad(bindArg(int, string, 10, "test", "test", "nest"))
|
||||
bad(bindArg(int, int, 10, 20, 30, "test"))
|
||||
bad(bindArg(int, string, 10.0, 20, "test", "nest"))
|
||||
bad(bindArg(int, string, "test", "nest", 10, 20))
|
||||
reject bindArg(int, string, 10, "test", "test", "nest")
|
||||
reject bindArg(int, int, 10, 20, 30, "test")
|
||||
reject bindArg(int, string, 10.0, 20, "test", "nest")
|
||||
reject bindArg(int, string, "test", "nest", 10, 20)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
file: "system.nim"
|
||||
line: 696
|
||||
line: 698
|
||||
errormsg: "type mismatch"
|
||||
"""
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ discard """
|
||||
WARNING: false first asseertion from bar
|
||||
ERROR: false second assertion from bar
|
||||
-1
|
||||
tests/run/tfailedassert.nim:40 false assertion from foo
|
||||
tests/run/tfailedassert.nim:27 false assertion from foo
|
||||
'''
|
||||
"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user