diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-04-30 01:12:36 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2016-04-30 01:12:36 +0200 |
commit | f348671ba7146420e1bfc7cd21ddc5464f0b9cb3 (patch) | |
tree | 490b6c4c73bd5681bd3411dea9a84c43a9e1dd01 /compiler | |
parent | e04f3195407cc99f958dd81e0a9d58fe5414e631 (diff) | |
download | Nim-f348671ba7146420e1bfc7cd21ddc5464f0b9cb3.tar.gz |
fixes #3544
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semexprs.nim | 9 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 6 |
2 files changed, 12 insertions, 3 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 3c4c453a9..105667aab 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -87,8 +87,9 @@ type convNotNeedeed, convNotLegal -proc checkConversionBetweenObjects(castDest, src: PType): TConvStatus = - return if inheritanceDiff(castDest, src) == high(int): +proc checkConversionBetweenObjects(castDest, src: PType; pointers: int): TConvStatus = + let diff = inheritanceDiff(castDest, src) + return if diff == high(int) or (pointers > 1 and diff != 0): convNotLegal else: convOK @@ -105,13 +106,15 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus = return var d = skipTypes(castDest, abstractVar) var s = skipTypes(src, abstractVar-{tyTypeDesc}) + var pointers = 0 while (d != nil) and (d.kind in {tyPtr, tyRef}) and (d.kind == s.kind): d = d.lastSon s = s.lastSon + inc pointers if d == nil: result = convNotLegal elif d.kind == tyObject and s.kind == tyObject: - result = checkConversionBetweenObjects(d, s) + result = checkConversionBetweenObjects(d, s, pointers) elif (skipTypes(castDest, abstractVarRange).kind in IntegralTypes) and (skipTypes(src, abstractVarRange-{tyTypeDesc}).kind in IntegralTypes): # accept conversion between integral types diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 377743de3..09758e05d 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -598,6 +598,10 @@ proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode = let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil) result = c.c.semExpr(c.c, instantiated) +template subtypeCheck() = + if result <= isSubrange and f.lastSon.skipTypes(abstractInst).kind in {tyRef, tyPtr, tyVar}: + result = isNone + proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = # typeRel can be used to establish various relationships between types: # @@ -737,6 +741,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = of tyVar: if aOrig.kind == tyVar: result = typeRel(c, f.base, aOrig.base) else: result = typeRel(c, f.base, aOrig) + subtypeCheck() of tyArray, tyArrayConstr: # tyArrayConstr cannot happen really, but # we wanna be safe here @@ -867,6 +872,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = for i in 0..f.len-2: if typeRel(c, f.sons[i], a.sons[i]) == isNone: return isNone result = typeRel(c, f.lastSon, a.lastSon) + subtypeCheck() if result <= isConvertible: result = isNone elif tfNotNil in f.flags and tfNotNil notin a.flags: result = isNilConversion |