diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 876802ed7a..1e86bc0bac 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -1784,13 +1784,18 @@ proc setEffectsForProcType*(g: ModuleGraph; t: PType, n: PNode; s: PSym = nil) = elif s != nil and (s.magic != mNone or {sfImportc, sfExportc} * s.flags == {sfImportc}): effects[exceptionEffects] = newNodeI(nkArgList, effects.info) + let forbidsSpec = effectSpec(n, wForbids) let tagsSpec = effectSpec(n, wTags) if not isNil(tagsSpec): effects[tagEffects] = tagsSpec + elif not isNil(forbidsSpec): + # `.forbids` without `.tags` still declares a known empty tag set. + # Leaving this as nil would mean "unknown tags", which later widens + # indirect calls to `RootEffect`. + effects[tagEffects] = newNodeI(nkArgList, effects.info) elif s != nil and (s.magic != mNone or {sfImportc, sfExportc} * s.flags == {sfImportc}): effects[tagEffects] = newNodeI(nkArgList, effects.info) - let forbidsSpec = effectSpec(n, wForbids) if not isNil(forbidsSpec): effects[forbiddenEffects] = forbidsSpec elif s != nil and (s.magic != mNone or {sfImportc, sfExportc} * s.flags == {sfImportc}): diff --git a/tests/effects/tissue25976.nim b/tests/effects/tissue25976.nim new file mode 100644 index 0000000000..ab19e59df2 --- /dev/null +++ b/tests/effects/tissue25976.nim @@ -0,0 +1,28 @@ +type + NestedPoll = object of RootEffect + + CallbackFunc = proc(arg: pointer) {.gcsafe, raises: [], forbids: [NestedPoll].} + TaggedCallbackFunc = proc(arg: pointer) {.gcsafe, raises: [], tags: [], forbids: [NestedPoll].} + + InternalAsyncCallback = object + fn: CallbackFunc + + TaggedInternalAsyncCallback = object + fn: TaggedCallbackFunc + +proc closeSocket(aftercb: CallbackFunc = nil) = + proc continuation(udata: pointer) = + aftercb(nil) + + let acb = InternalAsyncCallback(fn: continuation) + discard acb + +proc closeSocketTagged(aftercb: TaggedCallbackFunc = nil) = + proc continuation(udata: pointer) = + aftercb(nil) + + let acb = TaggedInternalAsyncCallback(fn: continuation) + discard acb + +closeSocket() +closeSocketTagged()