@@ -137,7 +137,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
137
137
138
138
if let Some ( ( msg, suggestion) ) = self . check_ref ( expr, checked_ty, expected) {
139
139
err. span_suggestion ( expr. span , msg, suggestion) ;
140
- } else {
140
+ } else if ! self . check_for_cast ( & mut err , expr , expr_ty , expected ) {
141
141
let methods = self . get_conversion_methods ( expected, checked_ty) ;
142
142
if let Ok ( expr_text) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
143
143
let suggestions = iter:: repeat ( expr_text) . zip ( methods. iter ( ) )
@@ -287,8 +287,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
287
287
// Maybe remove `&`?
288
288
hir:: ExprAddrOf ( _, ref expr) => {
289
289
if let Ok ( code) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
290
- return Some ( ( "consider removing the borrow" ,
291
- code) ) ;
290
+ return Some ( ( "consider removing the borrow" , code) ) ;
292
291
}
293
292
}
294
293
@@ -303,12 +302,181 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
303
302
format ! ( "*{}" , code) ) ) ;
304
303
}
305
304
}
306
- } ,
305
+ }
307
306
}
308
307
}
309
308
None
310
309
}
311
310
_ => None ,
312
311
}
313
312
}
313
+
314
+ fn check_for_cast ( & self ,
315
+ err : & mut DiagnosticBuilder < ' tcx > ,
316
+ expr : & hir:: Expr ,
317
+ checked_ty : Ty < ' tcx > ,
318
+ expected_ty : Ty < ' tcx > )
319
+ -> bool {
320
+ let will_truncate = "will truncate the source value" ;
321
+ let depending_on_isize = "will truncate or zero-extend depending on the bit width of \
322
+ `isize`";
323
+ let depending_on_usize = "will truncate or zero-extend depending on the bit width of \
324
+ `usize`";
325
+ let will_sign_extend = "will sign-extend the source value" ;
326
+ let will_zero_extend = "will zero-extend the source value" ;
327
+
328
+ let needs_paren = expr. needs_parens_around_cast ( ) ;
329
+
330
+ if let ( Ok ( src) , true ) = ( self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) ,
331
+ expr. could_cast_in_type_mismatch ( ) ) {
332
+ let msg = format ! ( "you can cast an `{}` to `{}`" , checked_ty, expected_ty) ;
333
+ let suggestion = format ! ( "{}{} as {}{}" ,
334
+ if needs_paren { "(" } else { "" } ,
335
+ src,
336
+ if needs_paren { ")" } else { "" } ,
337
+ expected_ty) ;
338
+
339
+ match ( & expected_ty. sty , & checked_ty. sty ) {
340
+ ( & ty:: TyInt ( ref exp) , & ty:: TyInt ( ref found) ) => {
341
+ match ( found. bit_width ( ) , exp. bit_width ( ) ) {
342
+ ( Some ( found) , Some ( exp) ) if found > exp => {
343
+ err. span_suggestion ( expr. span ,
344
+ & format ! ( "{}, which {}" , msg, will_truncate) ,
345
+ suggestion) ;
346
+ }
347
+ ( None , _) | ( _, None ) => {
348
+ err. span_suggestion ( expr. span ,
349
+ & format ! ( "{}, which {}" , msg, depending_on_isize) ,
350
+ suggestion) ;
351
+ }
352
+ _ => {
353
+ err. span_suggestion ( expr. span ,
354
+ & format ! ( "{}, which {}" , msg, will_sign_extend) ,
355
+ suggestion) ;
356
+ }
357
+ }
358
+ true
359
+ }
360
+ ( & ty:: TyUint ( ref exp) , & ty:: TyUint ( ref found) ) => {
361
+ match ( found. bit_width ( ) , exp. bit_width ( ) ) {
362
+ ( Some ( found) , Some ( exp) ) if found > exp => {
363
+ err. span_suggestion ( expr. span ,
364
+ & format ! ( "{}, which {}" , msg, will_truncate) ,
365
+ suggestion) ;
366
+ }
367
+ ( None , _) | ( _, None ) => {
368
+ err. span_suggestion ( expr. span ,
369
+ & format ! ( "{}, which {}" , msg, depending_on_usize) ,
370
+ suggestion) ;
371
+ }
372
+ _ => {
373
+ err. span_suggestion ( expr. span ,
374
+ & format ! ( "{}, which {}" , msg, will_zero_extend) ,
375
+ suggestion) ;
376
+ }
377
+ }
378
+ true
379
+ }
380
+ ( & ty:: TyInt ( ref exp) , & ty:: TyUint ( ref found) ) => {
381
+ match ( found. bit_width ( ) , exp. bit_width ( ) ) {
382
+ ( Some ( found) , Some ( exp) ) if found > exp - 1 => {
383
+ err. span_suggestion ( expr. span ,
384
+ & format ! ( "{}, which {}" , msg, will_truncate) ,
385
+ suggestion) ;
386
+ }
387
+ ( None , None ) => {
388
+ err. span_suggestion ( expr. span ,
389
+ & format ! ( "{}, which {}" , msg, will_truncate) ,
390
+ suggestion) ;
391
+ }
392
+ ( None , _) => {
393
+ err. span_suggestion ( expr. span ,
394
+ & format ! ( "{}, which {}" , msg, depending_on_isize) ,
395
+ suggestion) ;
396
+ }
397
+ ( _, None ) => {
398
+ err. span_suggestion ( expr. span ,
399
+ & format ! ( "{}, which {}" , msg, depending_on_usize) ,
400
+ suggestion) ;
401
+ }
402
+ _ => {
403
+ err. span_suggestion ( expr. span ,
404
+ & format ! ( "{}, which {}" , msg, will_zero_extend) ,
405
+ suggestion) ;
406
+ }
407
+ }
408
+ true
409
+ }
410
+ ( & ty:: TyUint ( ref exp) , & ty:: TyInt ( ref found) ) => {
411
+ match ( found. bit_width ( ) , exp. bit_width ( ) ) {
412
+ ( Some ( found) , Some ( exp) ) if found - 1 > exp => {
413
+ err. span_suggestion ( expr. span ,
414
+ & format ! ( "{}, which {}" , msg, will_truncate) ,
415
+ suggestion) ;
416
+ }
417
+ ( None , None ) => {
418
+ err. span_suggestion ( expr. span ,
419
+ & format ! ( "{}, which {}" , msg, will_sign_extend) ,
420
+ suggestion) ;
421
+ }
422
+ ( None , _) => {
423
+ err. span_suggestion ( expr. span ,
424
+ & format ! ( "{}, which {}" , msg, depending_on_usize) ,
425
+ suggestion) ;
426
+ }
427
+ ( _, None ) => {
428
+ err. span_suggestion ( expr. span ,
429
+ & format ! ( "{}, which {}" , msg, depending_on_isize) ,
430
+ suggestion) ;
431
+ }
432
+ _ => {
433
+ err. span_suggestion ( expr. span ,
434
+ & format ! ( "{}, which {}" , msg, will_sign_extend) ,
435
+ suggestion) ;
436
+ }
437
+ }
438
+ true
439
+ }
440
+ ( & ty:: TyFloat ( ref exp) , & ty:: TyFloat ( ref found) ) => {
441
+ if found. bit_width ( ) > exp. bit_width ( ) {
442
+ err. span_suggestion ( expr. span ,
443
+ & format ! ( "{}, producing the closest possible value" ,
444
+ msg) ,
445
+ suggestion) ;
446
+ err. warn ( "casting here will cause Undefined Behavior if the value is \
447
+ finite but larger or smaller than the largest or smallest \
448
+ finite value representable by `f32` (this is a bug and will be \
449
+ fixed)") ;
450
+ } else {
451
+ err. span_suggestion ( expr. span ,
452
+ & format ! ( "{} in a lossless way" ,
453
+ msg) ,
454
+ suggestion) ;
455
+ }
456
+ true
457
+ }
458
+ ( & ty:: TyUint ( _) , & ty:: TyFloat ( _) ) | ( & ty:: TyInt ( _) , & ty:: TyFloat ( _) ) => {
459
+ err. span_suggestion ( expr. span ,
460
+ & format ! ( "{}, rounding the float towards zero" ,
461
+ msg) ,
462
+ suggestion) ;
463
+ err. warn ( "casting here will cause Undefined Behavior if the rounded value \
464
+ cannot be represented by the target integer type, including `Inf` \
465
+ and `NaN` (this is a bug and will be fixed)") ;
466
+ true
467
+ }
468
+ ( & ty:: TyFloat ( _) , & ty:: TyUint ( _) ) | ( & ty:: TyFloat ( _) , & ty:: TyInt ( _) ) => {
469
+ err. span_suggestion ( expr. span ,
470
+ & format ! ( "{}, producing the floating point representation \
471
+ of the integer, rounded if necessary",
472
+ msg) ,
473
+ suggestion) ;
474
+ true
475
+ }
476
+ _ => false ,
477
+ }
478
+ } else {
479
+ false
480
+ }
481
+ }
314
482
}
0 commit comments