Skip to content

Commit 068e7a4

Browse files
committed
types: update proc type comparison
1 parent 0063d6d commit 068e7a4

File tree

1 file changed

+42
-33
lines changed

1 file changed

+42
-33
lines changed

compiler/ast/types.nim

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,15 +1027,30 @@ proc safeInheritanceDiff*(a, b: PType): int =
10271027
else:
10281028
result = inheritanceDiff(a.skipTypes(skipPtrs), b.skipTypes(skipPtrs))
10291029

1030-
proc compatibleEffectsAux(se, re: PNode): bool =
1031-
if re.isNil: return false
1032-
for r in items(re):
1033-
block search:
1034-
for s in items(se):
1035-
if safeInheritanceDiff(s.typ, r.typ) <= 0:
1036-
break search
1037-
return false
1038-
result = true
1030+
proc compatibleEffectsAux(se, re: PNode, unknown, differ: EffectsCompat
1031+
): EffectsCompat =
1032+
## Computes whether effect lists `se` and `re` are compatible; they are when
1033+
## `se` is a superset of `re`.
1034+
if se.isNil:
1035+
# assume that it means "any effect"
1036+
# FIXME: ^^ this is not always true! 'nil' can also mean
1037+
# "not computed yet", in which case types will be considered
1038+
# compatible that in reality are not
1039+
result = efCompat
1040+
elif re.isNil:
1041+
# actual effects are either "any effect" or "not computed yet"
1042+
# FIXME: when `se` is computed but `re` is not, both are still compatible
1043+
# when `se` contains the top type
1044+
result = unknown
1045+
else:
1046+
# every type in `re` must be equal to or a subtype of a type in `se`
1047+
for r in items(re):
1048+
block search:
1049+
for s in items(se):
1050+
if safeInheritanceDiff(s.typ, r.typ) <= 0:
1051+
break search
1052+
return differ
1053+
result = efCompat
10391054

10401055

10411056
proc compatibleEffects*(formal, actual: PType): EffectsCompat =
@@ -1044,32 +1059,26 @@ proc compatibleEffects*(formal, actual: PType): EffectsCompat =
10441059
#if tfEffectSystemWorkaround in actual.flags:
10451060
# return efCompat
10461061

1047-
if formal.n[0].kind != nkEffectList or
1048-
actual.n[0].kind != nkEffectList:
1062+
let
1063+
spec = formal.n[0]
1064+
real = actual.n[0]
1065+
1066+
if spec.kind != nkEffectList or
1067+
real.kind != nkEffectList:
10491068
return efTagsUnknown
10501069

1051-
var spec = formal.n[0]
1052-
if spec.len != 0:
1053-
var real = actual.n[0]
1054-
1055-
let se = spec[exceptionEffects]
1056-
# if 'se.kind == nkArgList' it is no formal type really, but a
1057-
# computed effect and as such no spec:
1058-
# 'r.msgHandler = if isNil(msgHandler): defaultMsgHandler else: msgHandler'
1059-
if not isNil(se) and se.kind != nkArgList:
1060-
# spec requires some exception or tag, but we don't know anything:
1061-
if real.len == 0: return efRaisesUnknown
1062-
let res = compatibleEffectsAux(se, real[exceptionEffects])
1063-
if not res: return efRaisesDiffer
1064-
1065-
let st = spec[tagEffects]
1066-
if not isNil(st) and st.kind != nkArgList:
1067-
# spec requires some exception or tag, but we don't know anything:
1068-
if real.len == 0: return efTagsUnknown
1069-
let res = compatibleEffectsAux(st, real[tagEffects])
1070-
if not res:
1071-
#if tfEffectSystemWorkaround notin actual.flags:
1072-
return efTagsDiffer
1070+
result = compatibleEffectsAux(
1071+
spec[exceptionEffects], real[exceptionEffects],
1072+
efRaisesUnknown, efRaisesDiffer)
1073+
if result != efCompat:
1074+
return
1075+
1076+
result = compatibleEffectsAux(
1077+
spec[tagEffects], real[tagEffects],
1078+
efTagsUnknown, efTagsDiffer)
1079+
if result != efCompat:
1080+
return
1081+
10731082
if formal.lockLevel.ord < 0 or
10741083
actual.lockLevel.ord <= formal.lockLevel.ord:
10751084

0 commit comments

Comments
 (0)