Exception: Axn::ReraiseFailed
- Inherits:
-
StandardError
- Object
- StandardError
- Axn::ReraiseFailed
- Includes:
- Error
- Defined in:
- lib/axn/exceptions.rb
Overview
Raised by Axn::Extensions.best_effort under best_effort_raises_in_dev for a side-effect exception that
raise cannot hand back AS ITSELF.
The dev-loud mode re-raises what the guarded block raised, and raise dispatches the 0-arg #exception on
whatever object it is given — a bare raise re-raising $! included, since Ruby has no re-raise that skips
that dispatch. So a class that owns #exception decides what leaves the guard: one answering a different
object escaped as that object with the block's exception gone entirely, and one that raises escaped as
whatever it raised. Either way the guard emitted a third exception, which is the one thing it promises never
to do.
The decision is by OWNERSHIP, never by behaviour (NativeMethods.native_exception_reraise?), and the
dispatch is AVOIDED rather than guarded — the doctrine Axn::Tools._named_invalid_contract settled for the
boot path, for the same reason: an #exception that answers itself once and raises the second time defeats
any probe, so the only bounded question is whether Ruby's own implementation is what will answer. When it is
— the overwhelmingly common case, an ordinary ArgumentError included, and a frozen exception too — the
original object is re-raised unchanged and this class never appears.
Dev-loud stays loud where it cannot: a developer who configured a raise gets one. Only the CLASS degrades.
The original is this error's cause, its class and message are repeated here, and a StandardError so an
enclosing rescue => e catches it exactly where it would have caught the ordinary case.
Every value interpolated came from someone else's object, so each is RENDERED rather than joined — the whole
point being that reporting must not become the failure (see Tools::InvalidContract above, which composes the
same way for the same reason). The caller renders them too, needing the same text for its warning path;
rendering is idempotent, so the guarantee holds for any caller rather than resting on that one's diligence.
Instance Method Summary collapse
-
#initialize(desc:, reason:, original_class:) ⇒ ReraiseFailed
constructor
A new instance of ReraiseFailed.
Constructor Details
#initialize(desc:, reason:, original_class:) ⇒ ReraiseFailed
Returns a new instance of ReraiseFailed.
299 300 301 302 303 304 305 306 |
# File 'lib/axn/exceptions.rb', line 299 def initialize(desc:, reason:, original_class:) desc, reason, original_class = [desc, reason, original_class].map { |text| Axn::Internal::RenderedText.of(text) } super("Exception raised while #{desc}, re-raised as #{self.class} and not as the original " \ "#{original_class}, because that class supplies its own `#exception` — which `raise` dispatches on " \ "whatever object it is handed — and axn does not run an exception's own code while re-raising it. " \ "The original is this error's `cause`, and its message was: #{reason}") end |