pub struct ExprUseVisitor<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> {
cx: Cx,
delegate: RefCell<D>,
upvars: Option<&'tcx FxIndexMap<HirId, Upvar>>,
}
Expand description
A visitor that reports how each expression is being used.
See module-level docs and Delegate
for details.
Fields§
§cx: Cx
§delegate: RefCell<D>
We use a RefCell
here so that delegates can mutate themselves, but we can
still have calls to our own helper functions.
upvars: Option<&'tcx FxIndexMap<HirId, Upvar>>
Implementations§
Source§impl<'a, 'tcx, D: Delegate<'tcx>> ExprUseVisitor<'tcx, (&'a LateContext<'tcx>, LocalDefId), D>
impl<'a, 'tcx, D: Delegate<'tcx>> ExprUseVisitor<'tcx, (&'a LateContext<'tcx>, LocalDefId), D>
pub fn for_clippy( cx: &'a LateContext<'tcx>, body_def_id: LocalDefId, delegate: D, ) -> Self
Source§impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D>
Sourcepub(crate) fn new(cx: Cx, delegate: D) -> Self
pub(crate) fn new(cx: Cx, delegate: D) -> Self
Creates the ExprUseVisitor, configuring it with the various options provided:
delegate
– who receives the callbacksparam_env
— parameter environment for trait lookups (esp. pertaining toCopy
)typeck_results
— typeck results for the code being analyzed
pub fn consume_body(&self, body: &Body<'_>) -> Result<(), Cx::Error>
fn consume_or_copy( &self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, )
pub fn consume_clone_or_copy( &self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, )
fn consume_exprs(&self, exprs: &[Expr<'_>]) -> Result<(), Cx::Error>
pub fn consume_expr(&self, expr: &Expr<'_>) -> Result<(), Cx::Error>
pub fn consume_or_clone_expr(&self, expr: &Expr<'_>) -> Result<(), Cx::Error>
fn mutate_expr(&self, expr: &Expr<'_>) -> Result<(), Cx::Error>
fn borrow_expr(&self, expr: &Expr<'_>, bk: BorrowKind) -> Result<(), Cx::Error>
pub fn walk_expr(&self, expr: &Expr<'_>) -> Result<(), Cx::Error>
fn walk_stmt(&self, stmt: &Stmt<'_>) -> Result<(), Cx::Error>
fn maybe_read_scrutinee<'t>( &self, discr: &Expr<'_>, discr_place: PlaceWithHirId<'tcx>, pats: impl Iterator<Item = &'t Pat<'t>>, ) -> Result<(), Cx::Error>
fn walk_local<F>( &self, expr: &Expr<'_>, pat: &Pat<'_>, els: Option<&Block<'_>>, f: F, ) -> Result<(), Cx::Error>
Sourcefn walk_block(&self, blk: &Block<'_>) -> Result<(), Cx::Error>
fn walk_block(&self, blk: &Block<'_>) -> Result<(), Cx::Error>
Indicates that the value of blk
will be consumed, meaning either copied or moved
depending on its type.
fn walk_struct_expr<'hir>( &self, fields: &[ExprField<'_>], opt_with: &StructTailExpr<'hir>, ) -> Result<(), Cx::Error>
Sourcefn walk_adjustment(&self, expr: &Expr<'_>) -> Result<(), Cx::Error>
fn walk_adjustment(&self, expr: &Expr<'_>) -> Result<(), Cx::Error>
Invoke the appropriate delegate calls for anything that gets consumed or borrowed as part of the automatic adjustment process.
Sourcefn walk_autoref(
&self,
expr: &Expr<'_>,
base_place: &PlaceWithHirId<'tcx>,
autoref: &AutoBorrow,
)
fn walk_autoref( &self, expr: &Expr<'_>, base_place: &PlaceWithHirId<'tcx>, 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.
fn walk_arm( &self, discr_place: &PlaceWithHirId<'tcx>, arm: &Arm<'_>, ) -> Result<(), Cx::Error>
Sourcefn walk_irrefutable_pat(
&self,
discr_place: &PlaceWithHirId<'tcx>,
pat: &Pat<'_>,
) -> Result<(), Cx::Error>
fn walk_irrefutable_pat( &self, discr_place: &PlaceWithHirId<'tcx>, pat: &Pat<'_>, ) -> Result<(), Cx::Error>
Walks a pat that occurs in isolation (i.e., top-level of fn argument or let binding, and not a match arm or nested pat.)
Sourcefn walk_pat(
&self,
discr_place: &PlaceWithHirId<'tcx>,
pat: &Pat<'_>,
has_guard: bool,
) -> Result<(), Cx::Error>
fn walk_pat( &self, discr_place: &PlaceWithHirId<'tcx>, pat: &Pat<'_>, has_guard: bool, ) -> Result<(), Cx::Error>
The core driver for walking a pattern
Sourcefn walk_captures(&self, closure_expr: &Closure<'_>) -> Result<(), Cx::Error>
fn walk_captures(&self, closure_expr: &Closure<'_>) -> Result<(), Cx::Error>
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§impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D>
The job of the methods whose name starts with cat_
is to analyze
expressions and construct the corresponding Place
s. The cat
stands for “categorize”, this is a leftover from long ago when
places were called “categorizations”.
impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx, Cx, D>
The job of the methods whose name starts with cat_
is to analyze
expressions and construct the corresponding Place
s. 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.
fn expect_and_resolve_type( &self, id: HirId, ty: Option<Ty<'tcx>>, ) -> Result<Ty<'tcx>, Cx::Error>
fn node_ty(&self, hir_id: HirId) -> Result<Ty<'tcx>, Cx::Error>
fn expr_ty(&self, expr: &Expr<'_>) -> Result<Ty<'tcx>, Cx::Error>
fn expr_ty_adjusted(&self, expr: &Expr<'_>) -> Result<Ty<'tcx>, Cx::Error>
Sourcefn pat_ty_adjusted(&self, pat: &Pat<'_>) -> Result<Ty<'tcx>, Cx::Error>
fn pat_ty_adjusted(&self, pat: &Pat<'_>) -> Result<Ty<'tcx>, Cx::Error>
Returns the type of value that this pattern matches against. Some non-obvious cases:
- a
ref x
binding matches against a value of typeT
and givesx
the type&T
; we returnT
. - 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>
).
Sourcefn pat_ty_unadjusted(&self, pat: &Pat<'_>) -> Result<Ty<'tcx>, Cx::Error>
fn pat_ty_unadjusted(&self, pat: &Pat<'_>) -> Result<Ty<'tcx>, Cx::Error>
Like Self::pat_ty_adjusted
, but ignores implicit &
patterns.
fn cat_expr(&self, expr: &Expr<'_>) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
Sourcefn cat_expr_(
&self,
expr: &Expr<'_>,
adjustments: &[Adjustment<'tcx>],
) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
fn cat_expr_( &self, expr: &Expr<'_>, adjustments: &[Adjustment<'tcx>], ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
This recursion helper avoids going through too many adjustments, since only non-overloaded deref recurses.
fn cat_expr_adjusted( &self, expr: &Expr<'_>, previous: PlaceWithHirId<'tcx>, adjustment: &Adjustment<'tcx>, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
fn cat_expr_adjusted_with<F>( &self, expr: &Expr<'_>, previous: F, adjustment: &Adjustment<'tcx>, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
fn cat_expr_unadjusted( &self, expr: &Expr<'_>, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
fn cat_res( &self, hir_id: HirId, span: Span, expr_ty: Ty<'tcx>, res: Res, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
Sourcefn cat_upvar(
&self,
hir_id: HirId,
var_id: HirId,
) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
fn cat_upvar( &self, hir_id: HirId, var_id: HirId, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
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.
fn cat_rvalue(&self, hir_id: HirId, expr_ty: Ty<'tcx>) -> PlaceWithHirId<'tcx>
fn cat_projection( &self, node: HirId, base_place: PlaceWithHirId<'tcx>, ty: Ty<'tcx>, kind: ProjectionKind, ) -> PlaceWithHirId<'tcx>
fn cat_overloaded_place( &self, expr: &Expr<'_>, base: &Expr<'_>, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
fn cat_deref( &self, node: HirId, base_place: PlaceWithHirId<'tcx>, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
Sourcefn variant_index_for_adt(
&self,
qpath: &QPath<'_>,
pat_hir_id: HirId,
span: Span,
) -> Result<VariantIdx, Cx::Error>
fn variant_index_for_adt( &self, qpath: &QPath<'_>, pat_hir_id: HirId, span: Span, ) -> Result<VariantIdx, Cx::Error>
Returns the variant index for an ADT used within a Struct or TupleStruct pattern
Here pat_hir_id
is the HirId of the pattern itself.
Sourcefn total_fields_in_adt_variant(
&self,
pat_hir_id: HirId,
variant_index: VariantIdx,
span: Span,
) -> Result<usize, Cx::Error>
fn total_fields_in_adt_variant( &self, pat_hir_id: HirId, variant_index: VariantIdx, span: Span, ) -> Result<usize, Cx::Error>
Returns the total number of fields in an ADT variant used within a pattern.
Here pat_hir_id
is the HirId of the pattern itself.
Sourcefn total_fields_in_tuple(
&self,
pat_hir_id: HirId,
span: Span,
) -> Result<usize, Cx::Error>
fn total_fields_in_tuple( &self, pat_hir_id: HirId, span: Span, ) -> Result<usize, Cx::Error>
Returns the total number of fields in a tuple used within a Tuple pattern.
Here pat_hir_id
is the HirId of the pattern itself.
Sourcefn cat_pattern<F>(
&self,
place_with_id: PlaceWithHirId<'tcx>,
pat: &Pat<'_>,
op: &mut F,
) -> Result<(), Cx::Error>
fn cat_pattern<F>( &self, place_with_id: PlaceWithHirId<'tcx>, pat: &Pat<'_>, op: &mut F, ) -> Result<(), Cx::Error>
Here, place
is the PlaceWithHirId
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 PlaceWithHirId
that represents the path that will be taken
to reach the value being matched.
Sourcefn pat_deref_place(
&self,
hir_id: HirId,
base_place: PlaceWithHirId<'tcx>,
inner: &Pat<'_>,
target_ty: Ty<'tcx>,
) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
fn pat_deref_place( &self, hir_id: HirId, base_place: PlaceWithHirId<'tcx>, inner: &Pat<'_>, target_ty: Ty<'tcx>, ) -> Result<PlaceWithHirId<'tcx>, Cx::Error>
Represents the place matched on by a deref pattern’s interior.
fn is_multivariant_adt(&self, ty: Ty<'tcx>, span: Span) -> bool
Auto Trait Implementations§
impl<'tcx, Cx, D> DynSend for ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx, D> !DynSync for ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx, D> !Freeze for ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx, D> !RefUnwindSafe for ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx, D> Send for ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx, D> !Sync for ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx, D> Unpin for ExprUseVisitor<'tcx, Cx, D>
impl<'tcx, Cx, D> UnwindSafe for ExprUseVisitor<'tcx, Cx, D>where
Cx: UnwindSafe,
D: UnwindSafe,
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, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
Source§impl<T> Filterable for T
impl<T> Filterable for T
Source§fn filterable(
self,
filter_name: &'static str,
) -> RequestFilterDataProvider<T, fn(DataRequest<'_>) -> bool>
fn filterable( self, filter_name: &'static str, ) -> RequestFilterDataProvider<T, fn(DataRequest<'_>) -> bool>
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 moreSource§impl<P> IntoQueryParam<P> for P
impl<P> IntoQueryParam<P> for P
fn into_query_param(self) -> P
Source§impl<T> MaybeResult<T> for T
impl<T> MaybeResult<T> for T
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
Source§impl<I, T> UpcastFrom<I, T> for T
impl<I, T> UpcastFrom<I, T> for T
fn upcast_from(from: T, _tcx: I) -> T
Source§impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
default fn from_cycle_error( tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed, ) -> T
Source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
Source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
Source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<T> ErasedDestructor for Twhere
T: 'static,
Layout§
Note: Unable to compute type layout, possibly due to this type having generic parameters. Layout can only be computed for concrete, fully-instantiated types.