pub struct PortFuncstackFrame;Expand description
!!! WARNING: Rust-only helper, no C counterpart !!!
This is NOT a port of anything. No C function corresponds to it; it exists only because a Rust port can reach a sibling port’s body without the frame a shell-function call would have opened.
It supplies ONLY the FUNCSTACK half of a doshfunc frame — the push at
c:Src/exec.c:6005-6016 and the pop at c:6218-6219 — and nothing else of
that prologue.
It is deliberately NOT doshfunc itself. doshfunc also bumps
locallevel, and comptags is indexed by that level
(Src/Zle/computil.c:3782). The ports that call _impl bodies pair their
own inc_locallevel/dec_locallevel around a _tags registration and the
comptags -A lookup that consumes it; a second bump landing between them
splits that pair. _message.rs records that dispatching there also flips
fourteen tests (dash_e_registers_its_own_tag_level,
default_mode_registers_the_messages_tag, and eleven _x_*
routes_to_message_*), which is why the level is managed by hand and only
the frame is restored here.
Why the frame has to exist at all: _next_label sh:9 (and _all_labels
sh:27) gate their _comp_tags strip on (( $#funcstack > _tags_level )).
A raw _next_label_impl call leaves $#funcstack one short, so that guard
is unobservable and a tag zsh drops survives.
The FUNCSTACK half of a doshfunc frame, for a port that deliberately
calls a sibling port’s raw _impl body instead of dispatching.
doshfunc pushes one FS_FUNC frame per shell-function call
(Src/exec.c:6005-6016) and pops it on the way out (c:6218-6219).
call_compfn gets that for free; a raw _impl call does not, and
call_compfn’s own contract says the caller “must supply the missing piece
inside its own fallback closure rather than assume this helper does it”.
The missing frame is not cosmetic. _next_label sh:9 and _all_labels
sh:27 gate their _comp_tags strip on (( $#funcstack > _tags_level )),
so a callee running one frame shallower than zsh’s silently keeps a tag
zsh drops. Measured on _arguments : '1::optional delimiter:(\:)' '*:spec'
(an empty rest action, which sh:413-417 routes to _message -e):
zsh _tags_level=9 _comp_tags=' argument-rest '
zshrs _tags_level=8 _comp_tags=' argument-1 argument-rest 'This guard supplies ONLY the funcstack frame. It deliberately does not go
through doshfunc, which would also bump locallevel — comptags is
indexed by that level (Src/Zle/computil.c:3782), and the ports that call
_impl bodies pair their own inc_locallevel/dec_locallevel around the
registration and its lookup. Adding a second bump between them would split
that pair.
Implementations§
Trait Implementations§
Source§impl Drop for PortFuncstackFrame
impl Drop for PortFuncstackFrame
Auto Trait Implementations§
impl Freeze for PortFuncstackFrame
impl RefUnwindSafe for PortFuncstackFrame
impl Send for PortFuncstackFrame
impl Sync for PortFuncstackFrame
impl Unpin for PortFuncstackFrame
impl UnsafeUnpin for PortFuncstackFrame
impl UnwindSafe for PortFuncstackFrame
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<F, W, T, D> Deserialize<With<T, W>, D> for F
impl<F, W, T, D> Deserialize<With<T, W>, D> for F
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more