pub struct BodyTypes {
pub params: Vec<(String, Ty)>,
pub locals: BTreeMap<String, Ty>,
pub return_ty: Ty,
pub has_value_return: bool,
pub value_calls: Vec<ValueCallFact>,
pub array_remove_calls: Vec<TextRange>,
pub direct_call_arg_mismatches: Vec<DirectCallArgMismatch>,
pub typed_assign_mismatches: Vec<TypedAssignMismatch>,
pub field_assign_mismatches: Vec<FieldAssignMismatch>,
pub lambda_annotation_mismatches: Vec<LambdaAnnotationMismatch>,
pub ufcs_call_args: Vec<UfcsCallArgs>,
pub lambda_escapes: Vec<LambdaEscapeSlot>,
}Expand description
The full inferred picture of one def’s body: params, every local
(params ∪ temps) by name, and the return type. A superset of
InferredSig — signatures is the firewall-facing projection,
bodies is what a hover/diagnostic consumer (TM-5) wants.
Fields§
§params: Vec<(String, Ty)>§locals: BTreeMap<String, Ty>§return_ty: Ty§has_value_return: boolIssue #1028: whether the body contains at least one value-carrying
return <expr> anywhere — see [body::BodyResult::has_value_return]
(the field this one is copied from) for why return_ty.is_unknown()
alone can’t distinguish “never returns a value” (should infer void)
from “returns a value inference couldn’t pin down” (a real
Unknown-escape).
value_calls: Vec<ValueCallFact>T1c (docs/t1c-spec.md §4): statically-checkable facts about calls
through a value (a callee resolving to a param/temp/VAR/CONST
rather than a callable def) observed in this body, in source-walk
order. Recorded unconditionally during inference (the walk is the
only place argument expressions have types); reported only by
strict mode (strict::check — gradual stays advisory, the runtime
fault is its backstop, spec §3/§4).
array_remove_calls: Vec<TextRange>Issue #1532: every remove(a, i) call site in this body whose first
argument is statically known to be Ty::Array — see
body::BodyResult::array_remove_calls’s doc for why this is
captured (the pre-#1484 array leg remove no longer serves).
Reported only by strict mode (strict::check_array_remove_calls,
E149), the same split as value_calls.
direct_call_arg_mismatches: Vec<DirectCallArgMismatch>Issue #1864: statically-checkable argument-type mismatches at
direct call sites (h("hi"), resolving straight to a known
knot/stitch via known_sigs — never a call through a value, which
ValueCallFact/ValueCallKind::ArgMismatch already covers).
Recorded unconditionally during inference, like value_calls;
reported only by strict mode — gradual mode keeps deferring to the
existing runtime type-mismatch fault as its backstop.
Deliberately excludes an argument that is a bare Path
resolving to a Param/Temp in the caller’s own body — the exact
set InferPass::observe unconditionally joins the callee’s declared
param type into, right after this check runs (see
body::InferPass::infer_call’s doc for why). A genuine disagreement
there drives that local to Ty::Conflicted on its own, which
strict::check_escapes already reports as E066 — recording a
second fact here for the identical disagreement would double-report
it. A Path argument resolving to anything else (a literal, a
nested call’s return value, a global VAR/CONST, an index
expression, …) is unaffected by observe and stays fully checked.
typed_assign_mismatches: Vec<TypedAssignMismatch>Issue #1877 (the remainder of #1864 left after PR #1875’s direct-
call-argument half): statically-checkable type mismatches at a ~ temp name: T = expr declaration initializer (against its own
ascription) or a plain ~ name = expr assignment (against the
target’s already-known declared type — a VAR/CONST’s declaration-
derived type, or an annotated ~ temp’s ascription). A Param
assignment target never reaches this fact at all: a param
annotation is a signature-firewall slot annotations::mismatches
(E063) already owns (compared against the body’s final inferred
param type), so checking it again here would double-report the
identical disagreement. Recorded unconditionally during inference,
like direct_call_arg_mismatches; reported only by strict mode.
A Temp assignment target is excluded from this fact whenever
InferPass::observe’s own join (which runs right after, on every
assignment) is already about to drive that local to
Ty::Conflicted on its own — that disagreement is independently
reported as E066 by strict::check_escapes, so recording a second
fact here for it would double-report (mirrors
DirectCallArgMismatch’s own arg_is_observed_local exclusion, but
computed per-write rather than a blanket kind exclusion, since an
assignment to an as-yet-Unknown local never goes Conflicted and
would otherwise go unchecked entirely). That per-write guard is
order-sensitive — a later read of the same temp can independently
conflict it after a fact was already recorded — so
body::infer_def_body also drops, post-walk, any fact whose
target’s final type is Conflicted. See
body::InferPass::check_declared_assign_target’s doc.
field_assign_mismatches: Vec<FieldAssignMismatch>Issue #1900 (split from #1864/#1877): a dotted struct-field
assignment target (~ p.x = expr), with the root’s declared type
resolved but the field chain past it left unresolved (no shape table
in this module — see FieldAssignMismatch’s own doc). Recorded
unconditionally during inference, like typed_assign_mismatches;
resolved and reported only by strict mode
(structs::check_assignments, E063).
lambda_annotation_mismatches: Vec<LambdaAnnotationMismatch>Issue #1994 (RULED 2026-08-01, closing #1932): a lambda’s own
written param/return annotation disagreeing with its body-derived
type — see LambdaAnnotationMismatch’s own doc for why this is a
materially different severity posture from typed_assign_mismatches/
field_assign_mismatches above (an eager Error, not a gradual
E063 advisory). Recorded unconditionally during inference, folded
in from every lambda anywhere in this body (including nested ones);
reported only by strict mode (strict::check_lambda_annotation_ mismatches, E174).
ufcs_call_args: Vec<UfcsCallArgs>Issue #1881: per-call-site written-argument types for every
UFCS-shaped (multi-segment, receiver-resolving) callee found in this
body — see UfcsCallArgs’s own doc for why this pass records raw
argument types here rather than checking them itself (the receiver
resolves to a value, so this pass’s own callee resolution can never
see the desugared free function’s declared param types the way
brink_analyzer::ufcs’s resolution pass can). Recorded
unconditionally, like direct_call_arg_mismatches; consumed by
ufcs::UfcsVisitor, reported only by strict mode
(ufcs::check_strict, E063).
lambda_escapes: Vec<LambdaEscapeSlot>Issue #1770: see LambdaEscapeSlot. Recorded unconditionally,
folded in from every lambda anywhere in this body (including nested
ones) exactly like lambda_annotation_mismatches; reported only by
strict mode (strict::check_def, the same E065/E066 codes a
top-level def’s own params/temps already use).
Trait Implementations§
impl Eq for BodyTypes
impl StructuralPartialEq for BodyTypes
Auto Trait Implementations§
impl Freeze for BodyTypes
impl RefUnwindSafe for BodyTypes
impl Send for BodyTypes
impl Sync for BodyTypes
impl Unpin for BodyTypes
impl UnsafeUnpin for BodyTypes
impl UnwindSafe for BodyTypes
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.