integrate the logic of fixupProcType into ReplaceTypeVars

This commit is contained in:
Zahary Karadjov 2013-12-29 16:08:33 +02:00
commit 72291875bf
10 changed files with 108 additions and 74 deletions

View file

@ -351,9 +351,12 @@ const
tyPureObject* = tyTuple tyPureObject* = tyTuple
GcTypeKinds* = {tyRef, tySequence, tyString} GcTypeKinds* = {tyRef, tySequence, tyString}
tyError* = tyProxy # as an errornous node should match everything tyError* = tyProxy # as an errornous node should match everything
tyTypeClasses* = {tyTypeClass, tyBuiltInTypeClass, tyCompositeTypeClass, tyTypeClasses* = {tyTypeClass, tyBuiltInTypeClass, tyCompositeTypeClass,
tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything} tyParametricTypeClass, tyAnd, tyOr, tyNot, tyAnything}
tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyStatic, tyExpr} + tyTypeClasses
type type
TTypeKinds* = set[TTypeKind] TTypeKinds* = set[TTypeKind]
@ -397,7 +400,8 @@ type
tfNeedsInit, # type constains a "not nil" constraint somewhere or some tfNeedsInit, # type constains a "not nil" constraint somewhere or some
# other type so that it requires inititalization # other type so that it requires inititalization
tfHasShared, # type constains a "shared" constraint modifier somewhere 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 tfHasGCedMem, # type contains GC'ed memory
tfGenericTypeParam tfGenericTypeParam
tfHasStatic tfHasStatic
@ -777,9 +781,11 @@ const
GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody, GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody,
tyGenericParam} tyGenericParam}
StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray, StructuralEquivTypes*: TTypeKinds = {tyArrayConstr, tyNil, tyTuple, tyArray,
tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray, tySet, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc, tyOpenArray,
tyVarargs} tyVarargs}
ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in:: ConcreteTypes*: TTypeKinds = { # types of the expr that may occur in::
# var x = expr # var x = expr
tyBool, tyChar, tyEnum, tyArray, tyObject, tyBool, tyChar, tyEnum, tyArray, tyObject,
@ -1222,7 +1228,7 @@ proc newSons(father: PNode, length: int) =
proc propagateToOwner*(owner, elem: PType) = proc propagateToOwner*(owner, elem: PType) =
const HaveTheirOwnEmpty = {tySequence, tySet} const HaveTheirOwnEmpty = {tySequence, tySet}
owner.flags = owner.flags + (elem.flags * {tfHasShared, tfHasMeta, owner.flags = owner.flags + (elem.flags * {tfHasShared, tfHasMeta,
tfHasGCedMem}) tfHasStatic, tfHasGCedMem})
if tfNotNil in elem.flags: if tfNotNil in elem.flags:
if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}: if owner.kind in {tyGenericInst, tyGenericBody, tyGenericInvokation}:
owner.flags.incl tfNotNil owner.flags.incl tfNotNil
@ -1236,9 +1242,13 @@ proc propagateToOwner*(owner, elem: PType) =
if tfShared in elem.flags: if tfShared in elem.flags:
owner.flags.incl tfHasShared owner.flags.incl tfHasShared
if elem.kind in {tyExpr, tyStatic, tyTypeDesc}: if elem.kind in tyMetaTypes:
owner.flags.incl tfHasMeta 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: elem.kind == tyProc and elem.callConv == ccClosure:
owner.flags.incl tfHasGCedMem owner.flags.incl tfHasGCedMem

View file

@ -217,21 +217,19 @@ proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
proc makeAndType*(c: PContext, t1, t2: PType): PType = proc makeAndType*(c: PContext, t1, t2: PType): PType =
result = newTypeS(tyAnd, c) result = newTypeS(tyAnd, c)
result.sons = @[t1, t2] result.sons = @[t1, t2]
result.flags.incl tfHasMeta propagateToOwner(result, t1)
if tfHasStatic in t1.flags or tfHasStatic in t2.flags: propagateToOwner(result, t2)
result.flags.incl tfHasStatic
proc makeOrType*(c: PContext, t1, t2: PType): PType = proc makeOrType*(c: PContext, t1, t2: PType): PType =
result = newTypeS(tyOr, c) result = newTypeS(tyOr, c)
result.sons = @[t1, t2] result.sons = @[t1, t2]
result.flags.incl tfHasMeta propagateToOwner(result, t1)
if tfHasStatic in t1.flags or tfHasStatic in t2.flags: propagateToOwner(result, t2)
result.flags.incl tfHasStatic
proc makeNotType*(c: PContext, t1: PType): PType = proc makeNotType*(c: PContext, t1: PType): PType =
result = newTypeS(tyNot, c) result = newTypeS(tyNot, c)
result.sons = @[t1] 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()) result = newType(kind, getCurrOwner())

View file

@ -310,7 +310,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
var entry = TInstantiation.new var entry = TInstantiation.new
entry.sym = result entry.sym = result
instantiateGenericParamList(c, n.sons[genericParamsPos], pt, entry[]) 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 n.sons[genericParamsPos] = ast.emptyNode
var oldPrc = GenericCacheGet(fn, entry[]) var oldPrc = GenericCacheGet(fn, entry[])
if oldPrc == nil: if oldPrc == nil:

View file

@ -591,6 +591,10 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
let typedescId = getIdent"typedesc" 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, proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
paramType: PType, paramName: string, paramType: PType, paramName: string,
info: TLineInfo, anon = false): PType = info: TLineInfo, anon = false): PType =
@ -674,24 +678,22 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true)) result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
result = instGenericContainer(c, paramType.sym.info, result, result = instGenericContainer(c, paramType.sym.info, result,
allowMetaTypes = true) allowMetaTypes = true)
result.lastSon.flags.incl tfHasMeta result.lastSon.shouldHaveMeta
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result]) result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
result = addImplicitGeneric(result) result = addImplicitGeneric(result)
of tyGenericInst: 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): for i in 1 .. (paramType.sons.len - 2):
var lifted = liftingWalk(paramType.sons[i]) var lifted = liftingWalk(paramType.sons[i])
if lifted != nil: if lifted != nil:
paramType.sons[i] = lifted paramType.sons[i] = lifted
result = paramType result = paramType
paramType.lastSon.flags.incl tfHasMeta result.lastSon.shouldHaveMeta
let liftBody = liftingWalk(paramType.lastSon) let liftBody = liftingWalk(paramType.lastSon)
if liftBody != nil: if liftBody != nil:
result = liftBody result = liftBody
result.flags.incl tfHasMeta result.shouldHaveMeta
of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot: of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true)) result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
@ -884,7 +886,10 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
when oUseLateInstantiation: when oUseLateInstantiation:
result = lateInstantiateGeneric(c, result, n.info) result = lateInstantiateGeneric(c, result, n.info)
else: 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 = proc semTypeExpr(c: PContext, n: PNode): PType =
var n = semExprWithType(c, n, {efDetermineType}) var n = semExprWithType(c, n, {efDetermineType})

View file

@ -135,7 +135,7 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType =
result = PType(idTableGet(cl.typeMap, t)) result = PType(idTableGet(cl.typeMap, t))
if result == nil: if result == nil:
if cl.allowMetaTypes: return if cl.allowMetaTypes or tfRetType in t.flags: return
LocalError(t.sym.info, errCannotInstantiateX, typeToString(t)) LocalError(t.sym.info, errCannotInstantiateX, typeToString(t))
result = errorType(cl.c) result = errorType(cl.c)
elif result.kind == tyGenericParam and not cl.allowMetaTypes: elif result.kind == tyGenericParam and not cl.allowMetaTypes:
@ -205,20 +205,29 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
return if s != nil: s else: t return if s != nil: s else: t
case t.kind case t.kind
of tyTypeClass, tyBuiltInTypeClass: nil of tyGenericParam, tyTypeClasses:
of tyGenericParam, tyCompositeTypeClass: let lookup = lookupTypeVar(cl, t)
result = lookupTypeVar(cl, t) if lookup != nil:
if result == nil: return t result = lookup
if result.kind == tyGenericInvokation: if result.kind == tyGenericInvokation:
result = handleGenericInvokation(cl, result) result = handleGenericInvokation(cl, result)
of tyGenericInvokation: of tyGenericInvokation:
result = handleGenericInvokation(cl, t) result = handleGenericInvokation(cl, t)
of tyGenericBody: of tyGenericBody:
InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody") InternalError(cl.info, "ReplaceTypeVarsT: tyGenericBody" )
result = ReplaceTypeVarsT(cl, lastSon(t)) result = ReplaceTypeVarsT(cl, lastSon(t))
of tyInt: of tyInt:
result = skipIntLit(t) result = skipIntLit(t)
# XXX now there are also float literals # 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: else:
if t.kind == tyArray: if t.kind == tyArray:
let idxt = t.sons[0] let idxt = t.sons[0]
@ -239,14 +248,17 @@ proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
if result.sons[0].kind == tyEmpty: if result.sons[0].kind == tyEmpty:
result.sons[0] = nil result.sons[0] = nil
proc generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode, proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
t: PType): PType = t: PType): PType =
var cl: TReplTypeVars var cl: TReplTypeVars
InitIdTable(cl.symMap) InitIdTable(cl.symMap)
copyIdTable(cl.typeMap, pt) copyIdTable(cl.typeMap, pt)
cl.info = arg.info cl.info = info
cl.c = p cl.c = p
pushInfoContext(arg.info) pushInfoContext(info)
result = ReplaceTypeVarsT(cl, t) result = ReplaceTypeVarsT(cl, t)
popInfoContext() popInfoContext()
template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode,
t: PType): expr =
generateTypeInstance(p, pt, arg.info, t)

