fixes #3544
This commit is contained in:
parent
e04f319540
commit
f348671ba7
2 changed files with 12 additions and 3 deletions
|
|
@ -87,8 +87,9 @@ type
|
||||||
convNotNeedeed,
|
convNotNeedeed,
|
||||||
convNotLegal
|
convNotLegal
|
||||||
|
|
||||||
proc checkConversionBetweenObjects(castDest, src: PType): TConvStatus =
|
proc checkConversionBetweenObjects(castDest, src: PType; pointers: int): TConvStatus =
|
||||||
return if inheritanceDiff(castDest, src) == high(int):
|
let diff = inheritanceDiff(castDest, src)
|
||||||
|
return if diff == high(int) or (pointers > 1 and diff != 0):
|
||||||
convNotLegal
|
convNotLegal
|
||||||
else:
|
else:
|
||||||
convOK
|
convOK
|
||||||
|
|
@ -105,13 +106,15 @@ proc checkConvertible(c: PContext, castDest, src: PType): TConvStatus =
|
||||||
return
|
return
|
||||||
var d = skipTypes(castDest, abstractVar)
|
var d = skipTypes(castDest, abstractVar)
|
||||||
var s = skipTypes(src, abstractVar-{tyTypeDesc})
|
var s = skipTypes(src, abstractVar-{tyTypeDesc})
|
||||||
|
var pointers = 0
|
||||||
while (d != nil) and (d.kind in {tyPtr, tyRef}) and (d.kind == s.kind):
|
while (d != nil) and (d.kind in {tyPtr, tyRef}) and (d.kind == s.kind):
|
||||||
d = d.lastSon
|
d = d.lastSon
|
||||||
s = s.lastSon
|
s = s.lastSon
|
||||||
|
inc pointers
|
||||||
if d == nil:
|
if d == nil:
|
||||||
result = convNotLegal
|
result = convNotLegal
|
||||||
elif d.kind == tyObject and s.kind == tyObject:
|
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
|
elif (skipTypes(castDest, abstractVarRange).kind in IntegralTypes) and
|
||||||
(skipTypes(src, abstractVarRange-{tyTypeDesc}).kind in IntegralTypes):
|
(skipTypes(src, abstractVarRange-{tyTypeDesc}).kind in IntegralTypes):
|
||||||
# accept conversion between integral types
|
# accept conversion between integral types
|
||||||
|
|
|
||||||
|
|
@ -598,6 +598,10 @@ proc tryResolvingStaticExpr(c: var TCandidate, n: PNode): PNode =
|
||||||
let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil)
|
let instantiated = replaceTypesInBody(c.c, c.bindings, n, nil)
|
||||||
result = c.c.semExpr(c.c, instantiated)
|
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 =
|
proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
# typeRel can be used to establish various relationships between types:
|
# 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:
|
of tyVar:
|
||||||
if aOrig.kind == tyVar: result = typeRel(c, f.base, aOrig.base)
|
if aOrig.kind == tyVar: result = typeRel(c, f.base, aOrig.base)
|
||||||
else: result = typeRel(c, f.base, aOrig)
|
else: result = typeRel(c, f.base, aOrig)
|
||||||
|
subtypeCheck()
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
# tyArrayConstr cannot happen really, but
|
# tyArrayConstr cannot happen really, but
|
||||||
# we wanna be safe here
|
# 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:
|
for i in 0..f.len-2:
|
||||||
if typeRel(c, f.sons[i], a.sons[i]) == isNone: return isNone
|
if typeRel(c, f.sons[i], a.sons[i]) == isNone: return isNone
|
||||||
result = typeRel(c, f.lastSon, a.lastSon)
|
result = typeRel(c, f.lastSon, a.lastSon)
|
||||||
|
subtypeCheck()
|
||||||
if result <= isConvertible: result = isNone
|
if result <= isConvertible: result = isNone
|
||||||
elif tfNotNil in f.flags and tfNotNil notin a.flags:
|
elif tfNotNil in f.flags and tfNotNil notin a.flags:
|
||||||
result = isNilConversion
|
result = isNilConversion
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue