@@ -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) ;
@@ -1051,15 +1104,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10511104 }
10521105 }
10531106
1054- fn node_ty ( & self , hir_id : HirId ) -> McResult < Ty < ' tcx > > {
1107+ fn node_ty ( & self , hir_id : HirId ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10551108 self . resolve_type_vars_or_error ( hir_id, self . cx . typeck_results ( ) . node_type_opt ( hir_id) )
10561109 }
10571110
1058- fn expr_ty ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < Ty < ' tcx > > {
1111+ fn expr_ty ( & self , expr : & hir:: Expr < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10591112 self . resolve_type_vars_or_error ( expr. hir_id , self . cx . typeck_results ( ) . expr_ty_opt ( expr) )
10601113 }
10611114
1062- fn expr_ty_adjusted ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < Ty < ' tcx > > {
1115+ fn expr_ty_adjusted ( & self , expr : & hir:: Expr < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10631116 self . resolve_type_vars_or_error (
10641117 expr. hir_id ,
10651118 self . cx . typeck_results ( ) . expr_ty_adjusted_opt ( expr) ,
@@ -1076,7 +1129,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10761129 /// implicit deref patterns attached (e.g., it is really
10771130 /// `&Some(x)`). In that case, we return the "outermost" type
10781131 /// (e.g., `&Option<T>`).
1079- fn pat_ty_adjusted ( & self , pat : & hir:: Pat < ' _ > ) -> McResult < Ty < ' tcx > > {
1132+ fn pat_ty_adjusted ( & self , pat : & hir:: Pat < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10801133 // Check for implicit `&` types wrapping the pattern; note
10811134 // that these are never attached to binding patterns, so
10821135 // actually this is somewhat "disjoint" from the code below
@@ -1091,8 +1144,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
10911144 self . pat_ty_unadjusted ( pat)
10921145 }
10931146
1094- /// Like `pat_ty`, but ignores implicit `&` patterns.
1095- fn pat_ty_unadjusted ( & self , pat : & hir:: Pat < ' _ > ) -> McResult < Ty < ' tcx > > {
1147+ /// Like `TypeckResults:: pat_ty`, but ignores implicit `&` patterns.
1148+ fn pat_ty_unadjusted ( & self , pat : & hir:: Pat < ' _ > ) -> Result < Ty < ' tcx > , ErrorGuaranteed > {
10961149 let base_ty = self . node_ty ( pat. hir_id ) ?;
10971150 trace ! ( ?base_ty) ;
10981151
@@ -1134,7 +1187,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11341187 }
11351188 }
11361189
1137- fn cat_expr ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < PlaceWithHirId < ' tcx > > {
1190+ fn cat_expr ( & self , expr : & hir:: Expr < ' _ > ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
11381191 self . cat_expr_ ( expr, self . cx . typeck_results ( ) . expr_adjustments ( expr) )
11391192 }
11401193
@@ -1144,7 +1197,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11441197 & self ,
11451198 expr : & hir:: Expr < ' _ > ,
11461199 adjustments : & [ adjustment:: Adjustment < ' tcx > ] ,
1147- ) -> McResult < PlaceWithHirId < ' tcx > > {
1200+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
11481201 match adjustments. split_last ( ) {
11491202 None => self . cat_expr_unadjusted ( expr) ,
11501203 Some ( ( adjustment, previous) ) => {
@@ -1158,7 +1211,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11581211 expr : & hir:: Expr < ' _ > ,
11591212 previous : PlaceWithHirId < ' tcx > ,
11601213 adjustment : & adjustment:: Adjustment < ' tcx > ,
1161- ) -> McResult < PlaceWithHirId < ' tcx > > {
1214+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
11621215 self . cat_expr_adjusted_with ( expr, || Ok ( previous) , adjustment)
11631216 }
11641217
@@ -1167,9 +1220,9 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11671220 expr : & hir:: Expr < ' _ > ,
11681221 previous : F ,
11691222 adjustment : & adjustment:: Adjustment < ' tcx > ,
1170- ) -> McResult < PlaceWithHirId < ' tcx > >
1223+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed >
11711224 where
1172- F : FnOnce ( ) -> McResult < PlaceWithHirId < ' tcx > > ,
1225+ F : FnOnce ( ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > ,
11731226 {
11741227 let target = self . cx . resolve_vars_if_possible ( adjustment. target ) ;
11751228 match adjustment. kind {
@@ -1194,7 +1247,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
11941247 }
11951248 }
11961249
1197- fn cat_expr_unadjusted ( & self , expr : & hir:: Expr < ' _ > ) -> McResult < PlaceWithHirId < ' tcx > > {
1250+ fn cat_expr_unadjusted (
1251+ & self ,
1252+ expr : & hir:: Expr < ' _ > ,
1253+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
11981254 let expr_ty = self . expr_ty ( expr) ?;
11991255 match expr. kind {
12001256 hir:: ExprKind :: Unary ( hir:: UnOp :: Deref , e_base) => {
@@ -1285,7 +1341,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
12851341 span : Span ,
12861342 expr_ty : Ty < ' tcx > ,
12871343 res : Res ,
1288- ) -> McResult < PlaceWithHirId < ' tcx > > {
1344+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
12891345 match res {
12901346 Res :: Def (
12911347 DefKind :: Ctor ( ..)
@@ -1319,7 +1375,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13191375 /// Note: the actual upvar access contains invisible derefs of closure
13201376 /// environment and upvar reference as appropriate. Only regionck cares
13211377 /// about these dereferences, so we let it compute them as needed.
1322- fn cat_upvar ( & self , hir_id : HirId , var_id : HirId ) -> McResult < PlaceWithHirId < ' tcx > > {
1378+ fn cat_upvar (
1379+ & self ,
1380+ hir_id : HirId ,
1381+ var_id : HirId ,
1382+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
13231383 let closure_expr_def_id = self . cx . body_owner_def_id ( ) ;
13241384
13251385 let upvar_id = ty:: UpvarId {
@@ -1368,7 +1428,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13681428 & self ,
13691429 expr : & hir:: Expr < ' _ > ,
13701430 base : & hir:: Expr < ' _ > ,
1371- ) -> McResult < PlaceWithHirId < ' tcx > > {
1431+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
13721432 // Reconstruct the output assuming it's a reference with the
13731433 // same region and mutability as the receiver. This holds for
13741434 // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
@@ -1390,7 +1450,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
13901450 & self ,
13911451 node : HirId ,
13921452 base_place : PlaceWithHirId < ' tcx > ,
1393- ) -> McResult < PlaceWithHirId < ' tcx > > {
1453+ ) -> Result < PlaceWithHirId < ' tcx > , ErrorGuaranteed > {
13941454 let base_curr_ty = base_place. place . ty ( ) ;
13951455 let deref_ty = match self
13961456 . cx
@@ -1415,26 +1475,14 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14151475 Ok ( PlaceWithHirId :: new ( node, base_place. place . base_ty , base_place. place . base , projections) )
14161476 }
14171477
1418- fn cat_pattern < F > (
1419- & self ,
1420- place : PlaceWithHirId < ' tcx > ,
1421- pat : & hir:: Pat < ' _ > ,
1422- mut op : F ,
1423- ) -> McResult < ( ) >
1424- where
1425- F : FnMut ( & PlaceWithHirId < ' tcx > , & hir:: Pat < ' _ > ) ,
1426- {
1427- self . cat_pattern_ ( place, pat, & mut op)
1428- }
1429-
14301478 /// Returns the variant index for an ADT used within a Struct or TupleStruct pattern
14311479 /// Here `pat_hir_id` is the HirId of the pattern itself.
14321480 fn variant_index_for_adt (
14331481 & self ,
14341482 qpath : & hir:: QPath < ' _ > ,
14351483 pat_hir_id : HirId ,
14361484 span : Span ,
1437- ) -> McResult < VariantIdx > {
1485+ ) -> Result < VariantIdx , ErrorGuaranteed > {
14381486 let res = self . cx . typeck_results ( ) . qpath_res ( qpath, pat_hir_id) ;
14391487 let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
14401488 let ty:: Adt ( adt_def, _) = self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) else {
@@ -1469,7 +1517,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14691517 pat_hir_id : HirId ,
14701518 variant_index : VariantIdx ,
14711519 span : Span ,
1472- ) -> McResult < usize > {
1520+ ) -> Result < usize , ErrorGuaranteed > {
14731521 let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
14741522 match self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) {
14751523 ty:: Adt ( adt_def, _) => Ok ( adt_def. variant ( variant_index) . fields . len ( ) ) ,
@@ -1484,7 +1532,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
14841532
14851533 /// Returns the total number of fields in a tuple used within a Tuple pattern.
14861534 /// Here `pat_hir_id` is the HirId of the pattern itself.
1487- fn total_fields_in_tuple ( & self , pat_hir_id : HirId , span : Span ) -> McResult < usize > {
1535+ fn total_fields_in_tuple (
1536+ & self ,
1537+ pat_hir_id : HirId ,
1538+ span : Span ,
1539+ ) -> Result < usize , ErrorGuaranteed > {
14881540 let ty = self . cx . typeck_results ( ) . node_type ( pat_hir_id) ;
14891541 match self . cx . try_structurally_resolve_type ( span, ty) . kind ( ) {
14901542 ty:: Tuple ( args) => Ok ( args. len ( ) ) ,
@@ -1502,12 +1554,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15021554 /// In general, the way that this works is that we walk down the pattern,
15031555 /// constructing a `PlaceWithHirId` that represents the path that will be taken
15041556 /// to reach the value being matched.
1505- fn cat_pattern_ < F > (
1557+ fn cat_pattern < F > (
15061558 & self ,
15071559 mut place_with_id : PlaceWithHirId < ' tcx > ,
15081560 pat : & hir:: Pat < ' _ > ,
15091561 op : & mut F ,
1510- ) -> McResult < ( ) >
1562+ ) -> Result < ( ) , ErrorGuaranteed >
15111563 where
15121564 F : FnMut ( & PlaceWithHirId < ' tcx > , & hir:: Pat < ' _ > ) ,
15131565 {
@@ -1578,7 +1630,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15781630 subpat_ty,
15791631 projection_kind,
15801632 ) ;
1581- self . cat_pattern_ ( sub_place, subpat, op) ?;
1633+ self . cat_pattern ( sub_place, subpat, op) ?;
15821634 }
15831635 }
15841636
@@ -1598,7 +1650,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
15981650 subpat_ty,
15991651 projection_kind,
16001652 ) ;
1601- self . cat_pattern_ ( sub_place, subpat, op) ?;
1653+ self . cat_pattern ( sub_place, subpat, op) ?;
16021654 }
16031655 }
16041656
@@ -1623,26 +1675,26 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16231675 field_ty,
16241676 ProjectionKind :: Field ( field_index, variant_index) ,
16251677 ) ;
1626- self . cat_pattern_ ( field_place, fp. pat , op) ?;
1678+ self . cat_pattern ( field_place, fp. pat , op) ?;
16271679 }
16281680 }
16291681
16301682 PatKind :: Or ( pats) => {
16311683 for pat in pats {
1632- self . cat_pattern_ ( place_with_id. clone ( ) , pat, op) ?;
1684+ self . cat_pattern ( place_with_id. clone ( ) , pat, op) ?;
16331685 }
16341686 }
16351687
16361688 PatKind :: Binding ( .., Some ( subpat) ) => {
1637- self . cat_pattern_ ( place_with_id, subpat, op) ?;
1689+ self . cat_pattern ( place_with_id, subpat, op) ?;
16381690 }
16391691
16401692 PatKind :: Box ( subpat) | PatKind :: Ref ( subpat, _) => {
16411693 // box p1, &p1, &mut p1. we can ignore the mutability of
16421694 // PatKind::Ref since that information is already contained
16431695 // in the type.
16441696 let subplace = self . cat_deref ( pat. hir_id , place_with_id) ?;
1645- self . cat_pattern_ ( subplace, subpat, op) ?;
1697+ self . cat_pattern ( subplace, subpat, op) ?;
16461698 }
16471699 PatKind :: Deref ( subpat) => {
16481700 let mutable = self . cx . typeck_results ( ) . pat_has_ref_mut_binding ( subpat) ;
@@ -1652,7 +1704,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16521704 let ty = Ty :: new_ref ( self . cx . tcx ( ) , re_erased, ty, mutability) ;
16531705 // A deref pattern generates a temporary.
16541706 let place = self . cat_rvalue ( pat. hir_id , ty) ;
1655- self . cat_pattern_ ( place, subpat, op) ?;
1707+ self . cat_pattern ( place, subpat, op) ?;
16561708 }
16571709
16581710 PatKind :: Slice ( before, ref slice, after) => {
@@ -1671,7 +1723,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16711723 ProjectionKind :: Index ,
16721724 ) ;
16731725 for before_pat in before {
1674- self . cat_pattern_ ( elt_place. clone ( ) , before_pat, op) ?;
1726+ self . cat_pattern ( elt_place. clone ( ) , before_pat, op) ?;
16751727 }
16761728 if let Some ( slice_pat) = * slice {
16771729 let slice_pat_ty = self . pat_ty_adjusted ( slice_pat) ?;
@@ -1681,10 +1733,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
16811733 slice_pat_ty,
16821734 ProjectionKind :: Subslice ,
16831735 ) ;
1684- self . cat_pattern_ ( slice_place, slice_pat, op) ?;
1736+ self . cat_pattern ( slice_place, slice_pat, op) ?;
16851737 }
16861738 for after_pat in after {
1687- self . cat_pattern_ ( elt_place. clone ( ) , after_pat, op) ?;
1739+ self . cat_pattern ( elt_place. clone ( ) , after_pat, op) ?;
16881740 }
16891741 }
16901742
0 commit comments