summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/aliases.nim3
-rw-r--r--compiler/ccgexprs.nim5
-rw-r--r--compiler/ccgtrav.nim4
-rw-r--r--compiler/ccgtypes.nim6
-rw-r--r--compiler/cgen.nim2
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/jstypes.nim2
-rw-r--r--compiler/lowerings.nim4
-rw-r--r--compiler/semasgn.nim3
-rw-r--r--compiler/semexprs.nim6
-rw-r--r--compiler/semfields.nim2
-rw-r--r--compiler/seminst.nim2
-rw-r--r--compiler/sempass2.nim2
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/semtypes.nim8
-rw-r--r--compiler/sigmatch.nim25
-rw-r--r--compiler/suggest.nim2
-rw-r--r--compiler/types.nim12
18 files changed, 61 insertions, 31 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim
index 4b592ee60..4186900ec 100644
--- a/compiler/aliases.nim
+++ b/compiler/aliases.nim
@@ -46,7 +46,8 @@ proc isPartOfAux(a, b: PType, marker: var IntSet): TAnalysisResult =
   if compareTypes(a, b, dcEqIgnoreDistinct): return arYes
   case a.kind
   of tyObject:
-    result = isPartOfAux(a.sons[0], b, marker)
+    if a.sons[0] != nil:
+      result = isPartOfAux(a.sons[0].skipTypes(skipPtrs), b, marker)
     if result == arNo: result = isPartOfAux(a.n, b, marker)
   of tyGenericInst, tyDistinct:
     result = isPartOfAux(lastSon(a), b, marker)
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 719bc195c..e1ee6f1de 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -726,6 +726,7 @@ proc lookupFieldAgain(p: BProc, ty: PType; field: PSym; r: var Rope): PSym =
   var ty = ty
   assert r != nil
   while ty != nil:
+    ty = ty.skipTypes(skipPtrs)
     assert(ty.kind in {tyTuple, tyObject})
     result = lookupInRecord(ty.n, field.name)
     if result != nil: break
@@ -1257,7 +1258,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
   if not p.module.compileToCpp:
     while t.kind == tyObject and t.sons[0] != nil:
       add(r, ~".Sup")
-      t = skipTypes(t.sons[0], typedescInst)
+      t = skipTypes(t.sons[0], skipPtrs)
   if isObjLackingTypeField(t):
     globalError(x.info, errGenerated,
       "no 'of' operator available for pure objects")
@@ -1875,7 +1876,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
     if not p.module.compileToCpp:
       while t.kind == tyObject and t.sons[0] != nil:
         add(r, ".Sup")
-        t = skipTypes(t.sons[0], abstractInst)
+        t = skipTypes(t.sons[0], skipPtrs)
     if nilCheck != nil:
       linefmt(p, cpsStmts, "if ($1) #chckObj($2.m_type, $3);$n",
               nilCheck, r, genTypeInfo(p.module, dest))
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index c4d47f148..a8c079b35 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -73,7 +73,9 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: Rope, typ: PType) =
     lineF(p, cpsStmts, "}$n", [])
   of tyObject:
     for i in countup(0, sonsLen(typ) - 1):
-      genTraverseProc(c, accessor.parentObj(c.p.module), typ.sons[i])
+      var x = typ.sons[i]
+      if x != nil: x = x.skipTypes(skipPtrs)
+      genTraverseProc(c, accessor.parentObj(c.p.module), x)
     if typ.n != nil: genTraverseProc(c, accessor, typ.n)
   of tyTuple:
     let typ = getUniqueType(typ)
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index e30395d2e..15fefa944 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -475,11 +475,11 @@ proc getRecordDesc(m: BModule, typ: PType, name: Rope,
         hasField = true
     elif m.compileToCpp:
       appcg(m, result, " : public $1 {$n",
-                      [getTypeDescAux(m, typ.sons[0], check)])
+                      [getTypeDescAux(m, typ.sons[0].skipTypes(skipPtrs), check)])
       hasField = true
     else:
       appcg(m, result, " {$n  $1 Sup;$n",
-                      [getTypeDescAux(m, typ.sons[0], check)])
+                      [getTypeDescAux(m, typ.sons[0].skipTypes(skipPtrs), check)])
       hasField = true
   else:
     addf(result, " {$n", [name])
