covariance for arrays and sequences
This commit is contained in:
parent
a802d72452
commit
f4e73344d4
3 changed files with 247 additions and 50 deletions
|
|
@ -889,7 +889,7 @@ proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
|
|||
return false
|
||||
|
||||
proc typeRel(c: var TCandidate, f, aOrig: PType,
|
||||
flags: TTypeRelFlags = {}): TTypeRelation =
|
||||
flags: TTypeRelFlags = {}): TTypeRelation =
|
||||
# typeRel can be used to establish various relationships between types:
|
||||
#
|
||||
# 1) When used with concrete types, it will check for type equivalence
|
||||
|
|
@ -1092,9 +1092,17 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
|||
fRange = a
|
||||
else:
|
||||
fRange = prev
|
||||
result = typeRel(c, f.sons[1].skipTypes({tyTypeDesc}),
|
||||
a.sons[1].skipTypes({tyTypeDesc}))
|
||||
if result < isGeneric: return isNone
|
||||
let ff = f.sons[1].skipTypes({tyTypeDesc})
|
||||
let aa = a.sons[1].skipTypes({tyTypeDesc})
|
||||
result = typeRel(c, ff, aa)
|
||||
if result < isGeneric:
|
||||
if nimEnableCovariance and
|
||||
trNoCovariance notin flags and
|
||||
ff.kind == aa.kind and
|
||||
isCovariantPtr(c, ff, aa):
|
||||
result = isSubtype
|
||||
else:
|
||||
return isNone
|
||||
|
||||
if fRange.rangeHasUnresolvedStatic:
|
||||
return inferStaticsInRange(c, fRange, a)
|
||||
|
|
@ -1113,20 +1121,31 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
|||
if tfOldSchoolExprStmt in f.sons[0].flags:
|
||||
if f.sons[0].kind == tyExpr: return
|
||||
elif f.sons[0].kind == tyStmt: return
|
||||
|
||||
template matchArrayOrSeq(aBase: PType) =
|
||||
let ff = f.base
|
||||
let aa = aBase
|
||||
let baseRel = typeRel(c, ff, aa)
|
||||
if baseRel >= isGeneric:
|
||||
result = isConvertible
|
||||
elif nimEnableCovariance and
|
||||
trNoCovariance notin flags and
|
||||
ff.kind == aa.kind and
|
||||
isCovariantPtr(c, ff, aa):
|
||||
result = isConvertible
|
||||
|
||||
case a.kind
|
||||
of tyOpenArray, tyVarargs:
|
||||
result = typeRel(c, base(f), base(a))
|
||||
if result < isGeneric: result = isNone
|
||||
of tyArray:
|
||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
|
||||
result = isSubtype
|
||||
elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
|
||||
result = isConvertible
|
||||
return isSubtype
|
||||
matchArrayOrSeq(a.sons[1])
|
||||
of tySequence:
|
||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
||||
result = isConvertible
|
||||
elif typeRel(c, base(f), a.sons[0]) >= isGeneric:
|
||||
result = isConvertible
|
||||
return isConvertible
|
||||
matchArrayOrSeq(a.sons[0])
|
||||
of tyString:
|
||||
if f.kind == tyOpenArray:
|
||||
if f.sons[0].kind == tyChar:
|
||||
|
|
@ -1141,8 +1160,17 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
|
|||
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
||||
result = isSubtype
|
||||
else:
|
||||
result = typeRel(c, f.sons[0], a.sons[0])
|
||||
if result < isGeneric: result = isNone
|
||||
let ff = f.sons[0]
|
||||
let aa = a.sons[0]
|
||||
result = typeRel(c, ff, aa)
|
||||
if result < isGeneric:
|
||||
if nimEnableCovariance and
|
||||
trNoCovariance notin flags and
|
||||
ff.kind == aa.kind and
|
||||
isCovariantPtr(c, ff, aa):
|
||||
result = isSubtype
|
||||
else:
|
||||
result = isNone
|
||||
elif tfNotNil in f.flags and tfNotNil notin a.flags:
|
||||
result = isNilConversion
|
||||
of tyNil: result = f.allowsNil
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue