//this causes EXC_BAD_ACCESS in consuming module
@_implementationOnly import AMQPClient
public struct Subscription: Sendable {
var channel: AMQPChannel //class from @_implementationOnly import
}
tl;dr: use with caution ; )
Thought I'd share the horrors I just went through because I tried using this in a package, maybe this helps somebody else:
I wanted a package that wraps our inter-services RPC/messaging in a nice, high-level package using rabbitmq-nio internally. I stumbled over the @_implementationOnly attribute and thought "nice, this prevents me from 'leaking' implementation details - if I want to swap out stuff later I can without having to adjust all our services". compiler warnings seemed reasonable, all seemed fine.
when running tests I started to get BAD_ACCESS errors in the weirdest places - very, VERY tough to debug for me. since I was using a lot of new concurrency stuff, NIO under the hood, and a few self-made unchecked sendable implementations I initially thought I must have screwed up data access somehow.
I kept getting this call stack in some objc_retain thing, which I figured must have to do something with ARC but for me it was miles away from a straight-forward error.
so, long story short, my package passed out a public struct with an internal field containing a class from the "_implementationOnly" module. and when the struct went out of scope, the ARC stuff seemed to get very confused. no compiler warnings or errors, just a pretty nasty crash at runtime.
Oddly, the crash had nothing to do with deinit or any actual call, and happened with unowned just as much as with weak. Just having this Subscription type it in a function's signature caused mayhem.
As a confusion bonus: if you import the implementationOnly module in the calling app/test as well, everything works just fine.