88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use std:: iter;
12-
1311use check:: FnCtxt ;
1412use rustc:: infer:: InferOk ;
1513use rustc:: traits:: ObligationCause ;
@@ -140,25 +138,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
140138 }
141139 }
142140
143- if let Some ( ( sp, msg, suggestion) ) = self . check_ref ( expr, checked_ty, expected) {
144- err. span_suggestion ( sp, msg, suggestion) ;
145- } else if !self . check_for_cast ( & mut err, expr, expr_ty, expected) {
146- let methods = self . get_conversion_methods ( expr. span , expected, checked_ty) ;
147- if let Ok ( expr_text) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
148- let suggestions = iter:: repeat ( expr_text) . zip ( methods. iter ( ) )
149- . map ( |( receiver, method) | format ! ( "{}.{}()" , receiver, method. ident) )
150- . collect :: < Vec < _ > > ( ) ;
151- if !suggestions. is_empty ( ) {
152- err. span_suggestions ( expr. span ,
153- "try using a conversion method" ,
154- suggestions) ;
155- }
156- }
157- }
141+ self . suggest_ref_or_into ( & mut err, expr, expected, expr_ty) ;
142+
158143 ( expected, Some ( err) )
159144 }
160145
161- fn get_conversion_methods ( & self , span : Span , expected : Ty < ' tcx > , checked_ty : Ty < ' tcx > )
146+ pub fn get_conversion_methods ( & self , span : Span , expected : Ty < ' tcx > , checked_ty : Ty < ' tcx > )
162147 -> Vec < AssociatedItem > {
163148 let mut methods = self . probe_for_return_type ( span,
164149 probe:: Mode :: MethodCall ,
@@ -261,19 +246,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
261246 /// In addition of this check, it also checks between references mutability state. If the
262247 /// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
263248 /// `&mut`!".
264- fn check_ref ( & self ,
249+ pub fn check_ref ( & self ,
265250 expr : & hir:: Expr ,
266251 checked_ty : Ty < ' tcx > ,
267252 expected : Ty < ' tcx > )
268253 -> Option < ( Span , & ' static str , String ) > {
269- let sp = expr. span ;
254+ let cm = self . sess ( ) . codemap ( ) ;
255+ // Use the callsite's span if this is a macro call. #41858
256+ let sp = cm. call_span_if_macro ( expr. span ) ;
257+ if !cm. span_to_filename ( sp) . is_real ( ) {
258+ return None ;
259+ }
260+
270261 match ( & expected. sty , & checked_ty. sty ) {
271262 ( & ty:: TyRef ( _, exp, _) , & ty:: TyRef ( _, check, _) ) => match ( & exp. sty , & check. sty ) {
272263 ( & ty:: TyStr , & ty:: TyArray ( arr, _) ) |
273264 ( & ty:: TyStr , & ty:: TySlice ( arr) ) if arr == self . tcx . types . u8 => {
274265 if let hir:: ExprLit ( _) = expr. node {
275- let sp = self . sess ( ) . codemap ( ) . call_span_if_macro ( expr. span ) ;
276- if let Ok ( src) = self . tcx . sess . codemap ( ) . span_to_snippet ( sp) {
266+ if let Ok ( src) = cm. span_to_snippet ( sp) {
277267 return Some ( ( sp,
278268 "consider removing the leading `b`" ,
279269 src[ 1 ..] . to_string ( ) ) ) ;
@@ -283,8 +273,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
283273 ( & ty:: TyArray ( arr, _) , & ty:: TyStr ) |
284274 ( & ty:: TySlice ( arr) , & ty:: TyStr ) if arr == self . tcx . types . u8 => {
285275 if let hir:: ExprLit ( _) = expr. node {
286- let sp = self . sess ( ) . codemap ( ) . call_span_if_macro ( expr. span ) ;
287- if let Ok ( src) = self . tcx . sess . codemap ( ) . span_to_snippet ( sp) {
276+ if let Ok ( src) = cm. span_to_snippet ( sp) {
288277 return Some ( ( sp,
289278 "consider adding a leading `b`" ,
290279 format ! ( "b{}" , src) ) ) ;
@@ -311,9 +300,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
311300 checked_ty) ,
312301 } ;
313302 if self . can_coerce ( ref_ty, expected) {
314- // Use the callsite's span if this is a macro call. #41858
315- let sp = self . sess ( ) . codemap ( ) . call_span_if_macro ( expr. span ) ;
316- if let Ok ( src) = self . tcx . sess . codemap ( ) . span_to_snippet ( sp) {
303+ if let Ok ( src) = cm. span_to_snippet ( sp) {
317304 let sugg_expr = match expr. node { // parenthesize if needed (Issue #46756)
318305 hir:: ExprCast ( _, _) | hir:: ExprBinary ( _, _, _) => format ! ( "({})" , src) ,
319306 _ => src,
@@ -342,11 +329,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
342329 // a macro; if so, it's hard to extract the text and make a good
343330 // suggestion, so don't bother.)
344331 if self . infcx . can_sub ( self . param_env , checked, & expected) . is_ok ( ) &&
345- expr . span . ctxt ( ) . outer ( ) . expn_info ( ) . is_none ( ) {
332+ sp . ctxt ( ) . outer ( ) . expn_info ( ) . is_none ( ) {
346333 match expr. node {
347334 // Maybe remove `&`?
348335 hir:: ExprAddrOf ( _, ref expr) => {
349- if let Ok ( code) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
336+ if !cm. span_to_filename ( expr. span ) . is_real ( ) {
337+ return None ;
338+ }
339+ if let Ok ( code) = cm. span_to_snippet ( expr. span ) {
350340 return Some ( ( sp, "consider removing the borrow" , code) ) ;
351341 }
352342 }
@@ -355,9 +345,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
355345 _ => {
356346 if !self . infcx . type_moves_by_default ( self . param_env ,
357347 checked,
358- expr . span ) {
359- let sp = self . sess ( ) . codemap ( ) . call_span_if_macro ( expr . span ) ;
360- if let Ok ( code) = self . tcx . sess . codemap ( ) . span_to_snippet ( sp) {
348+ sp ) {
349+ let sp = cm . call_span_if_macro ( sp ) ;
350+ if let Ok ( code) = cm . span_to_snippet ( sp) {
361351 return Some ( ( sp,
362352 "consider dereferencing the borrow" ,
363353 format ! ( "*{}" , code) ) ) ;
@@ -372,7 +362,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
372362 None
373363 }
374364
375- fn check_for_cast ( & self ,
365+ pub fn check_for_cast ( & self ,
376366 err : & mut DiagnosticBuilder < ' tcx > ,
377367 expr : & hir:: Expr ,
378368 checked_ty : Ty < ' tcx > ,
0 commit comments