Skip to main content

ExprUseVisitor

Struct ExprUseVisitor 

Source
pub(crate) struct ExprUseVisitor<'a, 'db, D: Delegate<'db>> {
    cx: &'a mut InferenceContext<'db>,
    delegate: D,
    closure_expr: ExprId,
    upvars: UpvarsRef<'db>,
}
Expand description

A visitor that reports how each expression is being used.

See module-level docs and Delegate for details.

Fields§

§cx: &'a mut InferenceContext<'db>§delegate: D§closure_expr: ExprId§upvars: UpvarsRef<'db>

Implementations§

Source§

impl<'a, 'db, D: Delegate<'db>> ExprUseVisitor<'a, 'db, D>

Source

pub(crate) fn new( cx: &'a mut InferenceContext<'db>, closure_expr: ExprId, upvars: UpvarsRef<'db>, delegate: D, ) -> Self

Creates the ExprUseVisitor, configuring it with the various options provided:

  • delegate – who receives the callbacks
  • param_env — parameter environment for trait lookups (esp. pertaining to Copy)
  • typeck_results — typeck results for the code being analyzed
Source

pub(crate) fn consume_closure_body( &mut self, params: &[PatId], body: ExprId, ) -> Result<(), ErrorGuaranteed>

Source

fn consume_or_copy(&mut self, place_with_id: PlaceWithOrigin)

Source

pub(crate) fn consume_clone_or_copy(&mut self, place_with_id: PlaceWithOrigin)

Source

fn consume_exprs(&mut self, exprs: &[ExprId]) -> Result<(), ErrorGuaranteed>

Source

pub(crate) fn consume_expr( &mut self, expr: ExprId, ) -> Result<(), ErrorGuaranteed>

Source

fn mutate_expr(&mut self, expr: ExprId) -> Result<(), ErrorGuaranteed>

Source

fn borrow_expr( &mut self, expr: ExprId, bk: BorrowKind, ) -> Result<(), ErrorGuaranteed>

Source

pub(crate) fn walk_expr(&mut self, expr: ExprId) -> Result<(), ErrorGuaranteed>

Source

fn walk_stmt(&mut self, stmt: &Statement) -> Result<(), ErrorGuaranteed>

Source

fn fake_read_scrutinee(&mut self, discr_place: PlaceWithOrigin, refutable: bool)

Source

fn walk_local<F>( &mut self, expr: ExprId, pat: PatId, els: Option<ExprId>, f: F, ) -> Result<(), ErrorGuaranteed>
where F: FnMut(&mut Self) -> Result<(), ErrorGuaranteed>,

Source

fn walk_struct_expr( &mut self, fields: &[RecordLitField], spread: RecordSpread, ) -> Result<(), ErrorGuaranteed>

Source

fn expr_adjustments(&self, expr: ExprId) -> SmallVec<[Adjustment; 5]>

Source

fn pat_adjustments(&self, pat: PatId) -> SmallVec<[PatAdjustment; 5]>

Source

fn walk_adjustment(&mut self, expr: ExprId) -> Result<(), ErrorGuaranteed>

Invoke the appropriate delegate calls for anything that gets consumed or borrowed as part of the automatic adjustment process.

Source

fn walk_autoref( &mut self, expr: ExprId, base_place: PlaceWithOrigin, autoref: &AutoBorrow, )

Walks the autoref autoref applied to the autoderef’d expr. base_place is expr represented as a place, after all relevant autoderefs have occurred.

Source

fn walk_arm( &mut self, discr_place: PlaceWithOrigin, arm: &MatchArm, ) -> Result<(), ErrorGuaranteed>

Source

fn walk_pat( &mut self, discr_place: PlaceWithOrigin, pat: PatId, has_guard: bool, ) -> Result<(), ErrorGuaranteed>

The core driver for walking a pattern

This should mirror how pattern-matching gets lowered to MIR, as otherwise lowering will ICE when trying to resolve the upvars.

However, it is okay to approximate it here by doing more accesses than the actual MIR builder will, which is useful when some checks are too cumbersome to perform here. For example, if after typeck it becomes clear that only one variant of an enum is inhabited, and therefore a read of the discriminant is not necessary, walk_pat will have over-approximated the necessary upvar capture granularity.

Do note that discrepancies like these do still create obscure corners in the semantics of the language, and should be avoided if possible.

Source

fn walk_captures(&mut self, closure_expr: ExprId)

Handle the case where the current body contains a closure.

When the current body being handled is a closure, then we must make sure that

  • The parent closure only captures Places from the nested closure that are not local to it.

In the following example the closures c only captures p.x even though incr is a capture of the nested closure

struct P { x: i32 }
let mut p = P { x: 4 };
let c = || {
   let incr = 10;
   let nested = || p.x += incr;
};
  • When reporting the Place back to the Delegate, ensure that the UpvarId uses the enclosing closure as the DefId.
Source

fn error_reported_in_ty(&self, ty: Ty<'db>) -> Result<(), ErrorGuaranteed>

Source§

impl<'db, D: Delegate<'db>> ExprUseVisitor<'_, 'db, D>

The job of the methods whose name starts with cat_ is to analyze expressions and construct the corresponding Places. The cat stands for “categorize”, this is a leftover from long ago when places were called “categorizations”.

Note that a Place differs somewhat from the expression itself. For example, auto-derefs are explicit. Also, an index a[b] is decomposed into two operations: a dereference to reach the array data and then an index to jump forward to the relevant item.

Source

fn expect_and_resolve_type( &mut self, ty: Option<Ty<'db>>, ) -> Result<Ty<'db>, ErrorGuaranteed>

Source

fn node_ty(&mut self, id: ExprOrPatId) -> Result<Ty<'db>, ErrorGuaranteed>

Source

fn expr_ty(&mut self, expr: ExprId) -> Result<Ty<'db>, ErrorGuaranteed>

Source

fn expr_ty_adjusted(&mut self, expr: ExprId) -> Result<Ty<'db>, ErrorGuaranteed>

Source

fn pat_ty_adjusted(&mut self, pat: PatId) -> Result<Ty<'db>, ErrorGuaranteed>

Returns the type of value that this pattern matches against. Some non-obvious cases:

  • a ref x binding matches against a value of type T and gives x the type &T; we return T.
  • a pattern with implicit derefs (thanks to default binding modes #42640) may look like Some(x) but in fact have implicit deref patterns attached (e.g., it is really &Some(x)). In that case, we return the “outermost” type (e.g., &Option<T>).
Source

fn pat_ty_unadjusted(&mut self, pat: PatId) -> Result<Ty<'db>, ErrorGuaranteed>

Like Self::pat_ty_adjusted, but ignores implicit & patterns.

Source

fn cat_expr(&mut self, expr: ExprId) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Source

fn cat_expr_( &mut self, expr: ExprId, adjustments: &[Adjustment], ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

This recursion helper avoids going through too many adjustments, since only non-overloaded deref recurses.

Source

fn cat_expr_adjusted( &mut self, expr: ExprId, previous: PlaceWithOrigin, adjustment: &Adjustment, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Source

fn cat_expr_adjusted_with<F>( &mut self, expr: ExprId, previous: F, adjustment: &Adjustment, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>
where F: FnOnce(&mut Self) -> Result<PlaceWithOrigin, ErrorGuaranteed>,

Source

fn cat_expr_unadjusted( &mut self, expr: ExprId, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Source

fn cat_local( &mut self, id: ExprOrPatIdPacked, expr_ty: Ty<'db>, var_id: BindingId, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Source

fn cat_upvar( &mut self, hir_id: ExprOrPatIdPacked, var_id: BindingId, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Categorize an upvar.

Note: the actual upvar access contains invisible derefs of closure environment and upvar reference as appropriate. Only regionck cares about these dereferences, so we let it compute them as needed.

Source

fn cat_rvalue( &self, hir_id: ExprOrPatIdPacked, expr_ty: Ty<'db>, ) -> PlaceWithOrigin

Source

fn cat_projection( &self, node: ExprOrPatIdPacked, base_place: PlaceWithOrigin, ty: Ty<'db>, kind: ProjectionKind, ) -> PlaceWithOrigin

Source

fn cat_overloaded_place( &mut self, expr: ExprId, base: ExprId, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Source

fn cat_deref( &mut self, node: ExprOrPatIdPacked, base_place: PlaceWithOrigin, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Source

fn variant_index_for_adt( &self, pat_id: PatId, ) -> Result<(u32, VariantId), ErrorGuaranteed>

Returns the variant index for an ADT used within a Struct or TupleStruct pattern Here pat_hir_id is the ExprId of the pattern itself.

Source

fn total_fields_in_tuple(&mut self, pat_id: PatId) -> usize

Returns the total number of fields in a tuple used within a Tuple pattern. Here pat_hir_id is the ExprId of the pattern itself.

Source

fn cat_pattern<F>( &mut self, place_with_id: PlaceWithOrigin, pat: PatId, op: &mut F, ) -> Result<(), ErrorGuaranteed>

Here, place is the PlaceWithId being matched and pat is the pattern it is being matched against.

In general, the way that this works is that we walk down the pattern, constructing a PlaceWithId that represents the path that will be taken to reach the value being matched.

Source

fn pat_deref_place( &mut self, node: ExprOrPatIdPacked, base_place: PlaceWithOrigin, inner: PatId, target_ty: Ty<'db>, ) -> Result<PlaceWithOrigin, ErrorGuaranteed>

Represents the place matched on by a deref pattern’s interior.

Source

fn is_multivariant_adt(&mut self, node: ExprOrPatIdPacked, ty: Ty<'db>) -> bool

Checks whether a type has multiple variants, and therefore, whether a read of the discriminant might be necessary. Note that the actual MIR builder code does a more specific check, filtering out variants that happen to be uninhabited.

Here, it is not practical to perform such a check, because inhabitedness queries require typeck results, and typeck requires closure capture analysis.

Moreover, the language is moving towards uninhabited variants still semantically causing a discriminant read, so we shouldn’t perform any such check.

FIXME(never_patterns): update this comment once the aforementioned MIR builder code is changed to be insensitive to inhhabitedness.

Auto Trait Implementations§

§

impl<'a, 'db, D> Freeze for ExprUseVisitor<'a, 'db, D>
where D: Freeze,

§

impl<'a, 'db, D> !RefUnwindSafe for ExprUseVisitor<'a, 'db, D>

§

impl<'a, 'db, D> !Send for ExprUseVisitor<'a, 'db, D>

§

impl<'a, 'db, D> !Sync for ExprUseVisitor<'a, 'db, D>

§

impl<'a, 'db, D> Unpin for ExprUseVisitor<'a, 'db, D>
where D: Unpin,

§

impl<'a, 'db, D> UnsafeUnpin for ExprUseVisitor<'a, 'db, D>
where D: UnsafeUnpin,

§

impl<'a, 'db, D> !UnwindSafe for ExprUseVisitor<'a, 'db, D>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, R> CollectAndApply<T, R> for T

§

fn collect_and_apply<I, F>(iter: I, f: F) -> R
where I: Iterator<Item = T>, F: FnOnce(&[T]) -> R,

Equivalent to f(&iter.collect::<Vec<_>>()).

§

type Output = R

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> IntoBox<dyn Any> for T
where T: Any,

§

fn into_box(self) -> Box<dyn Any>

Convert self into the appropriate boxed form.
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Lookup<T> for T

§

fn into_owned(self) -> T

§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<I, T, U> Upcast<I, U> for T
where U: UpcastFrom<I, T>,

§

fn upcast(self, interner: I) -> U

§

impl<I, T> UpcastFrom<I, T> for T

§

fn upcast_from(from: T, _tcx: I) -> T

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more