From f31d1fa98b65f497b914f5bbfe1a3827cf791814 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 19 Feb 2019 16:22:09 +0100 Subject: fixes #10195 --- compiler/semtypes.nim | 76 +++++++++++++++++++++++++---------------------- tests/objects/tobject.nim | 5 ++++ 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index d62bc664e..a497e1eae 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -184,39 +184,6 @@ proc semVarargs(c: PContext, n: PNode, prev: PType): PType = localError(c.config, n.info, errXExpectsOneTypeParam % "varargs") addSonSkipIntLit(result, errorType(c)) -proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = - if n.len < 1: - result = newConstraint(c, kind) - else: - let isCall = int ord(n.kind in nkCallKinds+{nkBracketExpr}) - let n = if n[0].kind == nkBracket: n[0] else: n - checkMinSonsLen(n, 1, c.config) - var t = semTypeNode(c, n.lastSon, nil) - if t.kind == tyTypeDesc and tfUnresolved notin t.flags: - t = t.base - if t.kind == tyVoid: - const kindToStr: array[tyPtr..tyRef, string] = ["ptr", "ref"] - localError(c.config, n.info, "type '$1 void' is not allowed" % kindToStr[kind]) - result = newOrPrevType(kind, prev, c) - var isNilable = false - # check every except the last is an object: - for i in isCall .. n.len-2: - let ni = n[i] - if ni.kind == nkNilLit: - isNilable = true - else: - let region = semTypeNode(c, ni, nil) - if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin { - tyError, tyObject}: - message c.config, n[i].info, errGenerated, "region needs to be an object type" - else: - message(c.config, n.info, warnDeprecated, "region for pointer types is deprecated") - addSonSkipIntLit(result, region) - addSonSkipIntLit(result, t) - if tfPartial in result.flags: - if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial) - #if not isNilable: result.flags.incl tfNotNil - proc semVarType(c: PContext, n: PNode, prev: PType): PType = if sonsLen(n) == 1: result = newOrPrevType(tyVar, prev, c) @@ -793,7 +760,7 @@ proc addInheritedFields(c: PContext, check: var IntSet, pos: var int, addInheritedFields(c, check, pos, obj.sons[0].skipGenericInvocation) addInheritedFieldsAux(c, check, pos, obj.n) -proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = +proc semObjectNode(c: PContext, n: PNode, prev: PType; isInheritable: bool): PType = if n.sonsLen == 0: return newConstraint(c, tyObject) var check = initIntSet() @@ -825,6 +792,8 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = if n.kind != nkObjectTy: internalError(c.config, n.info, "semObjectNode") result = newOrPrevType(tyObject, prev, c) rawAddSon(result, realBase) + if realBase == nil and isInheritable: + result.flags.incl tfInheritable if result.n.isNil: result.n = newNodeI(nkRecList, n.info) else: @@ -839,6 +808,43 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = if base == nil and tfInheritable notin result.flags: incl(result.flags, tfFinal) +proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = + if n.len < 1: + result = newConstraint(c, kind) + else: + let isCall = int ord(n.kind in nkCallKinds+{nkBracketExpr}) + let n = if n[0].kind == nkBracket: n[0] else: n + checkMinSonsLen(n, 1, c.config) + let body = n.lastSon + var t = if prev != nil and body.kind == nkObjectTy and tfInheritable in prev.flags: + semObjectNode(c, body, nil, isInheritable=true) + else: + semTypeNode(c, body, nil) + if t.kind == tyTypeDesc and tfUnresolved notin t.flags: + t = t.base + if t.kind == tyVoid: + const kindToStr: array[tyPtr..tyRef, string] = ["ptr", "ref"] + localError(c.config, n.info, "type '$1 void' is not allowed" % kindToStr[kind]) + result = newOrPrevType(kind, prev, c) + var isNilable = false + # check every except the last is an object: + for i in isCall .. n.len-2: + let ni = n[i] + if ni.kind == nkNilLit: + isNilable = true + else: + let region = semTypeNode(c, ni, nil) + if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin { + tyError, tyObject}: + message c.config, n[i].info, errGenerated, "region needs to be an object type" + else: + message(c.config, n.info, warnDeprecated, "region for pointer types is deprecated") + addSonSkipIntLit(result, region) + addSonSkipIntLit(result, t) + if tfPartial in result.flags: + if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial) + #if not isNilable: result.flags.incl tfNotNil + proc findEnforcedStaticType(t: PType): PType = # This handles types such as `static[T] and Foo`, # which are subset of `static[T]`, hence they could @@ -1705,7 +1711,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = else: if s.kind != skError: localError(c.config, n.info, errTypeExpected) result = newOrPrevType(tyError, prev, c) - of nkObjectTy: result = semObjectNode(c, n, prev) + of nkObjectTy: result = semObjectNode(c, n, prev, isInheritable=false) of nkTupleTy: result = semTuple(c, n, prev) of nkTupleClassTy: result = newConstraint(c, tyTuple) of nkTypeClassTy: result = semTypeClass(c, n, prev) diff --git a/tests/objects/tobject.nim b/tests/objects/tobject.nim index fbf531c3d..34856eaef 100644 --- a/tests/objects/tobject.nim +++ b/tests/objects/tobject.nim @@ -37,3 +37,8 @@ f(m) var a: TYourObj = m var b: TMyObj = a + +# bug #10195 +type + InheritableFoo {.inheritable.} = ref object + InheritableBar = ref object of InheritableFoo # ERROR. -- cgit 1.4.1-2-gfad0