@@ -34,6 +34,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
34
34
self . annotate_expected_due_to_let_ty ( err, expr, error) ;
35
35
self . suggest_deref_ref_or_into ( err, expr, expected, expr_ty, expected_ty_expr) ;
36
36
self . suggest_compatible_variants ( err, expr, expected, expr_ty) ;
37
+ self . suggest_non_zero_new_unwrap ( err, expr, expected, expr_ty) ;
37
38
if self . suggest_calling_boxed_future_when_appropriate ( err, expr, expected, expr_ty) {
38
39
return ;
39
40
}
@@ -418,6 +419,59 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
418
419
}
419
420
}
420
421
422
+ fn suggest_non_zero_new_unwrap (
423
+ & self ,
424
+ err : & mut Diagnostic ,
425
+ expr : & hir:: Expr < ' _ > ,
426
+ expected : Ty < ' tcx > ,
427
+ expr_ty : Ty < ' tcx > ,
428
+ ) {
429
+ let tcx = self . tcx ;
430
+ let ( adt, unwrap) = match expected. kind ( ) {
431
+ // In case Option<NonZero*> is wanted, but * is provided, suggest calling new
432
+ ty:: Adt ( adt, substs) if tcx. is_diagnostic_item ( sym:: Option , adt. did ( ) ) => {
433
+ // Unwrap option
434
+ let Some ( fst) = substs. first ( ) else { return } ;
435
+ let ty:: Adt ( adt, _) = fst. expect_ty ( ) . kind ( ) else { return } ;
436
+
437
+ ( adt, "" )
438
+ }
439
+ // In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types
440
+ ty:: Adt ( adt, _) => ( adt, ".unwrap()" ) ,
441
+ _ => return ,
442
+ } ;
443
+
444
+ let map = [
445
+ ( sym:: NonZeroU8 , tcx. types . u8 ) ,
446
+ ( sym:: NonZeroU16 , tcx. types . u16 ) ,
447
+ ( sym:: NonZeroU32 , tcx. types . u32 ) ,
448
+ ( sym:: NonZeroU64 , tcx. types . u64 ) ,
449
+ ( sym:: NonZeroU128 , tcx. types . u128 ) ,
450
+ ( sym:: NonZeroI8 , tcx. types . i8 ) ,
451
+ ( sym:: NonZeroI16 , tcx. types . i16 ) ,
452
+ ( sym:: NonZeroI32 , tcx. types . i32 ) ,
453
+ ( sym:: NonZeroI64 , tcx. types . i64 ) ,
454
+ ( sym:: NonZeroI128 , tcx. types . i128 ) ,
455
+ ] ;
456
+
457
+ let Some ( ( s, _) ) = map
458
+ . iter ( )
459
+ . find ( |& & ( s, _) | self . tcx . is_diagnostic_item ( s, adt. did ( ) ) )
460
+ . filter ( |& & ( _, t) | { self . can_coerce ( expr_ty, t) } )
461
+ else { return } ;
462
+
463
+ let path = self . tcx . def_path_str ( adt. non_enum_variant ( ) . def_id ) ;
464
+
465
+ err. multipart_suggestion (
466
+ format ! ( "consider calling `{s}::new`" ) ,
467
+ vec ! [
468
+ ( expr. span. shrink_to_lo( ) , format!( "{path}::new(" ) ) ,
469
+ ( expr. span. shrink_to_hi( ) , format!( "){unwrap}" ) ) ,
470
+ ] ,
471
+ Applicability :: MaybeIncorrect ,
472
+ ) ;
473
+ }
474
+
421
475
pub fn get_conversion_methods (
422
476
& self ,
423
477
span : Span ,
0 commit comments