@@ -2,7 +2,8 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
22use rustc_middle:: mir:: * ;
33use rustc_middle:: ty;
44use 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;
67
78use crate :: borrow_check:: diagnostics:: UseSpans ;
89use crate :: borrow_check:: prefixes:: PrefixSet ;
@@ -384,36 +385,44 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
384385 }
385386 }
386387 } ;
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 ,
396420 } ;
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 ( ) ,
417426 Applicability :: MaybeIncorrect ,
418427 ) ;
419428 }
0 commit comments