Skip to content

Commit 801eafd

Browse files
committed
Suggest if let PAT == expr on let PAT = expr else with non-structural type const
``` error: constant of non-structural type `partial_eq::S` in a pattern --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:22:18 | LL | struct S; | -------- `partial_eq::S` must be annotated with `#[derive(PartialEq)]` to be usable in patterns ... LL | const C: S = S; | ---------- constant defined here ... LL | let Some(C) = Some(S) else { return; }; | ^ constant of non-structural type | note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient; see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details --> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:5:5 | LL | impl PartialEq<S> for S { | ^^^^^^^^^^^^^^^^^^^^^^^ help: check for equality instead of pattern matching | LL - let Some(C) = Some(S) else { return; }; LL + if Some(C) == Some(S) { return; }; | ```
1 parent 3f08f67 commit 801eafd

4 files changed

Lines changed: 65 additions & 2 deletions

File tree

compiler/rustc_mir_build/src/errors.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,6 +1144,24 @@ pub(crate) enum SuggestEq<'tcx> {
11441144
ty: Ty<'tcx>,
11451145
manual_partialeq_impl: bool,
11461146
},
1147+
#[multipart_suggestion(
1148+
"{$manual_partialeq_impl ->
1149+
[false] if `{$ty}` manually implemented `PartialEq`, you could check
1150+
*[true] check
1151+
} for equality instead of pattern matching",
1152+
applicability = "maybe-incorrect",
1153+
style = "verbose"
1154+
)]
1155+
ReplaceLetElseWithIf {
1156+
#[suggestion_part(code = "if ")]
1157+
if_span: Span,
1158+
#[suggestion_part(code = " == ")]
1159+
eq: Span,
1160+
#[suggestion_part(code = " ")]
1161+
else_span: Span,
1162+
ty: Ty<'tcx>,
1163+
manual_partialeq_impl: bool,
1164+
},
11471165
}
11481166

11491167
#[derive(Diagnostic)]

compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,21 @@ impl<'tcx> ConstToPat<'tcx> {
283283
None
284284
}
285285
}
286+
hir::Node::LetStmt(let_stmt)
287+
if let Some(init) = let_stmt.init
288+
&& let Some(els) = let_stmt.els
289+
&& init.span.ctxt().is_root()
290+
&& els.span.ctxt().is_root() =>
291+
{
292+
// `let PAT = expr else {` -> `if PAT == expr {`.
293+
Some(SuggestEq::ReplaceLetElseWithIf {
294+
if_span: let_stmt.span.until(let_stmt.pat.span),
295+
eq: let_stmt.pat.span.between(init.span),
296+
else_span: init.span.between(els.span),
297+
ty,
298+
manual_partialeq_impl,
299+
})
300+
}
286301
_ => None,
287302
}
288303
} else {

tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ mod partial_eq {
2626
}
2727
if let V = vec![] {} //~ ERROR: constant of non-structural type
2828
let V = vec![] else { return; }; //~ ERROR: constant of non-structural type
29-
// ^ maybe suggest if V != vec![] { return; } ?
29+
let V = Vec::new() else { return; }; //~ ERROR: constant of non-structural type
3030
}
3131
}
3232

tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ note: the `PartialEq` trait must be derived, manual `impl`s are not sufficient;
107107
|
108108
LL | impl PartialEq<S> for S {
109109
| ^^^^^^^^^^^^^^^^^^^^^^^
110+
help: check for equality instead of pattern matching
111+
|
112+
LL - let Some(C) = Some(S) else { return; };
113+
LL + if Some(C) == Some(S) { return; };
114+
|
110115

111116
error: constant of non-structural type `Vec<()>` in a pattern
112117
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:24:13
@@ -158,6 +163,26 @@ LL | let V = vec![] else { return; };
158163
|
159164
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
160165

166+
error: constant of non-structural type `Vec<()>` in a pattern
167+
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:29:13
168+
|
169+
LL | const V: Vec<()> = vec![];
170+
| ---------------- constant defined here
171+
...
172+
LL | let V = Vec::new() else { return; };
173+
| ^ constant of non-structural type
174+
|
175+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
176+
|
177+
= note: `Vec<()>` is not usable in patterns
178+
|
179+
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
180+
help: check for equality instead of pattern matching
181+
|
182+
LL - let V = Vec::new() else { return; };
183+
LL + if V == Vec::new() { return; };
184+
|
185+
161186
error: constant of non-structural type `not_partial_eq::S` in a pattern
162187
--> $DIR/suggest_equality_comparison_instead_of_pattern_matching.rs:40:18
163188
|
@@ -247,6 +272,11 @@ LL | let Some(C) = Some(S) else { return; };
247272
| ^ constant of non-structural type
248273
|
249274
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
275+
help: check for equality instead of pattern matching
276+
|
277+
LL - let Some(C) = Some(S) else { return; };
278+
LL + if Some(C) == Some(S) { return; };
279+
|
250280

251-
error: aborting due to 13 previous errors
281+
error: aborting due to 14 previous errors
252282

0 commit comments

Comments
 (0)