View file

@ -418,7 +418,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if a.kind == tyGenericInst and if a.kind == tyGenericInst and
skipTypes(f, {tyVar}).kind notin { skipTypes(f, {tyVar}).kind notin {
tyGenericBody, tyGenericInvokation, tyGenericBody, tyGenericInvokation,
tyGenericParam} + tyTypeClasses: tyGenericInst, tyGenericParam} + tyTypeClasses:
return typeRel(c, f, lastSon(a)) return typeRel(c, f, lastSon(a))
template bindingRet(res) = template bindingRet(res) =
@ -649,7 +649,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
if a.kind == tyEmpty: result = isEqual if a.kind == tyEmpty: result = isEqual
of tyGenericInst: 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: of tyGenericBody:
if a.kind == tyGenericInst and a.sons[0] == f: if a.kind == tyGenericInst and a.sons[0] == f:
@ -937,8 +944,8 @@ proc ParamTypesMatchAux(m: var TCandidate, f, argType: PType,
var var
fMaybeStatic = f.skipTypes({tyDistinct}) fMaybeStatic = f.skipTypes({tyDistinct})
arg = argSemantized arg = argSemantized
c = m.c
argType = argType argType = argType
c = m.c
if tfHasStatic in fMaybeStatic.flags: if tfHasStatic in fMaybeStatic.flags:
# XXX: When implicit statics are the default # XXX: When implicit statics are the default

View file

@ -1221,7 +1221,8 @@ proc getSize(typ: PType): biggestInt =
if result < 0: InternalError("getSize: " & $typ.kind) if result < 0: InternalError("getSize: " & $typ.kind)
proc containsGenericTypeIter(t: PType, closure: PObject): bool = proc containsGenericTypeIter(t: PType, closure: PObject): bool =
result = t.kind in GenericTypes result = t.kind in GenericTypes + tyTypeClasses +
{tyTypeDesc, tyStatic}
proc containsGenericType*(t: PType): bool = proc containsGenericType*(t: PType): bool =
result = iterOverType(t, containsGenericTypeIter, nil) result = iterOverType(t, containsGenericTypeIter, nil)

View file

@ -16,10 +16,10 @@ type
TBar = tuple TBar = tuple
x, y: int x, y: int
template good(e: expr) = template accept(e: expr) =
static: assert(compiles(e)) static: assert(compiles(e))
template bad(e: expr) = template reject(e: expr) =
static: assert(not compiles(e)) static: assert(not compiles(e))
proc genericParamRepeated[T: typedesc](a: T, b: T) = proc genericParamRepeated[T: typedesc](a: T, b: T) =
@ -27,61 +27,61 @@ proc genericParamRepeated[T: typedesc](a: T, b: T) =
echo a.name echo a.name
echo b.name echo b.name
good(genericParamRepeated(int, int)) accept genericParamRepeated(int, int)
good(genericParamRepeated(float, float)) accept genericParamRepeated(float, float)
bad(genericParamRepeated(string, int)) reject genericParamRepeated(string, int)
bad(genericParamRepeated(int, float)) reject genericParamRepeated(int, float)
proc genericParamOnce[T: typedesc](a, b: T) = proc genericParamOnce[T: typedesc](a, b: T) =
static: static:
echo a.name echo a.name
echo b.name echo b.name
good(genericParamOnce(int, int)) accept genericParamOnce(int, int)
good(genericParamOnce(TFoo, TFoo)) accept genericParamOnce(TFoo, TFoo)
bad(genericParamOnce(string, int)) reject genericParamOnce(string, int)
bad(genericParamOnce(TFoo, float)) reject genericParamOnce(TFoo, float)
proc typePairs(A, B: type1; C, D: type2) = nil proc typePairs(A, B: type1; C, D: type2) = nil
good(typePairs(int, int, TFoo, TFOO)) accept typePairs(int, int, TFoo, TFOO)
good(typePairs(TBAR, TBar, TBAR, TBAR)) accept typePairs(TBAR, TBar, TBAR, TBAR)
good(typePairs(int, int, string, string)) accept typePairs(int, int, string, string)
bad(typePairs(TBAR, TBar, TBar, TFoo)) reject typePairs(TBAR, TBar, TBar, TFoo)
bad(typePairs(string, int, TBAR, TBAR)) reject typePairs(string, int, TBAR, TBAR)
proc typePairs2[T: typedesc, U: typedesc](A, B: T; C, D: U) = nil proc typePairs2[T: typedesc, U: typedesc](A, B: T; C, D: U) = nil
good(typePairs2(int, int, TFoo, TFOO)) accept typePairs2(int, int, TFoo, TFOO)
good(typePairs2(TBAR, TBar, TBAR, TBAR)) accept typePairs2(TBAR, TBar, TBAR, TBAR)
good(typePairs2(int, int, string, string)) accept typePairs2(int, int, string, string)
bad(typePairs2(TBAR, TBar, TBar, TFoo)) reject typePairs2(TBAR, TBar, TBar, TFoo)
bad(typePairs2(string, int, TBAR, TBAR)) reject typePairs2(string, int, TBAR, TBAR)
proc dontBind(a: typedesc, b: typedesc) = proc dontBind(a: typedesc, b: typedesc) =
static: static:
echo a.name echo a.name
echo b.name echo b.name
good(dontBind(int, float)) accept dontBind(int, float)
good(dontBind(TFoo, TFoo)) accept dontBind(TFoo, TFoo)
proc dontBind2(a, b: typedesc) = nil proc dontBind2(a, b: typedesc) = nil
good(dontBind2(int, float)) accept dontBind2(int, float)
good(dontBind2(TBar, int)) accept dontBind2(TBar, int)
proc bindArg(T: typedesc, U: typedesc, a, b: T, c, d: U) = nil proc bindArg(T: typedesc, U: typedesc, a, b: T, c, d: U) = nil
good(bindArg(int, string, 10, 20, "test", "nest")) accept bindArg(int, string, 10, 20, "test", "nest")
good(bindArg(int, int, 10, 20, 30, 40)) accept bindArg(int, int, 10, 20, 30, 40)
bad(bindArg(int, string, 10, "test", "test", "nest")) reject bindArg(int, string, 10, "test", "test", "nest")
bad(bindArg(int, int, 10, 20, 30, "test")) reject bindArg(int, int, 10, 20, 30, "test")
bad(bindArg(int, string, 10.0, 20, "test", "nest")) reject bindArg(int, string, 10.0, 20, "test", "nest")
bad(bindArg(int, string, "test", "nest", 10, 20)) reject bindArg(int, string, "test", "nest", 10, 20)

View file

@ -1,6 +1,6 @@
discard """ discard """
file: "system.nim" file: "system.nim"
line: 696 line: 698
errormsg: "type mismatch" errormsg: "type mismatch"
""" """

View file

@ -3,7 +3,7 @@ discard """
WARNING: false first asseertion from bar WARNING: false first asseertion from bar
ERROR: false second assertion from bar ERROR: false second assertion from bar
-1 -1
tests/run/tfailedassert.nim:40 false assertion from foo tests/run/tfailedassert.nim:27 false assertion from foo
''' '''
""" """