@@ -2,7 +2,8 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
2
2
use rustc_middle:: mir:: * ;
3
3
use rustc_middle:: ty;
4
4
use rustc_span:: source_map:: DesugaringKind ;
5
- use rustc_span:: { sym, Span } ;
5
+ use rustc_span:: { sym, Span , DUMMY_SP } ;
6
+ use rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions;
6
7
7
8
use crate :: borrow_check:: diagnostics:: UseSpans ;
8
9
use crate :: borrow_check:: prefixes:: PrefixSet ;
@@ -384,36 +385,44 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
384
385
}
385
386
}
386
387
} ;
387
- if let Ok ( snippet) = self . infcx . tcx . sess . source_map ( ) . span_to_snippet ( span) {
388
- let def_id = match * move_place. ty ( self . body , self . infcx . tcx ) . ty . kind ( ) {
389
- ty:: Adt ( self_def, _) => self_def. did ,
390
- ty:: Foreign ( def_id)
391
- | ty:: FnDef ( def_id, _)
392
- | ty:: Closure ( def_id, _)
393
- | ty:: Generator ( def_id, ..)
394
- | ty:: Opaque ( def_id, _) => def_id,
395
- _ => return err,
388
+ let ty = move_place. ty ( self . body , self . infcx . tcx ) . ty ;
389
+ let def_id = match * ty. kind ( ) {
390
+ ty:: Adt ( self_def, _) => self_def. did ,
391
+ ty:: Foreign ( def_id)
392
+ | ty:: FnDef ( def_id, _)
393
+ | ty:: Closure ( def_id, _)
394
+ | ty:: Generator ( def_id, ..)
395
+ | ty:: Opaque ( def_id, _) => def_id,
396
+ _ => return err,
397
+ } ;
398
+ let is_option = self . infcx . tcx . is_diagnostic_item ( sym:: option_type, def_id) ;
399
+ let is_result = self . infcx . tcx . is_diagnostic_item ( sym:: result_type, def_id) ;
400
+ if ( is_option || is_result) && use_spans. map_or ( true , |v| !v. for_closure ( ) ) {
401
+ err. span_suggestion_verbose (
402
+ span. shrink_to_hi ( ) ,
403
+ & format ! (
404
+ "consider borrowing the `{}`'s content" ,
405
+ if is_option { "Option" } else { "Result" }
406
+ ) ,
407
+ ".as_ref()" . to_string ( ) ,
408
+ Applicability :: MaybeIncorrect ,
409
+ ) ;
410
+ } else if matches ! ( span. desugaring_kind( ) , Some ( DesugaringKind :: ForLoop ( _) ) ) {
411
+ let suggest = match self . infcx . tcx . get_diagnostic_item ( sym:: IntoIterator ) {
412
+ Some ( def_id) => type_known_to_meet_bound_modulo_regions (
413
+ & self . infcx ,
414
+ self . param_env ,
415
+ self . infcx . tcx . mk_imm_ref ( self . infcx . tcx . lifetimes . re_erased , ty) ,
416
+ def_id,
417
+ DUMMY_SP ,
418
+ ) ,
419
+ _ => false ,
396
420
} ;
397
- let is_option = self . infcx . tcx . is_diagnostic_item ( sym:: option_type, def_id) ;
398
- let is_result = self . infcx . tcx . is_diagnostic_item ( sym:: result_type, def_id) ;
399
- if ( is_option || is_result) && use_spans. map_or ( true , |v| !v. for_closure ( ) ) {
400
- err. span_suggestion (
401
- span,
402
- & format ! (
403
- "consider borrowing the `{}`'s content" ,
404
- if is_option { "Option" } else { "Result" }
405
- ) ,
406
- format ! ( "{}.as_ref()" , snippet) ,
407
- Applicability :: MaybeIncorrect ,
408
- ) ;
409
- } else if matches ! ( span. desugaring_kind( ) , Some ( DesugaringKind :: ForLoop ( _) ) )
410
- && self . infcx . tcx . is_diagnostic_item ( sym:: vec_type, def_id)
411
- {
412
- // FIXME: suggest for anything that implements `IntoIterator`.
413
- err. span_suggestion (
414
- span,
415
- "consider iterating over a slice of the `Vec<_>`'s content" ,
416
- format ! ( "&{}" , snippet) ,
421
+ if suggest {
422
+ err. span_suggestion_verbose (
423
+ span. shrink_to_lo ( ) ,
424
+ & format ! ( "consider iterating over a slice of the `{}`'s content" , ty) ,
425
+ "&" . to_string ( ) ,
417
426
Applicability :: MaybeIncorrect ,
418
427
) ;
419
428
}
0 commit comments