diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 250e53ed6f..ba26635a1d 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -204,6 +204,8 @@ proc fixupProcType(c: PContext, genericType: PType, result = result.sons[0] of tyStatic: result = inst.concreteTypes[genericType.sym.position] + of tyGenericInst: + result = fixupProcType(c, result.lastSon, inst) of tyOpenArray, tyArray, tySet, tySequence, tyTuple, tyProc, tyPtr, tyVar, tyRef, tyOrdinal, tyRange, tyVarargs: if genericType.sons == nil: return @@ -234,7 +236,8 @@ proc fixupProcType(c: PContext, genericType: PType, continue result.sons[head] = changed - + result.size = 0 + if result.n != nil: if result.n.kind == nkRecList: for son in result.n.sons: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index d3a934c215..6f6d0c4c58 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -620,7 +620,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) @@ -665,6 +665,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, if lifted != nil: paramType.sons[i] = lifted result = paramType + of tyGenericBody: result = newTypeS(tyGenericInvokation, c) result.rawAddSon(paramType) @@ -674,6 +675,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, allowMetaTypes = true) result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result]) result = addImplicitGeneric(result) + of tyGenericInst: for i in 1 .. (paramType.sons.len - 2): var lifted = liftingWalk(paramType.sons[i]) @@ -681,21 +683,22 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, paramType.sons[i] = lifted result = paramType - if result == nil: - result = liftingWalk(paramType.lastSon) - else: - result.kind = tyGenericInvokation - result.sons.setLen(result.sons.len - 1) + let liftBody = liftingWalk(paramType.lastSon) + if liftBody != nil: result = liftBody + of tyTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot: - result = addImplicitGeneric(copyType(paramType, getCurrOwner(), false)) + result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true)) + of tyExpr: result = addImplicitGeneric(newTypeS(tyGenericParam, c)) + of tyGenericParam: if tfGenericTypeParam in paramType.flags and false: if paramType.sonsLen > 0: result = liftingWalk(paramType.lastSon) else: result = addImplicitGeneric(newTypeS(tyGenericParam, c)) + else: nil # result = liftingWalk(paramType) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index f7750171d6..384ce3498c 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -17,14 +17,14 @@ proc checkPartialConstructedType(info: TLineInfo, t: PType) = elif t.kind == tyVar and t.sons[0].kind == tyVar: LocalError(info, errVarVarTypeNotAllowed) -proc checkConstructedType*(info: TLineInfo, typ: PType) = +proc checkConstructedType*(info: TLineInfo, typ: PType) = var t = typ.skipTypes({tyDistinct}) if t.kind in tyTypeClasses: nil elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: LocalError(info, errInvalidPragmaX, "acyclic") elif t.kind == tyVar and t.sons[0].kind == tyVar: LocalError(info, errVarVarTypeNotAllowed) - elif computeSize(t) < 0: + elif computeSize(t) == szIllegalRecursion: LocalError(info, errIllegalRecursionInTypeX, typeToString(t)) when false: if t.kind == tyObject and t.sons[0] != nil: @@ -140,7 +140,7 @@ proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = result = errorType(cl.c) elif result.kind == tyGenericParam and not cl.allowMetaTypes: InternalError(cl.info, "substitution with generic parameter") - + proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType = # tyGenericInvokation[A, tyGenericInvokation[A, B]] # is difficult to handle: @@ -170,7 +170,8 @@ proc handleGenericInvokation(cl: var TReplTypeVars, t: PType): PType = # recursive instantions: result = newType(tyGenericInst, t.sons[0].owner) result.rawAddSon(header.sons[0]) - cacheTypeInst(result) + if not cl.allowMetaTypes: + cacheTypeInst(result) for i in countup(1, sonsLen(t) - 1): var x = replaceTypeVarsT(cl, t.sons[i]) diff --git a/compiler/types.nim b/compiler/types.nim index 1b25a396c3..d47015836d 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1098,18 +1098,22 @@ proc computeRecSizeAux(n: PNode, a, currOffset: var biggestInt): biggestInt = a = 1 result = - 1 -proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt = +const + szIllegalRecursion* = -2 + szUnknownSize* = -1 + +proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt = var res, maxAlign, length, currOffset: biggestInt - if typ.size == - 2: + if typ.size == szIllegalRecursion: # we are already computing the size of the type # --> illegal recursion in type - return - 2 - if typ.size >= 0: + return szIllegalRecursion + if typ.size >= 0: # size already computed result = typ.size a = typ.align return - typ.size = - 2 # mark as being computed + typ.size = szIllegalRecursion # mark as being computed case typ.kind of tyInt, tyUInt: result = IntSize @@ -1196,7 +1200,7 @@ proc computeSizeAux(typ: PType, a: var biggestInt): biggestInt = of tyProxy: result = 1 else: #internalError("computeSizeAux()") - result = - 1 + result = szUnknownSize typ.size = result typ.align = int(a) @@ -1213,7 +1217,6 @@ 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 diff --git a/tests/compile/tcompositetypeclasses.nim b/tests/compile/tcompositetypeclasses.nim index ea966f1a9d..4ba92fed1a 100644 --- a/tests/compile/tcompositetypeclasses.nim +++ b/tests/compile/tcompositetypeclasses.nim @@ -13,18 +13,23 @@ type TUserClass = int|string - # TBaz = TBar[TUserClass] + TBaz = TBar[TUserClass] var vfoo: TFoo[int, string] vbar: TFoo[string, string] + vbaz: TFoo[int, int] + vnotbaz: TFoo[TObject, TObject] proc foo(x: TFoo) = echo "foo" proc bar(x: TBar) = echo "bar" -# proc baz(x: TBaz) = echo "baz" +proc baz(x: TBaz) = echo "baz" -accept(foo(vfoo)) -accept(bar(vbar)) -# baz vbar -reject(bar(vfoo)) +accept foo(vfoo) +accept bar(vbar) +accept baz(vbar) +accept baz(vbaz) + +reject baz(vnotbaz) +reject bar(vfoo)