@@ -2,15 +2,15 @@ use rustc_errors::Applicability;
22use rustc_hir:: def:: Res ;
33use rustc_hir:: { Arm , Expr , ExprKind , HirId , LangItem , MatchSource , Pat , PatKind , QPath } ;
44use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
5- use rustc_middle:: ty:: { self , GenericArgKind } ;
5+ use rustc_middle:: ty:: GenericArgKind ;
66use rustc_session:: declare_lint_pass;
77use rustc_span:: sym;
88
99use clippy_utils:: diagnostics:: span_lint_and_sugg;
1010use clippy_utils:: higher:: IfLetOrMatch ;
1111use clippy_utils:: sugg:: Sugg ;
12- use clippy_utils:: ty:: implements_trait;
13- use clippy_utils:: { is_default_equivalent, is_in_const_context, peel_blocks, span_contains_comment} ;
12+ use clippy_utils:: ty:: { expr_type_is_certain , implements_trait} ;
13+ use clippy_utils:: { is_default_equivalent, is_in_const_context, path_res , peel_blocks, span_contains_comment} ;
1414
1515declare_clippy_lint ! {
1616 /// ### What it does
@@ -152,48 +152,42 @@ fn handle<'tcx>(cx: &LateContext<'tcx>, if_let_or_match: IfLetOrMatch<'tcx>, exp
152152 && is_default_equivalent ( cx, body_none)
153153 && let Some ( receiver) = Sugg :: hir_opt ( cx, condition) . map ( Sugg :: maybe_par)
154154 {
155- // We check if the expression is not a None variant
156- if let Some ( none_def_id) = cx. tcx . lang_items ( ) . option_none_variant ( ) {
157- if let ExprKind :: Path ( QPath :: Resolved ( _, path) ) = & condition. kind {
158- if let Some ( def_id) = path. res . opt_def_id ( ) {
159- if cx. tcx . parent ( def_id) == none_def_id {
160- return span_lint_and_sugg (
161- cx,
162- MANUAL_UNWRAP_OR_DEFAULT ,
163- expr. span ,
164- format ! ( "{expr_name} can be simplified with `.unwrap_or_default()`" ) ,
165- "replace it with" ,
166- format ! ( "{receiver}::</* Type */>.unwrap_or_default()" ) ,
167- Applicability :: HasPlaceholders ,
168- ) ;
169- }
170- }
171- }
172- }
173-
174- // We check if the expression is not a method or function with a unspecified return type
175- if let ExprKind :: MethodCall ( _, expr, _, _) = & condition. kind {
176- if let ty:: Adt ( _, substs) = cx. typeck_results ( ) . expr_ty ( expr) . kind ( ) {
177- if let Some ( ok_type) = substs. first ( ) {
178- return span_lint_and_sugg (
179- cx,
180- MANUAL_UNWRAP_OR_DEFAULT ,
181- expr. span ,
182- format ! ( "{expr_name} can be simplified with `.unwrap_or_default()`" ) ,
183- format ! ( "explicit the type {ok_type} and replace your expression with" ) ,
184- format ! ( "{receiver}.unwrap_or_default()" ) ,
185- Applicability :: Unspecified ,
186- ) ;
187- }
188- }
189- }
190-
191155 // Machine applicable only if there are no comments present
192156 let applicability = if span_contains_comment ( cx. sess ( ) . source_map ( ) , expr. span ) {
193157 Applicability :: MaybeIncorrect
194158 } else {
195159 Applicability :: MachineApplicable
196160 } ;
161+
162+ // We now check if the condition is a None variant, in which case we need to specify the type
163+ if path_res ( cx, condition)
164+ . opt_def_id ( )
165+ . is_some_and ( |id| Some ( cx. tcx . parent ( id) ) == cx. tcx . lang_items ( ) . option_none_variant ( ) )
166+ {
167+ return span_lint_and_sugg (
168+ cx,
169+ MANUAL_UNWRAP_OR_DEFAULT ,
170+ expr. span ,
171+ format ! ( "{expr_name} can be simplified with `.unwrap_or_default()`" ) ,
172+ "replace it with" ,
173+ format ! ( "{receiver}::<{expr_type}>.unwrap_or_default()" ) ,
174+ applicability,
175+ ) ;
176+ }
177+
178+ // We check if the expression type is still uncertain, in which case we ask the user to specify it
179+ if !expr_type_is_certain ( cx, condition) {
180+ return span_lint_and_sugg (
181+ cx,
182+ MANUAL_UNWRAP_OR_DEFAULT ,
183+ expr. span ,
184+ format ! ( "{expr_name} can be simplified with `.unwrap_or_default()`" ) ,
185+ format ! ( "ascribe the type {expr_type} and replace your expression with" ) ,
186+ format ! ( "{receiver}.unwrap_or_default()" ) ,
187+ Applicability :: Unspecified ,
188+ ) ;
189+ }
190+
197191 span_lint_and_sugg (
198192 cx,
199193 MANUAL_UNWRAP_OR_DEFAULT ,
0 commit comments