integrate the logic of fixupProcType into ReplaceTypeVars

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

View File

@@ -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

View File

@@ -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,

View File

@@ -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:

View File

@@ -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})

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

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

View File

@@ -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
'''
"""