8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use std:: iter;
12
-
13
11
use check:: FnCtxt ;
14
12
use rustc:: infer:: InferOk ;
15
13
use rustc:: traits:: ObligationCause ;
@@ -140,25 +138,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
140
138
}
141
139
}
142
140
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
+
158
143
( expected, Some ( err) )
159
144
}
160
145
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 > )
162
147
-> Vec < AssociatedItem > {
163
148
let mut methods = self . probe_for_return_type ( span,
164
149
probe:: Mode :: MethodCall ,
@@ -261,19 +246,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
261
246
/// In addition of this check, it also checks between references mutability state. If the
262
247
/// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
263
248
/// `&mut`!".
264
- fn check_ref ( & self ,
249
+ pub fn check_ref ( & self ,
265
250
expr : & hir:: Expr ,
266
251
checked_ty : Ty < ' tcx > ,
267
252
expected : Ty < ' tcx > )
268
253
-> 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
+
270
261
match ( & expected. sty , & checked_ty. sty ) {
271
262
( & ty:: TyRef ( _, exp, _) , & ty:: TyRef ( _, check, _) ) => match ( & exp. sty , & check. sty ) {
272
263
( & ty:: TyStr , & ty:: TyArray ( arr, _) ) |
273
264
( & ty:: TyStr , & ty:: TySlice ( arr) ) if arr == self . tcx . types . u8 => {
274
265
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) {
277
267
return Some ( ( sp,
278
268
"consider removing the leading `b`" ,
279
269
src[ 1 ..] . to_string ( ) ) ) ;
@@ -283,8 +273,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
283
273
( & ty:: TyArray ( arr, _) , & ty:: TyStr ) |
284
274
( & ty:: TySlice ( arr) , & ty:: TyStr ) if arr == self . tcx . types . u8 => {
285
275
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) {
288
277
return Some ( ( sp,
289
278
"consider adding a leading `b`" ,
290
279
format ! ( "b{}" , src) ) ) ;
@@ -311,9 +300,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
311
300
checked_ty) ,
312
301
} ;
313
302
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) {
317
304
let sugg_expr = match expr. node { // parenthesize if needed (Issue #46756)
318
305
hir:: ExprCast ( _, _) | hir:: ExprBinary ( _, _, _) => format ! ( "({})" , src) ,
319
306
_ => src,
@@ -342,11 +329,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
342
329
// a macro; if so, it's hard to extract the text and make a good
343
330
// suggestion, so don't bother.)
344
331
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 ( ) {
346
333
match expr. node {
347
334
// Maybe remove `&`?
348
335
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 ) {
350
340
return Some ( ( sp, "consider removing the borrow" , code) ) ;
351
341
}
352
342
}
@@ -355,9 +345,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
355
345
_ => {
356
346
if !self . infcx . type_moves_by_default ( self . param_env ,
357
347
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) {
361
351
return Some ( ( sp,
362
352
"consider dereferencing the borrow" ,
363
353
format ! ( "*{}" , code) ) ) ;
@@ -372,7 +362,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
372
362
None
373
363
}
374
364
375
- fn check_for_cast ( & self ,
365
+ pub fn check_for_cast ( & self ,
376
366
err : & mut DiagnosticBuilder < ' tcx > ,
377
367
expr : & hir:: Expr ,
378
368
checked_ty : Ty < ' tcx > ,
0 commit comments