@@ -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
10411056proc 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