pub struct Kernel { /* private fields */ }Expand description
The Kernel (核) — executes kaish code.
This is the primary interface for running kaish commands. It owns all the runtime state: variables, tools, VFS, jobs, and persistence.
Implementations§
Source§impl Kernel
impl Kernel
Sourcepub fn new(config: KernelConfig) -> Result<Self>
pub fn new(config: KernelConfig) -> Result<Self>
Create a new kernel with the given configuration.
Sourcepub fn with_backend(
backend: Arc<dyn KernelBackend>,
config: KernelConfig,
configure_vfs: impl FnOnce(&mut VfsRouter),
configure_tools: impl FnOnce(&mut ToolRegistry),
) -> Result<Self>
pub fn with_backend( backend: Arc<dyn KernelBackend>, config: KernelConfig, configure_vfs: impl FnOnce(&mut VfsRouter), configure_tools: impl FnOnce(&mut ToolRegistry), ) -> Result<Self>
Create a kernel with a custom backend and /v/* virtual path support.
This is the constructor for embedding kaish in other systems that provide their own storage backend (e.g., CRDT-backed storage in kaijutsu).
A VirtualOverlayBackend routes paths automatically:
/v/*→ Internal VFS (JobFs at/v/jobs, MemoryFs at/v/blobs)/dev→ DevFs (synthetic/dev/null,/dev/zero,/dev/random,/dev/urandom) — kernel-owned so it works even when your backend is read-only- Everything else → Your custom backend
The optional configure_vfs closure lets you add additional virtual mounts
(e.g., /v/docs for CRDT blocks) after the built-in mounts are set up.
Note: The config’s vfs_mode is ignored — all non-/v/* path routing
is handled by your custom backend. The config is only used for name, cwd,
skip_validation, and interactive.
§Example
// Simple: default /v/* mounts only
let kernel = Kernel::with_backend(backend, config, |_| {}, |_| {})?;
// With custom mounts
let kernel = Kernel::with_backend(backend, config, |vfs| {
vfs.mount_arc("/v/docs", docs_fs);
vfs.mount_arc("/v/g", git_fs);
}, |_| {})?;
// With custom tools
let kernel = Kernel::with_backend(backend, config, |_| {}, |tools| {
tools.register(MyCustomTool::new());
})?;Sourcepub fn plan_program(
&self,
source: &str,
) -> Result<Vec<PlannedStatement>, Vec<ParseError>>
pub fn plan_program( &self, source: &str, ) -> Result<Vec<PlannedStatement>, Vec<ParseError>>
Plan every statement of source without executing anything —
plan_program as a method, so an
embedder holding a kernel can pair the plans with get_var lookups
against this kernel’s live state.
§Errors
Returns the parse errors when source does not parse.
Sourcepub fn expand_fragment(
&self,
source: &str,
addr: FragmentAddr,
scope: &[(String, Value)],
) -> Result<Expansion, FragmentError>
pub fn expand_fragment( &self, source: &str, addr: FragmentAddr, scope: &[(String, Value)], ) -> Result<Expansion, FragmentError>
Expand one heredoc body against a scope the caller supplies —
expand_fragment as a method.
The scope is the caller’s, not this kernel’s: pair it with get_var
when the session’s values are the ones to judge against, and supply
different values when they are not. Nothing executes, and a $(…) in
the body comes back as a Hole rather than
running here.
§Errors
Returns a FragmentError when the
source does not parse, the address names no heredoc, or the body reads
something the supplied scope does not carry.
Sourcepub fn into_arc(self) -> Arc<Self> ⓘ
pub fn into_arc(self) -> Arc<Self> ⓘ
Wrap this Kernel in an Arc and initialize its self-reference.
This enables the Kernel to hand out Arc<dyn CommandDispatcher> references
to child contexts, allowing builtins like timeout to dispatch inner
commands through the full resolution chain (user tools → builtins →
.kai scripts → external commands).
Sourcepub async fn fork(&self) -> Arc<Self> ⓘ
pub async fn fork(&self) -> Arc<Self> ⓘ
Fork a subsidiary kernel for concurrent execution.
The fork is a fully-functional Kernel that:
- Snapshots per-session state from the parent: scope (COW — cheap), user-defined tools, cwd, aliases, ignore config, etc. Mutations on the fork do NOT propagate back to the parent — matching bash subshell / background-job semantics.
- Shares read-mostly resources with the parent via
Arc: the tool registry, the VFS router, and the job manager. A job registered by the fork is visible to the parent’sjobsbuiltin, and the fork sees the same VFS mounts. - Owns its own
stderr_receiver,cancel_token, andexecute_lock. It is never the TTY owner, sointeractiveisfalseandterminal_stateisNone.
The returned Arc has its self_weak populated (via into_arc), so
nested dispatch through ctx.dispatcher (e.g. the timeout builtin)
routes through the fork itself, not the parent — which is essential
for concurrency safety.
Use this for detached background concurrency where the fork should
survive parent cancellation: the & background-job operator and any
other “fire and forget” worker. The fork gets a fresh, independent
cancellation token.
For foreground concurrency (scatter workers, concurrent pipeline
stages, $(...) cmdsubs) where parent timeout/cancel must cascade
into the fork’s external children, use Self::fork_attached.
Sourcepub async fn fork_attached(&self) -> Arc<Self> ⓘ
pub async fn fork_attached(&self) -> Arc<Self> ⓘ
Fork attached to the parent’s cancellation.
Same as Self::fork but the fork’s cancel_token is a child of
the parent’s. When the parent cancels (request timeout, embedder
Kernel::cancel, etc.), the fork’s token also cancels, which in
turn kills any external children spawned in the fork via the
wait_or_kill / SIGTERM-grace-SIGKILL path.
Sourcepub async fn fork_for_background(
&self,
cancel: CancellationToken,
job_id: JobId,
) -> Arc<Self> ⓘ
pub async fn fork_for_background( &self, cancel: CancellationToken, job_id: JobId, ) -> Arc<Self> ⓘ
Fork for a background job, stamping the job id so external commands
spawned anywhere beneath it record their process groups on that job
(for kill -<sig> %N). The caller owns cancel so it can also drive
JobManager::cancel.
Sourcepub fn dispatcher(&self) -> Option<Arc<dyn CommandDispatcher>>
pub fn dispatcher(&self) -> Option<Arc<dyn CommandDispatcher>>
Get an Arc<dyn CommandDispatcher> to this Kernel, if wrapped via into_arc().
Returns None if the Kernel was not wrapped, or if all strong references
have been dropped (the Weak can no longer upgrade).
Sourcepub fn set_trash_backend(&mut self, backend: Option<Arc<dyn TrashBackend>>)
pub fn set_trash_backend(&mut self, backend: Option<Arc<dyn TrashBackend>>)
Replace or remove the trash backend used by rm and kaish-trash.
The kernel installs the OS trash (SystemTrash) automatically when
built with the os-integration feature. Embedders and tests can swap
in a custom crate::trash::TrashBackend, or pass None to remove
it — with trash enabled but no backend present, rm fails loud
rather than falling through to permanent delete.
Sourcepub fn cancel(&self)
pub fn cancel(&self)
Cancel the current execution.
This cancels the current cancellation token, causing any execution
loop to exit at the next checkpoint with exit code 130 (SIGINT).
A fresh token is installed for the next execute() call.
Sourcepub fn is_cancelled(&self) -> bool
pub fn is_cancelled(&self) -> bool
Check if the current execution has been cancelled.
Also the polling point for ExecuteOptions::interrupt: when the
embedder’s check reports true, the internal token fires here, so every
call site of this method is an interrupt checkpoint for free.
Sourcepub async fn execute(&self, input: &str) -> Result<ExecResult, KernelError>
pub async fn execute(&self, input: &str) -> Result<ExecResult, KernelError>
Execute kaish source code with default options.
Equivalent to execute_with_options(input, ExecuteOptions::default()).
Returns the result of the last statement executed.
§Errors
Returns KernelError when the program was rejected before running
(a lex/parse failure or a validator rejection) or faulted while
running. See KernelError::is_rejected to route on that
distinction. A nonzero exit from the script itself — a failed
command, set -e — is not an Err; it comes back as Ok with the
exit code folded into the returned ExecResult.
Sourcepub async fn execute_argv(
&self,
name: &str,
argv: &[Value],
) -> Result<ExecResult, KernelError>
pub async fn execute_argv( &self, name: &str, argv: &[Value], ) -> Result<ExecResult, KernelError>
Argv-native peer of Self::execute — run one command whose arguments
are already tokenized.
execute(&str) is string-native: it lexes and parses its input. A caller
that already holds OS/structured argv (a busybox-style multicall binary, a
structured embedder like kaijutsu) would otherwise have to re-quote argv
into a string just to have the lexer split it apart again — a round-trip
that is lossy for typed values, since to_argv() stringifies
Value::Bytes/Value::Json. execute_argv skips it.
Tokens are literal. No glob expansion, no $VAR interpolation, no
command substitution, no word splitting — the “single-quoted word”
semantics taken to its end. execute_argv("echo", &[Value::String("*.txt" .into())]) emits *.txt; it does not glob. (One shared-binder expansion
does still apply, for consistency with the string door: a leading ~ is
expanded against the session HOME — kaish expands ~ uniformly, so the
two doors agree. Pass a pre-resolved path if you need it byte-literal.) A
non-string Value
(Bytes/Json/Int) lands directly in ToolArgs.positional, so typed
data survives without a to_argv() round-trip. (Caveat: the two-layer
clap arg model means a builtin that re-parses its own to_argv() still
sees a stringified value; the typed-passthrough win fully lands only for
builtins that read args.positional directly — the documented pattern.)
This is a peer, not a subset: a command string can carry pipelines,
&&/||, control flow and $() that have no argv encoding, so the two
doors converge late (at the shared dispatch chain) rather than one
wrapping the other. From argv classification onward execute_argv reuses
the exact path a Stmt::Command takes — command resolution (aliases, user
tools, .kai scripts, externals, backend tools), arg binding, and the
--json transform — so an ls --json still applies output formatting. The kernel’s
pre-execution syntax validator does not run: argv has no shell syntax to
validate (a tool’s own validate()/clap parse still runs at dispatch).
Concurrent callers serialize on the same execute lock as Self::execute,
and the kernel’s configured request_timeout applies (a hung builtin or
external is interrupted at the deadline with exit code 124, the same as the
string door). There is no per-call options surface yet — a future
execute_argv_with_options would carry per-call timeout/cancel/vars/cwd.
§Errors
Returns KernelError, always KernelError::Execution — argv has
no shell syntax to reject, so execute_argv never returns
KernelError::Parse or KernelError::Validation (a tool’s own
validate()/clap parse at dispatch still surfaces here, as an
execution failure).
Sourcepub async fn execute_with_options(
&self,
input: &str,
opts: ExecuteOptions,
) -> Result<ExecResult, KernelError>
pub async fn execute_with_options( &self, input: &str, opts: ExecuteOptions, ) -> Result<ExecResult, KernelError>
Execute with per-call options. The primary entry point for embedders that don’t need per-statement output streaming.
opts carries timeout, transient vars overlay, optional cwd override,
and optional embedder-owned cancellation token. See ExecuteOptions
for semantics. For streaming, use Self::execute_with_options_streaming.
Cancellation: if opts.cancel_token is Some, it is raced
against the kernel’s internal token. Either firing cancels and kills
external children. The embedder’s token is read-only — kernel
timeouts do NOT propagate into it. Distinguish via the returned
code: 124 = timeout, 130 = cancellation.
Timeout: opts.timeout overrides KernelConfig::request_timeout.
Some(Duration::ZERO) returns 124 immediately without spawning.
Concurrent callers on the same Kernel serialize on the kernel-wide
execute lock. For true parallelism, call Kernel::fork (detached)
or Kernel::fork_attached (cancellation cascades from this kernel).
§Errors
Returns KernelError when the program was rejected before running
or faulted while running — see KernelError::is_rejected.
Sourcepub async fn execute_with_options_streaming(
&self,
input: &str,
opts: ExecuteOptions,
on_output: &mut (dyn FnMut(&ExecResult) + Send),
) -> Result<ExecResult, KernelError>
pub async fn execute_with_options_streaming( &self, input: &str, opts: ExecuteOptions, on_output: &mut (dyn FnMut(&ExecResult) + Send), ) -> Result<ExecResult, KernelError>
Same as Self::execute_with_options but with a per-statement output
callback. The callback fires after each top-level statement so the
embedder (REPL, MCP streaming) can flush output incrementally.
§Errors
Sourcepub async fn execute_with_pipe_stdin(
&self,
input: &str,
opts: ExecuteOptions,
pipe_stdin: PipeReader,
) -> Result<ExecResult, KernelError>
pub async fn execute_with_pipe_stdin( &self, input: &str, opts: ExecuteOptions, pipe_stdin: PipeReader, ) -> Result<ExecResult, KernelError>
Execute with a lazy standard input fed as a PipeReader.
Unlike ExecuteOptions::with_stdin (a pre-read buffer), this never
forces the input to be drained before execution: the reader seeds the
first top-level command’s pipe_stdin, and a command that does not read
stdin (echo) returns without touching it. This is the seam a
non-interactive frontend uses to forward an open process stdin without
hanging on a pipe that never sends EOF (sleep 10 | kaish -c 'echo hi').
Embedders that already hold a complete buffer (text or binary) should
prefer the simpler ExecuteOptions::with_stdin path instead.
§Errors
Sourcepub async fn execute_with_pipe_stdin_streaming(
&self,
input: &str,
opts: ExecuteOptions,
pipe_stdin: PipeReader,
on_output: &mut (dyn FnMut(&ExecResult) + Send),
) -> Result<ExecResult, KernelError>
pub async fn execute_with_pipe_stdin_streaming( &self, input: &str, opts: ExecuteOptions, pipe_stdin: PipeReader, on_output: &mut (dyn FnMut(&ExecResult) + Send), ) -> Result<ExecResult, KernelError>
Streaming counterpart to Self::execute_with_pipe_stdin — the REPL
-c/script frontend uses this to print output incrementally while
feeding a lazy process-stdin pipe.
§Errors
Sourcepub async fn execute_with_vars(
&self,
input: &str,
vars: HashMap<String, Value>,
) -> Result<ExecResult, KernelError>
👎Deprecated: use Kernel::execute_with_options with ExecuteOptions::with_vars
pub async fn execute_with_vars( &self, input: &str, vars: HashMap<String, Value>, ) -> Result<ExecResult, KernelError>
use Kernel::execute_with_options with ExecuteOptions::with_vars
Execute kaish source code with a transient overlay of exported variables.
Deprecated thin wrapper over Self::execute_with_options. New code
should use that method directly:
execute_with_options(input, ExecuteOptions::new().with_vars(vars)).
Sourcepub async fn execute_streaming(
&self,
input: &str,
on_output: &mut (dyn FnMut(&ExecResult) + Send),
) -> Result<ExecResult, KernelError>
👎Deprecated: use Kernel::execute_with_options_streaming
pub async fn execute_streaming( &self, input: &str, on_output: &mut (dyn FnMut(&ExecResult) + Send), ) -> Result<ExecResult, KernelError>
use Kernel::execute_with_options_streaming
Execute kaish source code with a per-statement callback.
Deprecated thin wrapper. New code should use
Self::execute_with_options_streaming.
Sourcepub async fn set_positional(
&self,
script_name: impl Into<String>,
args: Vec<String>,
)
pub async fn set_positional( &self, script_name: impl Into<String>, args: Vec<String>, )
Set positional parameters ($0 script name and $1-$9 args).
Sourcepub async fn exported_vars(&self) -> Vec<(String, Value)>
pub async fn exported_vars(&self) -> Vec<(String, Value)>
List exported variables (name, value), sorted by name. These are the
vars a child process would see (see dispatch’s hermetic env build).
Sourcepub async fn try_set_cwd(&self, path: PathBuf) -> bool
pub async fn try_set_cwd(&self, path: PathBuf) -> bool
Set the working directory only if path resolves to a directory in the
kernel’s backend — the same namespace cd validates against. Unlike a
raw host-FS is_dir() check, this correctly accepts virtual mounts
(/v/docs, in-memory scratch, …) and rejects real paths that have since
disappeared. Returns whether the cwd was changed.
Sourcepub async fn last_result(&self) -> ExecResult
pub async fn last_result(&self) -> ExecResult
Get the last result ($?).
Sourcepub async fn has_function(&self, name: &str) -> bool
pub async fn has_function(&self, name: &str) -> bool
Check if a user-defined function exists.
Sourcepub fn tool_schemas(&self) -> Vec<ToolSchema>
pub fn tool_schemas(&self) -> Vec<ToolSchema>
Get available tool schemas.
Sourcepub async fn classify_command(&self, name: &str) -> CommandKind
pub async fn classify_command(&self, name: &str) -> CommandKind
Classify how the kernel will resolve a command name.
This is the supported, single source of truth for command resolution that
embedders should call instead of re-deriving the rules. Walk a parsed
script (kaish_kernel::parser::parse → Stmt::Command nodes) and call
this per command name to bucket each into builtin / user-function /
special-form / dynamic / external — for example a consent gate that blocks
a script until external commands are approved.
The classification mirrors the interpreter’s real resolution order
(execute_command_depth): special-forms (true/false/source/.)
short-circuit first, then aliases are expanded (bounded recursion,
re-checking special-forms each step, exactly as execution does), then user
functions (which shadow builtins), then builtins, then a PATH lookup. A
name that is a variable or command-substitution expansion ($cmd,
$(pick), ${x}) classifies as CommandKind::Dynamic because it can’t
be resolved statically.
Aliases are resolved against the kernel’s current alias table, so an
alias cat=/bin/something makes cat classify as External — the same
thing it would actually run. The safe direction of any residual imprecision
is External/Dynamic, never a false “internal”: the /v/bin/ prefix and
.kai/backend-tool resolution are reported External even though some of
those resolve in-process, so a consent gate over-gates rather than letting
a PATH escape slip through.
Sourcepub fn jobs(&self) -> Arc<JobManager> ⓘ
pub fn jobs(&self) -> Arc<JobManager> ⓘ
Get job manager.
Sourcepub async fn reset(&self) -> Result<()>
pub async fn reset(&self) -> Result<()>
Reset kernel to initial state.
Clears in-memory variables and resets cwd to root. History is not
cleared (it persists across resets). The kernel’s $$ identity, the
trash-on-delete configuration, the current errexit state, and any
frontend-seeded initial_vars (HOME/PATH/etc, from KernelConfig)
are re-applied to the fresh scope rather than silently reverting to
defaults — an embedder that opted into trash or errexit must not find
either quietly disabled after a reset() between requests.
Background jobs are untouched (GH #245) — reset() is a scope/cwd
reset, not a session boundary for &. A job started before reset()
keeps running, stays in jobs, and the job ID counter keeps counting
up. An embedder treating reset() as “new session” (a fresh MCP
conversation reusing one kernel, say) inherits every job the previous
conversation backgrounded — call Self::cancel_all_jobs first if
that inheritance is not wanted.
Sourcepub async fn cancel_all_jobs(&self) -> usize
pub async fn cancel_all_jobs(&self) -> usize
Trip the cancellation token of every tracked background job (&) —
whether or not shutdown follows.
This is the same lever kill %N uses: a running job’s in-process
future exits at its next checkpoint, and any external children it
spawned get the SIGTERM→SIGKILL cascade; it then stays tracked with
status Killed once it unwinds. For an already-finished job the
token trip is a no-op — its future has already resolved and the job
keeps reporting its terminal status. This only
starts cancellation, it does not wait (pair with
JobManager::wait/wait_all if the caller needs to block on the
unwind, bounded as Self::shutdown does).
A job registered by an embedder via JobManager::register with no
cancel token attached has no lever to cancel — silently skipped here,
same as kill %N’s own “no cancellation token” case.
Returns how many jobs a token was actually tripped for.
Sourcepub async fn shutdown(&self) -> Result<()>
pub async fn shutdown(&self) -> Result<()>
Shut down the kernel.
Cancels every tracked background job (Self::cancel_all_jobs), then
waits up to kill_grace + 3s per job — the same bound kill %N
gives a single target (GH #244) — for it to actually unwind. The
waits are sequential, so the worst case is additive: N jobs that all
ignore cancellation block shutdown for N × (kill_grace + 3s). Jobs
that unwind promptly (the normal case) cost only their own unwind
time. Before this fix shutdown called wait_all() with no timeout
at all: sleep 3600 & then shutdown() blocked for an hour (GH #245).
A job that has not unwound by its deadline is abandoned: logged via
tracing::warn! and left running detached until the tokio runtime
itself goes away. There is no further lever once shutdown() has
returned — this method does not hang, but it also does not guarantee
every job actually stopped.
Takes &self, not owned self — an embedder holding Arc<Kernel>
(e.g. kaish-client’s EmbeddedClient) can call this without
Arc::try_unwrap, since the work here only touches the shared
Arc<JobManager>, never kernel state that would need exclusive
ownership.
Trait Implementations§
Source§impl CommandDispatcher for Kernel
impl CommandDispatcher for Kernel
Source§fn dispatch<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
cmd: &'life1 Command,
ctx: &'life2 mut ExecContext,
) -> Pin<Box<dyn Future<Output = Result<ExecResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn dispatch<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
cmd: &'life1 Command,
ctx: &'life2 mut ExecContext,
) -> Pin<Box<dyn Future<Output = Result<ExecResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Dispatch a command through the Kernel’s full resolution chain.
This is the single path for all command execution when called from the pipeline runner. It provides the full dispatch chain: user tools → builtins → .kai scripts → external commands → backend tools.
Source§fn dispatch_stmt<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
stmt: &'life1 Stmt,
ctx: &'life2 mut ExecContext,
) -> Pin<Box<dyn Future<Output = Result<ExecResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn dispatch_stmt<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
stmt: &'life1 Stmt,
ctx: &'life2 mut ExecContext,
) -> Pin<Box<dyn Future<Output = Result<ExecResult>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Run a compound pipeline stage through the kernel’s statement executor.
Source§fn eval_expr<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
expr: &'life1 Expr,
_ctx: &'life2 ExecContext,
) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn eval_expr<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
expr: &'life1 Expr,
_ctx: &'life2 ExecContext,
) -> Pin<Box<dyn Future<Output = Result<Value>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Evaluate an expression through the kernel’s async chain, including
command substitution. Delegates to eval_expr_async, which snapshots
the kernel’s scope/cwd and restores them after any $(...) runs, so
only command output escapes. The ctx is unused here because the
kernel evaluates against its own session state (a fork carries the
pipeline stage’s snapshot); var refs resolve against that scope.
Source§fn fork<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Arc<dyn CommandDispatcher>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn fork<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Arc<dyn CommandDispatcher>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Produce a forked dispatcher with independent mutable state (detached).
Calls the inherent Kernel::fork method (note the UFCS to avoid
recursing into the trait method we’re defining) and coerces the
returned Arc<Kernel> to Arc<dyn CommandDispatcher>.
Source§fn fork_attached<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Arc<dyn CommandDispatcher>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn fork_attached<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Arc<dyn CommandDispatcher>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Produce a forked dispatcher with cancellation cascading from this kernel.
Auto Trait Implementations§
impl !Freeze for Kernel
impl !RefUnwindSafe for Kernel
impl !UnwindSafe for Kernel
impl Send for Kernel
impl Sync for Kernel
impl Unpin for Kernel
impl UnsafeUnpin for Kernel
Blanket Implementations§
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
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
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> Pointable for T
impl<T> Pointable for T
Source§impl<T, S> SpanWrap<S> for Twhere
S: WrappingSpan<T>,
impl<T, S> SpanWrap<S> for Twhere
S: WrappingSpan<T>,
Source§fn with_span(self, span: S) -> <S as WrappingSpan<Self>>::Spanned
fn with_span(self, span: S) -> <S as WrappingSpan<Self>>::Spanned
WrappingSpan::make_wrapped to wrap an AST node in a span.