@@ -30,8 +30,6 @@ use ty::BorrowKind::ImmBorrow;
3030
3131use crate :: fn_ctxt:: FnCtxt ;
3232
33- type McResult < T > = Result < T , ErrorGuaranteed > ;
34-
3533/// This trait defines the callbacks you can expect to receive when
3634/// employing the ExprUseVisitor.
3735pub trait Delegate < ' tcx > {
@@ -219,6 +217,8 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
219217/// This is the code that actually walks the tree.
220218pub struct ExprUseVisitor < ' tcx , Cx : TypeInformationCtxt < ' tcx > , D : Delegate < ' tcx > > {
221219 cx : Cx ,
220+ /// We use a `RefCell` here so that delegates can mutate themselves, but we can
221+ /// still have calls to our own helper functions.
222222 delegate : RefCell < D > ,
223223 upvars : Option < & ' tcx FxIndexMap < HirId , hir:: Upvar > > ,
224224}
@@ -517,14 +517,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
517517 discr : & Expr < ' _ > ,
518518 discr_place : PlaceWithHirId < ' tcx > ,
519519 pats : impl Iterator < Item = & ' t hir:: Pat < ' t > > ,
520- ) -> McResult < ( ) > {
520+ ) -> Result < ( ) , ErrorGuaranteed > {
521521 // Matching should not always be considered a use of the place, hence
522522 // discr does not necessarily need to be borrowed.
523523 // We only want to borrow discr if the pattern contain something other
524524 // than wildcards.
525525 let mut needs_to_be_read = false ;
526526 for pat in pats {
527- self . cat_pattern ( discr_place. clone ( ) , pat, |place, pat| {
527+ self . cat_pattern ( discr_place. clone ( ) , pat, & mut |place, pat| {
528528 match & pat. kind {
529529 PatKind :: Binding ( .., opt_sub_pat) => {
530530 // If the opt_sub_pat is None, then the binding does not count as
@@ -836,7 +836,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
836836 debug ! ( "walk_pat(discr_place={:?}, pat={:?}, has_guard={:?})" , discr_place, pat, has_guard) ;
837837
838838 let tcx = self . cx . tcx ( ) ;
839- return_if_err ! ( self . cat_pattern( discr_place. clone( ) , pat, |place, pat| {
839+ return_if_err ! ( self . cat_pattern( discr_place. clone( ) , pat, & mut |place, pat| {
840840 if let PatKind :: Binding ( _, canonical_id, ..) = pat. kind {
841841 debug!( "walk_pat: binding place={:?} pat={:?}" , place, pat) ;
842842 if let Some ( bm) =
@@ -1021,8 +1021,61 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10211021 }
10221022 }
10231023 }
1024+ }
10241025
1025- fn resolve_type_vars_or_error ( & self , id : HirId , ty : Option < Ty < ' tcx > > ) -> McResult < Ty < ' tcx > > {
1026+ /// The job of the categorization methods is to analyze an expression to
1027+ /// determine what kind of memory is used in evaluating it (for example,
1028+ /// where dereferences occur and what kind of pointer is dereferenced;
1029+ /// whether the memory is mutable, etc.).
1030+ ///
1031+ /// Categorization effectively transforms all of our expressions into
1032+ /// expressions of the following forms (the actual enum has many more
1033+ /// possibilities, naturally, but they are all variants of these base
1034+ /// forms):
1035+ /// ```ignore (not-rust)
1036+ /// E = rvalue // some computed rvalue
1037+ /// | x // address of a local variable or argument
1038+ /// | *E // deref of a ptr
1039+ /// | E.comp // access to an interior component
1040+ /// ```
1041+ /// Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
1042+ /// address where the result is to be found. If Expr is a place, then this
1043+ /// is the address of the place. If `Expr` is an rvalue, this is the address of
1044+ /// some temporary spot in memory where the result is stored.
1045+ ///
1046+ /// Now, `cat_expr()` classifies the expression `Expr` and the address `A = ToAddr(Expr)`
1047+ /// as follows:
1048+ ///
1049+ /// - `cat`: what kind of expression was this? This is a subset of the
1050+ /// full expression forms which only includes those that we care about
1051+ /// for the purpose of the analysis.
1052+ /// - `mutbl`: mutability of the address `A`.
1053+ /// - `ty`: the type of data found at the address `A`.
1054+ ///
1055+ /// The resulting categorization tree differs somewhat from the expressions
1056+ /// themselves. For example, auto-derefs are explicit. Also, an index `a[b]` is
1057+ /// decomposed into two operations: a dereference to reach the array data and
1058+ /// then an index to jump forward to the relevant item.
1059+ ///
1060+ /// ## By-reference upvars
1061+ ///
1062+ /// One part of the codegen which may be non-obvious is that we translate
1063+ /// closure upvars into the dereference of a borrowed pointer; this more closely
1064+ /// resembles the runtime codegen. So, for example, if we had:
1065+ ///
1066+ /// let mut x = 3;
1067+ /// let y = 5;
1068+ /// let inc = || x += y;
1069+ ///
1070+ /// Then when we categorize `x` (*within* the closure) we would yield a
1071+ /// result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
1072+ /// tied to `x`. The type of `x'` will be a borrowed pointer.
1073+ impl < ' tcx , Cx : TypeInformationCtxt < ' tcx > , D : Delegate < ' tcx > > ExprUseVisitor < ' tcx , Cx , D > {
1074+ fn resolve_type_vars_or_error (
1075+ & self ,
1076+ id : HirId ,
1077+ ty : Option < Ty < ' tcx > > ,
1078+ ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10261079 match ty {
10271080 Some ( ty) => {
10281081 let ty = self . cx . resolve_vars_if_possible ( ty) ;
@@ -1053,15 +1106,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10531106 }
10541107 }
10551108
1056- fn node_ty ( & self , hir_id : HirId ) -> McResult < Ty < ' tcx > > {
1109+ fn node_ty ( & self , hir_id : HirId ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10571110 self . resolve_type_vars_or_error ( hir_id, self . cx . typeck_results ( ) . node_type_opt ( hir_id) )
10581111 }
10591112
1060- fn expr_ty ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < Ty < ' tcx > > {
1113+ fn expr_ty ( & self , expr : & hir:: Expr < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10611114 self . resolve_type_vars_or_error ( expr. hir_id , self . cx . typeck_results ( ) . expr_ty_opt ( expr) )
10621115 }
10631116
1064- fn expr_ty_adjusted ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < Ty < ' tcx > > {
1117+ fn expr_ty_adjusted ( & self , expr : & hir:: Expr < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10651118 self . resolve_type_vars_or_error (
10661119 expr. hir_id ,
10671120 self . cx . typeck_results ( ) . expr_ty_adjusted_opt ( expr) ,
@@ -1078,7 +1131,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10781131 /// implicit deref patterns attached (e.g., it is really
10791132 /// `&Some(x)`). In that case, we return the "outermost" type
10801133 /// (e.g., `&Option<T>`).
1081- fn pat_ty_adjusted ( & self , pat : & hir:: Pat < ' _ > ) -> McResult < Ty < ' tcx > > {
1134+ fn pat_ty_adjusted ( & self , pat : & hir:: Pat < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10821135 // Check for implicit `&` types wrapping the pattern; note
10831136 // that these are never attached to binding patterns, so
10841137 // actually this is somewhat "disjoint" from the code below
@@ -1093,8 +1146,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10931146 self . pat_ty_unadjusted ( pat)
10941147 }
10951148
1096- /// Like `pat_ty`, but ignores implicit `&` patterns.
1097- fn pat_ty_unadjusted ( & self , pat : & hir:: Pat < ' _ > ) -> McResult < Ty < ' tcx > > {
1149+ /// Like `TypeckResults:: pat_ty`, but ignores implicit `&` patterns.
1150+ fn pat_ty_unadjusted ( & self , pat : & hir:: Pat < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10981151 let base_ty = self . node_ty ( pat. hir_id ) ?;
10991152 trace ! ( ?base_ty) ;
11001153
@@ -1136,7 +1189,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11361189 }
11371190 }
11381191
1139- fn cat_expr ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < PlaceWithHirId < ' tcx > > {
1192+ fn cat_expr ( & self , expr : & hir:: Expr < ' _ > ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
11401193 self . cat_expr_ ( expr, self . cx . typeck_results ( ) . expr_adjustments ( expr) )
11411194 }
11421195
@@ -1146,7 +1199,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11461199 & self ,
11471200 expr : & hir:: Expr < ' _ > ,
11481201 adjustments : & [ adjustment:: Adjustment < ' tcx > ] ,
1149- ) -> McResult < PlaceWithHirId < ' tcx > > {
1202+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
11501203 match adjustments. split_last ( ) {
11511204 None => self . cat_expr_unadjusted ( expr) ,
11521205 Some ( ( adjustment, previous) ) => {
@@ -1160,7 +1213,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11601213 expr : & hir:: Expr < ' _ > ,
11611214 previous : PlaceWithHirId < ' tcx > ,
11621215 adjustment : & adjustment:: Adjustment < ' tcx > ,
1163- ) -> McResult < PlaceWithHirId < ' tcx > > {
1216+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
11641217 self . cat_expr_adjusted_with ( expr, || Ok ( previous) , adjustment)
11651218 }
11661219
@@ -1169,9 +1222,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11691222 expr : & hir:: Expr < ' _ > ,
11701223 previous : F ,
11711224 adjustment : & adjustment:: Adjustment < ' tcx > ,
1172- ) -> McResult < PlaceWithHirId < ' tcx > >
1225+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed >
11731226 where
1174- F : FnOnce ( ) -> McResult < PlaceWithHirId < ' tcx > > ,
1227+ F : FnOnce ( ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > ,
11751228 {
11761229 let target = self . cx . resolve_vars_if_possible ( adjustment. target ) ;
11771230 match adjustment. kind {
@@ -1196,7 +1249,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11961249 }
11971250 }
11981251
1199- fn cat_expr_unadjusted ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < PlaceWithHirId < ' tcx > > {
1252+ fn cat_expr_unadjusted (
1253+ & self ,
1254+ expr : & hir:: Expr < ' _ > ,
1255+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
12001256 let expr_ty = self . expr_ty ( expr) ?;
12011257 match expr. kind {
12021258 hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , e_base) => {
@@ -1287,7 +1343,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12871343 span : Span ,
12881344 expr_ty : Ty < ' tcx > ,
12891345 res : Res ,
1290- ) -> McResult < PlaceWithHirId < ' tcx > > {
1346+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
12911347 match res {
12921348 Res :: Def (
12931349 DefKind :: Ctor ( ..)
@@ -1321,7 +1377,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13211377 /// Note: the actual upvar access contains invisible derefs of closure
13221378 /// environment and upvar reference as appropriate. Only regionck cares
13231379 /// about these dereferences, so we let it compute them as needed.
1324- fn cat_upvar ( & self , hir_id : HirId , var_id : HirId ) -> McResult < PlaceWithHirId < ' tcx > > {
1380+ fn cat_upvar (
1381+ & self ,
1382+ hir_id : HirId ,
1383+ var_id : HirId ,
1384+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
13251385 let closure_expr_def_id = self . cx . body_owner_def_id ( ) ;
13261386
13271387 let upvar_id = ty:: UpvarId {
@@ -1370,7 +1430,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13701430 & self ,
13711431 expr : & hir:: Expr < ' _ > ,
13721432 base : & hir:: Expr < ' _ > ,
1373- ) -> McResult < PlaceWithHirId < ' tcx > > {
1433+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
13741434 // Reconstruct the output assuming it's a reference with the
13751435 // same region and mutability as the receiver. This holds for
13761436 // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
@@ -1392,7 +1452,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13921452 & self ,
13931453 node : HirId ,
13941454 base_place : PlaceWithHirId < ' tcx > ,
1395- ) -> McResult < PlaceWithHirId < ' tcx > > {
1455+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
13961456 let base_curr_ty = base_place. place . ty ( ) ;
13971457 let deref_ty = match self
13981458 . cx
@@ -1417,26 +1477,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14171477 Ok ( PlaceWithHirId :: new ( node, base_place. place . base_ty , base_place. place . base , projections) )
14181478 }
14191479
1420- fn cat_pattern < F > (
1421- & self ,
1422- place : PlaceWithHirId < ' tcx > ,
1423- pat : & hir:: Pat < ' _ > ,
1424- mut op : F ,
1425- ) -> McResult < ( ) >
1426- where
1427- F : FnMut ( & PlaceWithHirId < ' tcx > , & hir:: Pat < ' _ > ) ,
1428- {
1429- self . cat_pattern_ ( place, pat, & mut op)
1430- }
1431-
14321480 /// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
14331481 /// Here `pat_hir_id` is the HirId of the pattern itself.
14341482 fn variant_index_for_adt (
14351483 & self ,
14361484 qpath : & hir:: QPath < ' _ > ,
14371485 pat_hir_id : HirId ,
14381486 span : Span ,
1439- ) -> McResult < VariantIdx > {
1487+ ) -> Result < VariantIdx , ErrorGuaranteed > {
14401488 let res = self . cx . typeck_results ( ) . qpath_res ( qpath, pat_hir_id) ;
14411489 let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
14421490 let ty:: Adt ( adt_def, _) = self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) else {
@@ -1471,7 +1519,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14711519 pat_hir_id : HirId ,
14721520 variant_index : VariantIdx ,
14731521 span : Span ,
1474- ) -> McResult < usize > {
1522+ ) -> Result < usize , ErrorGuaranteed > {
14751523 let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
14761524 match self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) {
14771525 ty:: Adt ( adt_def, _) => Ok ( adt_def. variant ( variant_index) . fields . len ( ) ) ,
@@ -1486,7 +1534,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14861534
14871535 /// Returns the total number of fields in a tuple used within a Tuple pattern.
14881536 /// Here `pat_hir_id` is the HirId of the pattern itself.
1489- fn total_fields_in_tuple ( & self , pat_hir_id : HirId , span : Span ) -> McResult < usize > {
1537+ fn total_fields_in_tuple (
1538+ & self ,
1539+ pat_hir_id : HirId ,
1540+ span : Span ,
1541+ ) -> Result < usize , ErrorGuaranteed > {
14901542 let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
14911543 match self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) {
14921544 ty:: Tuple ( args) => Ok ( args. len ( ) ) ,
@@ -1504,12 +1556,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15041556 /// In general, the way that this works is that we walk down the pattern,
15051557 /// constructing a `PlaceWithHirId` that represents the path that will be taken
15061558 /// to reach the value being matched.
1507- fn cat_pattern_ < F > (
1559+ fn cat_pattern < F > (
15081560 & self ,
15091561 mut place_with_id : PlaceWithHirId < ' tcx > ,
15101562 pat : & hir:: Pat < ' _ > ,
15111563 op : & mut F ,
1512- ) -> McResult < ( ) >
1564+ ) -> Result < ( ) , ErrorGuaranteed >
15131565 where
15141566 F : FnMut ( & PlaceWithHirId < ' tcx > , & hir:: Pat < ' _ > ) ,
15151567 {
@@ -1580,7 +1632,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15801632 subpat_ty,
15811633 projection_kind,
15821634 ) ;
1583- self . cat_pattern_ ( sub_place, subpat, op) ?;
1635+ self . cat_pattern ( sub_place, subpat, op) ?;
15841636 }
15851637 }
15861638
@@ -1600,7 +1652,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16001652 subpat_ty,
16011653 projection_kind,
16021654 ) ;
1603- self . cat_pattern_ ( sub_place, subpat, op) ?;
1655+ self . cat_pattern ( sub_place, subpat, op) ?;
16041656 }
16051657 }
16061658
@@ -1625,26 +1677,26 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16251677 field_ty,
16261678 ProjectionKind :: Field ( field_index, variant_index) ,
16271679 ) ;
1628- self . cat_pattern_ ( field_place, fp. pat , op) ?;
1680+ self . cat_pattern ( field_place, fp. pat , op) ?;
16291681 }
16301682 }
16311683
16321684 PatKind :: Or ( pats) => {
16331685 for pat in pats {
1634- self . cat_pattern_ ( place_with_id. clone ( ) , pat, op) ?;
1686+ self . cat_pattern ( place_with_id. clone ( ) , pat, op) ?;
16351687 }
16361688 }
16371689
16381690 PatKind :: Binding ( .., Some ( subpat) ) => {
1639- self . cat_pattern_ ( place_with_id, subpat, op) ?;
1691+ self . cat_pattern ( place_with_id, subpat, op) ?;
16401692 }
16411693
16421694 PatKind :: Box ( subpat) | PatKind :: Ref ( subpat, _) => {
16431695 // box p1, &p1, &mut p1. we can ignore the mutability of
16441696 // PatKind::Ref since that information is already contained
16451697 // in the type.
16461698 let subplace = self . cat_deref ( pat. hir_id , place_with_id) ?;
1647- self . cat_pattern_ ( subplace, subpat, op) ?;
1699+ self . cat_pattern ( subplace, subpat, op) ?;
16481700 }
16491701 PatKind :: Deref ( subpat) => {
16501702 let mutable = self . cx . typeck_results ( ) . pat_has_ref_mut_binding ( subpat) ;
@@ -1654,7 +1706,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16541706 let ty = Ty :: new_ref ( self . cx . tcx ( ) , re_erased, ty, mutability) ;
16551707 // A deref pattern generates a temporary.
16561708 let place = self . cat_rvalue ( pat. hir_id , ty) ;
1657- self . cat_pattern_ ( place, subpat, op) ?;
1709+ self . cat_pattern ( place, subpat, op) ?;
16581710 }
16591711
16601712 PatKind :: Slice ( before, ref slice, after) => {
@@ -1673,7 +1725,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16731725 ProjectionKind :: Index ,
16741726 ) ;
16751727 for before_pat in before {
1676- self . cat_pattern_ ( elt_place. clone ( ) , before_pat, op) ?;
1728+ self . cat_pattern ( elt_place. clone ( ) , before_pat, op) ?;
16771729 }
16781730 if let Some ( slice_pat) = * slice {
16791731 let slice_pat_ty = self . pat_ty_adjusted ( slice_pat) ?;
@@ -1683,10 +1735,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16831735 slice_pat_ty,
16841736 ProjectionKind :: Subslice ,
16851737 ) ;
1686- self . cat_pattern_ ( slice_place, slice_pat, op) ?;
1738+ self . cat_pattern ( slice_place, slice_pat, op) ?;
16871739 }
16881740 for after_pat in after {
1689- self . cat_pattern_ ( elt_place. clone ( ) , after_pat, op) ?;
1741+ self . cat_pattern ( elt_place. clone ( ) , after_pat, op) ?;
16901742 }
16911743 }
16921744
0 commit comments