@@ -901,7 +901,7 @@ proc genObjectInfo(m: BModule, typ, origType: PType, name: Rope) =
   addf(m.s[cfsTypeInit3], "$1.node = &$2;$n", [name, tmp])
   var t = typ.sons[0]
   while t != nil:
-    t = t.skipTypes(abstractInst)
+    t = t.skipTypes(skipPtrs)
     t.flags.incl tfObjHasKids
     t = t.sons[0]
 
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 42883b590..4a3113edf 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -246,7 +246,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
     if not p.module.compileToCpp:
       while (s.kind == tyObject) and (s.sons[0] != nil):
         add(r, ".Sup")
-        s = skipTypes(s.sons[0], abstractInst)
+        s = skipTypes(s.sons[0], skipPtrs)
     linefmt(p, section, "$1.m_type = $2;$n", r, genTypeInfo(p.module, t))
   of frEmbedded:
     # worst case for performance:
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 3e56e2f41..d17f5580e 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -1364,7 +1364,7 @@ proc createObjInitList(p: PProc, typ: PType, excludedFieldIDs: IntSet, output: v
     if output.len > 0: output.add(", ")
     addf(output, "m_type: $1" | "'m_type' => $#", [genTypeInfo(p, t)])
   while t != nil:
-    createRecordVarAux(p, t.n, excludedFieldIDs, output)
+    createRecordVarAux(p, t.skipTypes(skipPtrs).n, excludedFieldIDs, output)
     t = t.sons[0]
 
 proc arrayTypeForElemType(typ: PType): string =
diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim
index cf1679ee4..0aaf93579 100644
--- a/compiler/jstypes.nim
+++ b/compiler/jstypes.nim
@@ -76,7 +76,7 @@ proc genObjectInfo(p: PProc, typ: PType, name: Rope) =
   addf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, rope(typ.id)])
   if (typ.kind == tyObject) and (typ.sons[0] != nil):
     addf(p.g.typeInfo, "$1.base = $2;$n",
-         [name, genTypeInfo(p, typ.sons[0])])
+         [name, genTypeInfo(p, typ.sons[0].skipTypes(skipPtrs))])
 
 proc genTupleFields(p: PProc, typ: PType): Rope =
   var s: Rope = nil
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 36eb24653..9db4383f6 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -172,7 +172,7 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
     if field != nil: break
     t = t.sons[0]
     if t == nil: break
-    t = t.skipTypes(abstractInst)
+    t = t.skipTypes(skipPtrs)
   #if field == nil:
   #  echo "FIELD ", b
   #  debug deref.typ
@@ -193,7 +193,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
     if result != nil: break
     t = t.sons[0]
     if t == nil: break
-    t = t.skipTypes(abstractInst)
+    t = t.skipTypes(skipPtrs)
 
 proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
   # returns a[].b as a node
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
index 9702128ba..2e925e386 100644
--- a/compiler/semasgn.nim
+++ b/compiler/semasgn.nim
@@ -203,7 +203,8 @@ proc liftBodyAux(c: var TLiftCtx; t: PType; body, x, y: PNode) =
       defaultOp(c, t, body, x, y)
   of tyObject, tyDistinct:
     if not considerOverloadedOp(c, t, body, x, y):
-      if t.sons[0] != nil: liftBodyAux(c, t.sons[0], body, x, y)
+      if t.sons[0] != nil:
+        liftBodyAux(c, t.sons[0].skipTypes(skipPtrs), body, x, y)
       if t.kind == tyObject: liftBodyObj(c, t.n, body, x, y)
   of tyTuple:
     liftBodyTup(c, t, body, x, y)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 274bb15b9..5c29530b8 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1070,7 +1070,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
               result = check
             return result
           if ty.sons[0] == nil: break
-          ty = skipTypes(ty.sons[0], {tyGenericInst})
+          ty = skipTypes(ty.sons[0], skipPtrs)
     # old code, not sure if it's live code:
     markUsed(n.info, s)
     styleCheckUse(n.info, s)
@@ -1148,7 +1148,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
       f = lookupInRecordAndBuildCheck(c, n, ty.n, i, check)
       if f != nil: break
       if ty.sons[0] == nil: break
-      ty = skipTypes(ty.sons[0], {tyGenericInst})
+      ty = skipTypes(ty.sons[0], skipPtrs)
     if f != nil:
       if fieldVisible(c, f):
         # is the access to a public field or in the same module or in a friend?
@@ -2108,7 +2108,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
       f = lookupInRecordAndBuildCheck(c, it, t.n, id, check)
       if f != nil: break
       if t.sons[0] == nil: break
-      t = skipTypes(t.sons[0], {tyGenericInst})
+      t = skipTypes(t.sons[0], skipPtrs)
     if f != nil and fieldVisible(c, f):
       it.sons[0] = newSymNode(f)
       e = fitNode(c, f.typ, e)
diff --git a/compiler/semfields.nim b/compiler/semfields.nim
index 2e6c6c3ea..9d8cea862 100644
--- a/compiler/semfields.nim
+++ b/compiler/semfields.nim
@@ -152,7 +152,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
     while t.kind == tyObject:
       semForObjectFields(fc, t.n, n, stmts)
       if t.sons[0] == nil: break
-      t = skipTypes(t.sons[0], abstractPtrs)
+      t = skipTypes(t.sons[0], skipPtrs)
   dec(c.p.nestedLoopCounter)
   # for TR macros this 'while true: ...; break' loop is pretty bad, so
   # we avoid it now if we can:
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 498ebc3fb..d7cad6a2f 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -47,7 +47,7 @@ proc rawHandleSelf(c: PContext; owner: PSym) =
         while t.kind == tyObject:
           addObjFieldsToLocalScope(c, t.n)
           if t.sons[0] == nil: break
-          t = t.sons[0].skipTypes(abstractPtrs)
+          t = t.sons[0].skipTypes(skipPtrs)
 
 proc pushProcCon*(c: PContext; owner: PSym) =
   rawPushProcCon(c, owner)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 3908fa26e..df9b3f69c 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -131,7 +131,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
         if field != nil: break
         ty = ty.sons[0]
         if ty == nil: break
-        ty = ty.skipTypes(abstractPtrs)
+        ty = ty.skipTypes(skipPtrs)
     if field == nil:
       localError(n.info, errGenerated, "invalid guard field: " & g.name.s)
       return
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index cd96600ec..97c3b6ddd 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -659,7 +659,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
   if n.sons[0].kind != nkEmpty:
     n.sons[0] = semExprWithType(c, n.sons[0])
     var typ = n.sons[0].typ
-    if typ.kind != tyRef or typ.sons[0].kind != tyObject:
+    if typ.kind != tyRef or typ.lastSon.kind != tyObject:
       localError(n.info, errExprCannotBeRaised)
 
 proc addGenericParamListToScope(c: PContext, n: PNode) =
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 3834d0b51..ed576f85e 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -661,11 +661,12 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
   if n.sonsLen == 0: return newConstraint(c, tyObject)
   var check = initIntSet()
   var pos = 0
-  var base: PType = nil
+  var base, realBase: PType = nil
   # n.sons[0] contains the pragmas (if any). We process these later...
   checkSonsLen(n, 3)
   if n.sons[1].kind != nkEmpty:
-    base = skipTypesOrNil(semTypeNode(c, n.sons[1].sons[0], nil), skipPtrs)
+    realBase = semTypeNode(c, n.sons[1].sons[0], nil)
+    base = skipTypesOrNil(realBase, skipPtrs)
     if base.isNil:
       localError(n.info, errIllegalRecursionInTypeX, "object")
     else:
@@ -676,9 +677,10 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
         if concreteBase.kind != tyError:
           localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
         base = nil
+        realBase = nil
   if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
   result = newOrPrevType(tyObject, prev, c)
-  rawAddSon(result, base)
+  rawAddSon(result, realBase)
   if result.n.isNil:
     result.n = newNodeI(nkRecList, n.info)
   else:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 1abfaab69..90435f9c0 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -352,18 +352,28 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
       else: result = isIntConv
     else: result = isNone
 
-proc isObjectSubtype(a, f: PType): int =
+proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
   var t = a
   assert t.kind == tyObject
   var depth = 0
+  var last = a
   while t != nil and not sameObjectTypes(f, t):
     assert t.kind == tyObject
     t = t.sons[0]
     if t == nil: break
