@@ -18,7 +18,7 @@ use smallvec::SmallVec;
18
18
use stdx:: never;
19
19
20
20
use crate :: {
21
- mir:: { BorrowKind , ProjectionElem } ,
21
+ mir:: { BorrowKind , MirSpan , ProjectionElem } ,
22
22
static_lifetime, to_chalk_trait_id,
23
23
traits:: FnTrait ,
24
24
utils:: { self , pattern_matching_dereference_count} ,
@@ -121,6 +121,22 @@ impl HirPlace {
121
121
}
122
122
ty. clone ( )
123
123
}
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
+ }
124
140
}
125
141
126
142
#[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
@@ -133,13 +149,15 @@ pub(crate) enum CaptureKind {
133
149
pub ( crate ) struct CapturedItem {
134
150
pub ( crate ) place : HirPlace ,
135
151
pub ( crate ) kind : CaptureKind ,
152
+ pub ( crate ) span : MirSpan ,
136
153
pub ( crate ) ty : Ty ,
137
154
}
138
155
139
156
#[ derive( Debug , Clone , PartialEq , Eq ) ]
140
157
pub ( crate ) struct CapturedItemWithoutTy {
141
158
pub ( crate ) place : HirPlace ,
142
159
pub ( crate ) kind : CaptureKind ,
160
+ pub ( crate ) span : MirSpan ,
143
161
}
144
162
145
163
impl CapturedItemWithoutTy {
@@ -155,7 +173,7 @@ impl CapturedItemWithoutTy {
155
173
TyKind :: Ref ( m, static_lifetime ( ) , ty) . intern ( Interner )
156
174
}
157
175
} ;
158
- CapturedItem { place : self . place , kind : self . kind , ty }
176
+ CapturedItem { place : self . place , kind : self . kind , span : self . span , ty }
159
177
}
160
178
}
161
179
@@ -211,14 +229,14 @@ impl InferenceContext<'_> {
211
229
212
230
fn ref_expr ( & mut self , expr : ExprId ) {
213
231
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 ( ) ) ;
215
233
}
216
234
self . walk_expr ( expr) ;
217
235
}
218
236
219
- fn add_capture ( & mut self , place : HirPlace , kind : CaptureKind ) {
237
+ fn add_capture ( & mut self , place : HirPlace , kind : CaptureKind , span : MirSpan ) {
220
238
if self . is_upvar ( & place) {
221
- self . push_capture ( CapturedItemWithoutTy { place, kind } ) ;
239
+ self . push_capture ( CapturedItemWithoutTy { place, kind, span } ) ;
222
240
}
223
241
}
224
242
@@ -227,27 +245,28 @@ impl InferenceContext<'_> {
227
245
self . add_capture (
228
246
place,
229
247
CaptureKind :: ByRef ( BorrowKind :: Mut { allow_two_phase_borrow : false } ) ,
248
+ expr. into ( ) ,
230
249
) ;
231
250
}
232
251
self . walk_expr ( expr) ;
233
252
}
234
253
235
254
fn consume_expr ( & mut self , expr : ExprId ) {
236
255
if let Some ( place) = self . place_of_expr ( expr) {
237
- self . consume_place ( place) ;
256
+ self . consume_place ( place, expr . into ( ) ) ;
238
257
}
239
258
self . walk_expr ( expr) ;
240
259
}
241
260
242
- fn consume_place ( & mut self , place : HirPlace ) {
261
+ fn consume_place ( & mut self , place : HirPlace , span : MirSpan ) {
243
262
if self . is_upvar ( & place) {
244
263
let ty = place. ty ( self ) . clone ( ) ;
245
264
let kind = if self . is_ty_copy ( ty) {
246
265
CaptureKind :: ByRef ( BorrowKind :: Shared )
247
266
} else {
248
267
CaptureKind :: ByValue
249
268
} ;
250
- self . push_capture ( CapturedItemWithoutTy { place, kind } ) ;
269
+ self . push_capture ( CapturedItemWithoutTy { place, kind, span } ) ;
251
270
}
252
271
}
253
272
@@ -281,9 +300,7 @@ impl InferenceContext<'_> {
281
300
} ;
282
301
if let Some ( place) = self . place_of_expr_without_adjust ( tgt_expr) {
283
302
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 ( ) ) ;
287
304
}
288
305
}
289
306
self . walk_expr_with_adjust ( tgt_expr, rest) ;
@@ -456,12 +473,9 @@ impl InferenceContext<'_> {
456
473
"We sort closures, so we should always have data for inner closures" ,
457
474
) ;
458
475
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
+ } ) ) ;
465
479
self . current_captures = cc;
466
480
}
467
481
Expr :: Array ( Array :: ElementList { elements : exprs, is_assignee_expr : _ } )
@@ -552,8 +566,11 @@ impl InferenceContext<'_> {
552
566
} ;
553
567
match prev_index {
554
568
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) ;
555
572
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 ) ;
557
574
}
558
575
None => {
559
576
hash_map. insert ( item. place . clone ( ) , self . current_captures . len ( ) ) ;
@@ -603,7 +620,7 @@ impl InferenceContext<'_> {
603
620
} ;
604
621
match variant {
605
622
VariantId :: EnumVariantId ( _) | VariantId :: UnionId ( _) => {
606
- self . consume_place ( place)
623
+ self . consume_place ( place, pat . into ( ) )
607
624
}
608
625
VariantId :: StructId ( s) => {
609
626
let vd = & * self . db . struct_data ( s) . variant_data ;
@@ -632,21 +649,21 @@ impl InferenceContext<'_> {
632
649
| Pat :: Slice { .. }
633
650
| Pat :: ConstBlock ( _)
634
651
| Pat :: Path ( _)
635
- | Pat :: Lit ( _) => self . consume_place ( place) ,
652
+ | Pat :: Lit ( _) => self . consume_place ( place, pat . into ( ) ) ,
636
653
Pat :: Bind { id, subpat : _ } => {
637
654
let mode = self . body . bindings [ * id] . mode ;
638
655
if matches ! ( mode, BindingAnnotation :: Ref | BindingAnnotation :: RefMut ) {
639
656
bm = mode;
640
657
}
641
658
let capture_kind = match bm {
642
659
BindingAnnotation :: Unannotated | BindingAnnotation :: Mutable => {
643
- self . consume_place ( place) ;
660
+ self . consume_place ( place, pat . into ( ) ) ;
644
661
return ;
645
662
}
646
663
BindingAnnotation :: Ref => BorrowKind :: Shared ,
647
664
BindingAnnotation :: RefMut => BorrowKind :: Mut { allow_two_phase_borrow : false } ,
648
665
} ;
649
- self . add_capture ( place, CaptureKind :: ByRef ( capture_kind) ) ;
666
+ self . add_capture ( place, CaptureKind :: ByRef ( capture_kind) , pat . into ( ) ) ;
650
667
}
651
668
Pat :: TupleStruct { path : _, args, ellipsis } => {
652
669
pattern_matching_dereference ( & mut ty, & mut bm, & mut place) ;
@@ -659,7 +676,7 @@ impl InferenceContext<'_> {
659
676
} ;
660
677
match variant {
661
678
VariantId :: EnumVariantId ( _) | VariantId :: UnionId ( _) => {
662
- self . consume_place ( place)
679
+ self . consume_place ( place, pat . into ( ) )
663
680
}
664
681
VariantId :: StructId ( s) => {
665
682
let vd = & * self . db . struct_data ( s) . variant_data ;
0 commit comments