@@ -18,7 +18,7 @@ use smallvec::SmallVec;
1818use stdx:: never;
1919
2020use crate :: {
21- mir:: { BorrowKind , ProjectionElem } ,
21+ mir:: { BorrowKind , MirSpan , ProjectionElem } ,
2222 static_lifetime, to_chalk_trait_id,
2323 traits:: FnTrait ,
2424 utils:: { self , pattern_matching_dereference_count} ,
@@ -121,6 +121,22 @@ impl HirPlace {
121121 }
122122 ty. clone ( )
123123 }
124+
125+ fn capture_kind_of_truncated_place (
126+ & self ,
127+ mut current_capture : CaptureKind ,
128+ len : usize ,
129+ ) -> CaptureKind {
130+ match current_capture {
131+ CaptureKind :: ByRef ( BorrowKind :: Mut { .. } ) => {
132+ if self . projections [ len..] . iter ( ) . any ( |x| * x == ProjectionElem :: Deref ) {
133+ current_capture = CaptureKind :: ByRef ( BorrowKind :: Unique ) ;
134+ }
135+ }
136+ _ => ( ) ,
137+ }
138+ current_capture
139+ }
124140}
125141
126142#[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
@@ -133,13 +149,15 @@ pub(crate) enum CaptureKind {
133149pub ( crate ) struct CapturedItem {
134150 pub ( crate ) place : HirPlace ,
135151 pub ( crate ) kind : CaptureKind ,
152+ pub ( crate ) span : MirSpan ,
136153 pub ( crate ) ty : Ty ,
137154}
138155
139156#[ derive( Debug , Clone , PartialEq , Eq ) ]
140157pub ( crate ) struct CapturedItemWithoutTy {
141158 pub ( crate ) place : HirPlace ,
142159 pub ( crate ) kind : CaptureKind ,
160+ pub ( crate ) span : MirSpan ,
143161}
144162
145163impl CapturedItemWithoutTy {
@@ -155,7 +173,7 @@ impl CapturedItemWithoutTy {
155173 TyKind :: Ref ( m, static_lifetime ( ) , ty) . intern ( Interner )
156174 }
157175 } ;
158- CapturedItem { place : self . place , kind : self . kind , ty }
176+ CapturedItem { place : self . place , kind : self . kind , span : self . span , ty }
159177 }
160178}
161179
@@ -211,14 +229,14 @@ impl InferenceContext<'_> {
211229
212230 fn ref_expr ( & mut self , expr : ExprId ) {
213231 if let Some ( place) = self . place_of_expr ( expr) {
214- self . add_capture ( place, CaptureKind :: ByRef ( BorrowKind :: Shared ) ) ;
232+ self . add_capture ( place, CaptureKind :: ByRef ( BorrowKind :: Shared ) , expr . into ( ) ) ;
215233 }
216234 self . walk_expr ( expr) ;
217235 }
218236
219- fn add_capture ( & mut self , place : HirPlace , kind : CaptureKind ) {
237+ fn add_capture ( & mut self , place : HirPlace , kind : CaptureKind , span : MirSpan ) {
220238 if self . is_upvar ( & place) {
221- self . push_capture ( CapturedItemWithoutTy { place, kind } ) ;
239+ self . push_capture ( CapturedItemWithoutTy { place, kind, span } ) ;
222240 }
223241 }
224242
@@ -227,27 +245,28 @@ impl InferenceContext<'_> {
227245 self . add_capture (
228246 place,
229247 CaptureKind :: ByRef ( BorrowKind :: Mut { allow_two_phase_borrow : false } ) ,
248+ expr. into ( ) ,
230249 ) ;
231250 }
232251 self . walk_expr ( expr) ;
233252 }
234253
235254 fn consume_expr ( & mut self , expr : ExprId ) {
236255 if let Some ( place) = self . place_of_expr ( expr) {
237- self . consume_place ( place) ;
256+ self . consume_place ( place, expr . into ( ) ) ;
238257 }
239258 self . walk_expr ( expr) ;
240259 }
241260
242- fn consume_place ( & mut self , place : HirPlace ) {
261+ fn consume_place ( & mut self , place : HirPlace , span : MirSpan ) {
243262 if self . is_upvar ( & place) {
244263 let ty = place. ty ( self ) . clone ( ) ;
245264 let kind = if self . is_ty_copy ( ty) {
246265 CaptureKind :: ByRef ( BorrowKind :: Shared )
247266 } else {
248267 CaptureKind :: ByValue
249268 } ;
250- self . push_capture ( CapturedItemWithoutTy { place, kind } ) ;
269+ self . push_capture ( CapturedItemWithoutTy { place, kind, span } ) ;
251270 }
252271 }
253272
@@ -281,9 +300,7 @@ impl InferenceContext<'_> {
281300 } ;
282301 if let Some ( place) = self . place_of_expr_without_adjust ( tgt_expr) {
283302 if let Some ( place) = apply_adjusts_to_place ( place, rest) {
284- if self . is_upvar ( & place) {
285- self . push_capture ( CapturedItemWithoutTy { place, kind : capture_kind } ) ;
286- }
303+ self . add_capture ( place, capture_kind, tgt_expr. into ( ) ) ;
287304 }
288305 }
289306 self . walk_expr_with_adjust ( tgt_expr, rest) ;
@@ -456,12 +473,9 @@ impl InferenceContext<'_> {
456473 "We sort closures, so we should always have data for inner closures" ,
457474 ) ;
458475 let mut cc = mem:: take ( & mut self . current_captures ) ;
459- cc. extend (
460- captures
461- . iter ( )
462- . filter ( |x| self . is_upvar ( & x. place ) )
463- . map ( |x| CapturedItemWithoutTy { place : x. place . clone ( ) , kind : x. kind } ) ,
464- ) ;
476+ cc. extend ( captures. iter ( ) . filter ( |x| self . is_upvar ( & x. place ) ) . map ( |x| {
477+ CapturedItemWithoutTy { place : x. place . clone ( ) , kind : x. kind , span : x. span }
478+ } ) ) ;
465479 self . current_captures = cc;
466480 }
467481 Expr :: Array ( Array :: ElementList { elements : exprs, is_assignee_expr : _ } )
@@ -552,8 +566,11 @@ impl InferenceContext<'_> {
552566 } ;
553567 match prev_index {
554568 Some ( p) => {
569+ let len = self . current_captures [ p] . place . projections . len ( ) ;
570+ let kind_after_truncate =
571+ item. place . capture_kind_of_truncated_place ( item. kind , len) ;
555572 self . current_captures [ p] . kind =
556- cmp:: max ( item . kind , self . current_captures [ p] . kind ) ;
573+ cmp:: max ( kind_after_truncate , self . current_captures [ p] . kind ) ;
557574 }
558575 None => {
559576 hash_map. insert ( item. place . clone ( ) , self . current_captures . len ( ) ) ;
@@ -603,7 +620,7 @@ impl InferenceContext<'_> {
603620 } ;
604621 match variant {
605622 VariantId :: EnumVariantId ( _) | VariantId :: UnionId ( _) => {
606- self . consume_place ( place)
623+ self . consume_place ( place, pat . into ( ) )
607624 }
608625 VariantId :: StructId ( s) => {
609626 let vd = & * self . db . struct_data ( s) . variant_data ;
@@ -632,21 +649,21 @@ impl InferenceContext<'_> {
632649 | Pat :: Slice { .. }
633650 | Pat :: ConstBlock ( _)
634651 | Pat :: Path ( _)
635- | Pat :: Lit ( _) => self . consume_place ( place) ,
652+ | Pat :: Lit ( _) => self . consume_place ( place, pat . into ( ) ) ,
636653 Pat :: Bind { id, subpat : _ } => {
637654 let mode = self . body . bindings [ * id] . mode ;
638655 if matches ! ( mode, BindingAnnotation :: Ref | BindingAnnotation :: RefMut ) {
639656 bm = mode;
640657 }
641658 let capture_kind = match bm {
642659 BindingAnnotation :: Unannotated | BindingAnnotation :: Mutable => {
643- self . consume_place ( place) ;
660+ self . consume_place ( place, pat . into ( ) ) ;
644661 return ;
645662 }
646663 BindingAnnotation :: Ref => BorrowKind :: Shared ,
647664 BindingAnnotation :: RefMut => BorrowKind :: Mut { allow_two_phase_borrow : false } ,
648665 } ;
649- self . add_capture ( place, CaptureKind :: ByRef ( capture_kind) ) ;
666+ self . add_capture ( place, CaptureKind :: ByRef ( capture_kind) , pat . into ( ) ) ;
650667 }
651668 Pat :: TupleStruct { path : _, args, ellipsis } => {
652669 pattern_matching_dereference ( & mut ty, & mut bm, & mut place) ;
@@ -659,7 +676,7 @@ impl InferenceContext<'_> {
659676 } ;
660677 match variant {
661678 VariantId :: EnumVariantId ( _) | VariantId :: UnionId ( _) => {
662- self . consume_place ( place)
679+ self . consume_place ( place, pat . into ( ) )
663680 }
664681 VariantId :: StructId ( s) => {
665682 let vd = & * self . db . struct_data ( s) . variant_data ;
0 commit comments