summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2019-02-19 16:22:09 +0100
committerAraq <rumpf_a@web.de>2019-02-19 16:25:57 +0100
commitf31d1fa98b65f497b914f5bbfe1a3827cf791814 (patch)
tree6489918838d43fd930b798b81cbb9e184cadd166
parent51f516e030c9727f756e4e53558c5e7cb8f93ccd (diff)
downloadNim-f31d1fa98b65f497b914f5bbfe1a3827cf791814.tar.gz
fixes #10195
-rw-r--r--compiler/semtypes.nim76
-rw-r--r--tests/objects/tobject.nim5
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.