-    t = skipTypes(t, {tyGenericInst})
+    last = t
+    t = skipTypes(t, skipPtrs)
     inc depth
   if t != nil:
+    if fGenericOrigin != nil and last.kind == tyGenericInst and
+        last.len-1 == fGenericOrigin.len:
+      for i in countup(1, sonsLen(fGenericOrigin) - 1):
+        let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i]))
+        if x == nil:
+          put(c, fGenericOrigin.sons[i], last.sons[i])
     result = depth
+  else:
+    result = -1
 
 type
   SkippedPtr = enum skippedNone, skippedRef, skippedPtr
@@ -896,7 +906,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         result = isEqual
         # elif tfHasMeta in f.flags: result = recordRel(c, f, a)
       else:
-        var depth = isObjectSubtype(a, f)
+        var depth = isObjectSubtype(c, a, f, nil)
         if depth > 0:
           inc(c.inheritancePenalty, depth)
           result = isSubtype
@@ -1012,6 +1022,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       result = isGeneric
     else:
       let genericBody = f.sons[0]
+      var askip = skippedNone
+      var fskip = skippedNone
+      let aobj = x.skipToObject(askip)
+      let fobj = genericBody.lastSon.skipToObject(fskip)
+      if fobj != nil and aobj != nil and askip == fskip:
+        let depth = isObjectSubtype(c, aobj, fobj, f)
+        if depth >= 0:
+          c.inheritancePenalty += depth
+          return if depth == 0: isGeneric else: isSubtype
       result = typeRel(c, genericBody, x)
       if result != isNone:
         # see tests/generics/tgeneric3.nim for an example that triggers this
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index c127b968c..f331fce69 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -273,7 +273,7 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) =
       while true:
         suggestObject(c, t.n, outputs)
         if t.sons[0] == nil: break
-        t = skipTypes(t.sons[0], {tyGenericInst})
+        t = skipTypes(t.sons[0], skipPtrs)
       suggestOperations(c, n, typ, outputs)
     elif typ.kind == tyTuple and typ.n != nil:
       suggestSymList(c, typ.n, outputs)
diff --git a/compiler/types.nim b/compiler/types.nim
index 4690d5a1f..3db0c4507 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -94,7 +94,8 @@ proc invalidGenericInst(f: PType): bool =
 
 proc isPureObject(typ: PType): bool =
   var t = typ
-  while t.kind == tyObject and t.sons[0] != nil: t = t.sons[0]
+  while t.kind == tyObject and t.sons[0] != nil:
+    t = t.sons[0].skipTypes(skipPtrs)
   result = t.sym != nil and sfPure in t.sym.flags
 
 proc getOrdValue(n: PNode): BiggestInt =
@@ -228,7 +229,8 @@ proc searchTypeForAux(t: PType, predicate: TTypePredicate,
   if result: return
   case t.kind
   of tyObject:
-    result = searchTypeForAux(t.sons[0], predicate, marker)
+    if t.sons[0] != nil:
+      result = searchTypeForAux(t.sons[0].skipTypes(skipPtrs), predicate, marker)
     if not result: result = searchTypeNodeForAux(t.n, predicate, marker)
   of tyGenericInst, tyDistinct:
     result = searchTypeForAux(lastSon(t), predicate, marker)
@@ -265,7 +267,9 @@ proc analyseObjectWithTypeFieldAux(t: PType,
       if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
         return frEmbedded
     for i in countup(0, sonsLen(t) - 1):
-      res = analyseObjectWithTypeFieldAux(t.sons[i], marker)
+      var x = t.sons[i]
+      if x != nil: x = x.skipTypes(skipPtrs)
+      res = analyseObjectWithTypeFieldAux(x, marker)
       if res == frEmbedded:
         return frEmbedded
       if res == frHeader: result = frHeader
@@ -1293,7 +1297,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     a = maxAlign
   of tyObject:
     if typ.sons[0] != nil:
-      result = computeSizeAux(typ.sons[0], a)
+      result = computeSizeAux(typ.sons[0].skipTypes(skipPtrs), a)
       if result < 0: return
       maxAlign = a
     elif isObjectWithTypeFieldPredicate(typ):