@@ -1407,6 +1407,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1407
1407
true
1408
1408
}
1409
1409
1410
+ // Suggest to change `Option<&Vec<T>>::unwrap_or(&[])` to `Option::map_or(&[], |v| v)`.
1411
+ #[ instrument( level = "trace" , skip( self , err, provided_expr) ) ]
1412
+ pub ( crate ) fn suggest_deref_unwrap_or (
1413
+ & self ,
1414
+ err : & mut Diag < ' _ > ,
1415
+ error_span : Span ,
1416
+ callee_ty : Option < Ty < ' tcx > > ,
1417
+ call_ident : Option < Ident > ,
1418
+ expected_ty : Ty < ' tcx > ,
1419
+ provided_ty : Ty < ' tcx > ,
1420
+ provided_expr : & Expr < ' tcx > ,
1421
+ is_method : bool ,
1422
+ ) {
1423
+ if !is_method {
1424
+ return ;
1425
+ }
1426
+ let Some ( callee_ty) = callee_ty else {
1427
+ return ;
1428
+ } ;
1429
+ let ty:: Adt ( callee_adt, _) = callee_ty. peel_refs ( ) . kind ( ) else {
1430
+ return ;
1431
+ } ;
1432
+ if !self . tcx . is_diagnostic_item ( sym:: Option , callee_adt. did ( ) ) {
1433
+ return ;
1434
+ }
1435
+
1436
+ if call_ident. map_or ( true , |ident| ident. name != sym:: unwrap_or) {
1437
+ return ;
1438
+ }
1439
+
1440
+ let ty:: Ref ( _, peeled, _mutability) = provided_ty. kind ( ) else {
1441
+ return ;
1442
+ } ;
1443
+
1444
+ // NOTE: Can we reuse `suggest_deref_or_ref`?
1445
+
1446
+ // Create an dummy type `&[_]` so that both &[] and `&Vec<T>` can coerce to it.
1447
+ let dummy_ty = if let ty:: Array ( elem_ty, size) = peeled. kind ( )
1448
+ && let ty:: Infer ( _) = elem_ty. kind ( )
1449
+ && size. try_eval_target_usize ( self . tcx , self . param_env ) == Some ( 0 )
1450
+ {
1451
+ let slice = Ty :: new_slice ( self . tcx , * elem_ty) ;
1452
+ Ty :: new_imm_ref ( self . tcx , self . tcx . lifetimes . re_static , slice)
1453
+ } else {
1454
+ provided_ty
1455
+ } ;
1456
+
1457
+ if !self . can_coerce ( expected_ty, dummy_ty) {
1458
+ return ;
1459
+ }
1460
+ let ( provided_snip, applicability) =
1461
+ match self . tcx . sess . source_map ( ) . span_to_snippet ( provided_expr. span ) {
1462
+ Ok ( snip) => ( snip, Applicability :: MachineApplicable ) ,
1463
+ Err ( _) => ( "/* _ */" . to_owned ( ) , Applicability :: MaybeIncorrect ) ,
1464
+ } ;
1465
+ let sugg = & format ! ( "map_or({provided_snip}, |v| v)" ) ;
1466
+ err. span_suggestion_verbose (
1467
+ error_span,
1468
+ "use `Option::map_or` to deref inner value of `Option`" ,
1469
+ sugg,
1470
+ applicability,
1471
+ ) ;
1472
+ return ;
1473
+ }
1474
+
1410
1475
/// Suggest wrapping the block in square brackets instead of curly braces
1411
1476
/// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
1412
1477
pub ( crate ) fn suggest_block_to_brackets (
0 commit comments