@@ -1407,6 +1407,71 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14071407 true
14081408 }
14091409
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+
14101475 /// Suggest wrapping the block in square brackets instead of curly braces
14111476 /// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
14121477 pub ( crate ) fn suggest_block_to_brackets (
0 commit comments