@@ -111,39 +111,42 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
111111 // If that ever stops being the case, then the ever initialized
112112 // flow could be used.
113113 if let Some ( StatementKind :: Assign (
114- Place :: Local ( local ) ,
114+ place ,
115115 box Rvalue :: Use ( Operand :: Move ( move_from) ) ,
116116 ) ) = self . mir . basic_blocks ( ) [ location. block ]
117117 . statements
118118 . get ( location. statement_index )
119119 . map ( |stmt| & stmt. kind )
120120 {
121- let local_decl = & self . mir . local_decls [ * local] ;
122- // opt_match_place is the
123- // match_span is the span of the expression being matched on
124- // match *x.y { ... } match_place is Some(*x.y)
125- // ^^^^ match_span is the span of *x.y
126- //
127- // opt_match_place is None for let [mut] x = ... statements,
128- // whether or not the right-hand side is a place expression
129- if let Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
130- opt_match_place : Some ( ( ref opt_match_place, match_span) ) ,
131- binding_mode : _,
132- opt_ty_info : _,
133- pat_span : _,
134- } ) ) ) = local_decl. is_user_variable
135- {
136- self . append_binding_error (
137- grouped_errors,
138- kind,
139- original_path,
140- move_from,
141- * local,
142- opt_match_place,
143- match_span,
144- stmt_source_info. span ,
145- ) ;
146- return ;
121+ let neo_place = self . infcx . tcx . as_new_place ( & place) ;
122+ if let Some ( PlaceBase :: Local ( local) ) = neo_place. as_place_base ( ) {
123+ let local_decl = & self . mir . local_decls [ * local] ;
124+ // opt_match_place is the
125+ // match_span is the span of the expression being matched on
126+ // match *x.y { ... } match_place is Some(*x.y)
127+ // ^^^^ match_span is the span of *x.y
128+ //
129+ // opt_match_place is None for let [mut] x = ... statements,
130+ // whether or not the right-hand side is a place expression
131+ if let Some ( ClearCrossCrate :: Set ( BindingForm :: Var ( VarBindingForm {
132+ opt_match_place : Some ( ( ref opt_match_place, match_span) ) ,
133+ binding_mode : _,
134+ opt_ty_info : _,
135+ pat_span : _,
136+ } ) ) ) = local_decl. is_user_variable
137+ {
138+ self . append_binding_error (
139+ grouped_errors,
140+ kind,
141+ original_path,
142+ move_from,
143+ * local,
144+ opt_match_place,
145+ match_span,
146+ stmt_source_info. span ,
147+ ) ;
148+ return ;
149+ }
147150 }
148151 }
149152 grouped_errors. push ( GroupedMoveError :: OtherIllegalMove {
@@ -269,12 +272,15 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
269272 // Inspect the type of the content behind the
270273 // borrow to provide feedback about why this
271274 // was a move rather than a copy.
272- let ty = place. ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) ;
275+ let neo_place = self . infcx . tcx . as_new_place ( & place) ;
276+ let ty = neo_place. ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) ;
277+
273278 let is_upvar_field_projection =
274279 self . prefixes ( & original_path, PrefixSet :: All )
275280 . map ( |p| self . infcx . tcx . as_new_place ( & p) )
276281 . any ( |p| p. is_upvar_field_projection ( self . mir , & self . infcx . tcx )
277- . is_some ( ) ) ;
282+ . is_some ( )
283+ ) ;
278284 debug ! ( "report: ty={:?}" , ty) ;
279285 match ty. sty {
280286 ty:: Array ( ..) | ty:: Slice ( ..) =>
@@ -354,52 +360,54 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
354360 err : & mut DiagnosticBuilder < ' a > ,
355361 span : Span ,
356362 ) {
357- let snippet = self . infcx . tcx . sess . source_map ( ) . span_to_snippet ( span) . unwrap ( ) ;
358- match error {
359- GroupedMoveError :: MovesFromPlace {
360- mut binds_to,
361- move_from,
362- ..
363- } => {
364- let try_remove_deref = match move_from {
365- Place :: Projection ( box PlaceProjection {
366- elem : ProjectionElem :: Deref ,
367- ..
368- } ) => true ,
369- _ => false ,
370- } ;
371- if try_remove_deref && snippet. starts_with ( '*' ) {
372- // The snippet doesn't start with `*` in (e.g.) index
373- // expressions `a[b]`, which roughly desugar to
374- // `*Index::index(&a, b)` or
375- // `*IndexMut::index_mut(&mut a, b)`.
376- err. span_suggestion (
377- span,
378- "consider removing the `*`" ,
379- snippet[ 1 ..] . to_owned ( ) ,
380- Applicability :: Unspecified ,
381- ) ;
382- } else {
383- err. span_suggestion (
384- span,
385- "consider borrowing here" ,
386- format ! ( "&{}" , snippet) ,
387- Applicability :: Unspecified ,
388- ) ;
389- }
363+ if let Ok ( snippet) = self . infcx . tcx . sess
364+ . source_map ( ) . span_to_snippet ( span) {
365+ match error {
366+ GroupedMoveError :: MovesFromPlace {
367+ mut binds_to,
368+ move_from,
369+ ..
370+ } => {
371+ let try_remove_deref = match move_from {
372+ Place :: Projection ( box PlaceProjection {
373+ elem : ProjectionElem :: Deref ,
374+ ..
375+ } ) => true ,
376+ _ => false ,
377+ } ;
378+ if try_remove_deref && snippet. starts_with ( '*' ) {
379+ // The snippet doesn't start with `*` in (e.g.) index
380+ // expressions `a[b]`, which roughly desugar to
381+ // `*Index::index(&a, b)` or
382+ // `*IndexMut::index_mut(&mut a, b)`.
383+ err. span_suggestion (
384+ span,
385+ "consider removing the `*`" ,
386+ snippet[ 1 ..] . to_owned ( ) ,
387+ Applicability :: Unspecified ,
388+ ) ;
389+ } else {
390+ err. span_suggestion (
391+ span,
392+ "consider borrowing here" ,
393+ format ! ( "&{}" , snippet) ,
394+ Applicability :: Unspecified ,
395+ ) ;
396+ }
390397
391- binds_to. sort ( ) ;
392- binds_to. dedup ( ) ;
393- self . add_move_error_details ( err, & binds_to) ;
394- }
395- GroupedMoveError :: MovesFromValue { mut binds_to, .. } => {
396- binds_to. sort ( ) ;
397- binds_to. dedup ( ) ;
398- self . add_move_error_suggestions ( err, & binds_to) ;
399- self . add_move_error_details ( err, & binds_to) ;
398+ binds_to. sort ( ) ;
399+ binds_to. dedup ( ) ;
400+ self . add_move_error_details ( err, & binds_to) ;
401+ }
402+ GroupedMoveError :: MovesFromValue { mut binds_to, .. } => {
403+ binds_to. sort ( ) ;
404+ binds_to. dedup ( ) ;
405+ self . add_move_error_suggestions ( err, & binds_to) ;
406+ self . add_move_error_details ( err, & binds_to) ;
407+ }
408+ // No binding. Nothing to suggest.
409+ GroupedMoveError :: OtherIllegalMove { .. } => ( ) ,
400410 }
401- // No binding. Nothing to suggest.
402- GroupedMoveError :: OtherIllegalMove { .. } => ( ) ,
403411 }
404412 }
405413
@@ -417,27 +425,28 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
417425 ..
418426 } ) )
419427 ) = bind_to. is_user_variable {
420- let pat_snippet = self . infcx . tcx . sess . source_map ( )
421- . span_to_snippet ( pat_span)
422- . unwrap ( ) ;
423- if pat_snippet. starts_with ( '&' ) {
424- let pat_snippet = pat_snippet[ 1 ..] . trim_start ( ) ;
425- let suggestion;
426- let to_remove;
427- if pat_snippet. starts_with ( "mut" )
428- && pat_snippet[ "mut" . len ( ) ..] . starts_with ( Pattern_White_Space )
429- {
430- suggestion = pat_snippet[ "mut" . len ( ) ..] . trim_start ( ) ;
431- to_remove = "&mut" ;
432- } else {
433- suggestion = pat_snippet;
434- to_remove = "&" ;
428+ if let Ok ( pat_snippet) = self . infcx . tcx . sess
429+ . source_map ( )
430+ . span_to_snippet ( pat_span) {
431+ if pat_snippet. starts_with ( '&' ) {
432+ let pat_snippet = pat_snippet[ 1 ..] . trim_start ( ) ;
433+ let suggestion;
434+ let to_remove;
435+ if pat_snippet. starts_with ( "mut" )
436+ && pat_snippet[ "mut" . len ( ) ..] . starts_with ( Pattern_White_Space )
437+ {
438+ suggestion = pat_snippet[ "mut" . len ( ) ..] . trim_start ( ) ;
439+ to_remove = "&mut" ;
440+ } else {
441+ suggestion = pat_snippet;
442+ to_remove = "&" ;
443+ }
444+ suggestions. push ( (
445+ pat_span,
446+ to_remove,
447+ suggestion. to_owned ( ) ,
448+ ) ) ;
435449 }
436- suggestions. push ( (
437- pat_span,
438- to_remove,
439- suggestion. to_owned ( ) ,
440- ) ) ;
441450 }
442451 }
443452 }
@@ -536,7 +545,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
536545 // We're only interested in assignments (in particular, where the
537546 // assignment came from - was it an `Rc` or `Arc`?).
538547 if let StatementKind :: Assign ( _, box Rvalue :: Ref ( _, _, source) ) = & stmt. kind {
539- let ty = source. ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) ;
548+ let neo_place = self . infcx . tcx . as_new_place ( source) ;
549+ let ty = neo_place. ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) ;
540550 let ty = match ty. sty {
541551 ty:: TyKind :: Ref ( _, ty, _) => ty,
542552 _ => ty,
@@ -560,8 +570,8 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
560570 Operand :: Copy ( place) | Operand :: Move ( place) => place,
561571 _ => continue ,
562572 } ;
563-
564- let ty = source . ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) ;
573+ let neo_place = self . infcx . tcx . as_new_place ( & source ) ;
574+ let ty = neo_place . ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) ;
565575 let ty = match ty. sty {
566576 ty:: TyKind :: Ref ( _, ty, _) => ty,
567577 _ => ty,
@@ -583,11 +593,14 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
583593 // If we didn't find an `Arc` or an `Rc`, then check specifically for
584594 // a dereference of a place that has the type of a raw pointer.
585595 // We can't use `place.ty(..).to_ty(..)` here as that strips away the raw pointer.
586- if let Place :: Projection ( box Projection {
587- base,
588- elem : ProjectionElem :: Deref ,
589- } ) = place {
590- if base. ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) . is_unsafe_ptr ( ) {
596+ let neo_place = self . infcx . tcx . as_new_place ( & place) ;
597+ let place_tys = neo_place. place_tys ( & self . mir , self . infcx . tcx ) ;
598+ if let Some ( & ProjectionElem :: Deref ) = neo_place. elems . last ( ) {
599+ // Given place
600+ // base.[a, b, c]
601+ // ^-- deref
602+ // ^^^^^^^^^^
603+ if place_tys[ place_tys. len ( ) - 2 ] . to_ty ( self . infcx . tcx ) . is_unsafe_ptr ( ) {
591604 return BorrowedContentSource :: DerefRawPointer ;
592605 }
593606 }
0 commit comments