Skip to content

Commit a6dfbb3

Browse files
authored
Stop inserting redundant parenthesis around desugared match expressions (#16102)
Currently the `sugg` utility treats all `ExprKind::Match` expressions as potentially needing brackets, and therefore many lints will add parenthesis around them. However this includes desugared match expressions like the `?` and `.await` operators. In this PR I have updated the utility to only treat match expressions which include a code block as needing parenthesis, as the other types have similar precedence rules and expectations to things like member access and I think can be treated like as such. While this change is small on paper it touches a large amount of code due to changing a cross cutting concern, I am happy to add additional tests if we think it is needed, but I wanted to get a feel for if this is even a sensible change to be doing and what the expectations were around the level of testing needed before investing more time into it. Regarding not putting a specific lint in the changelog, determining all the lints this could possibly effect would be possible but take some time, and I wonder if it would be a bit too noisy in the changelog. Open to suggestions about how best to address that. fixes #16045 changelog: stop inserting unnecessary brackets around `x?` and `x.await` expressions in suggestions
2 parents 6748911 + 466646f commit a6dfbb3

File tree

6 files changed

+96
-5
lines changed

6 files changed

+96
-5
lines changed

clippy_utils/src/sugg.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_ast::util::parser::AssocOp;
88
use rustc_ast::{UnOp, ast};
99
use rustc_data_structures::fx::FxHashSet;
1010
use rustc_errors::Applicability;
11-
use rustc_hir::{self as hir, Closure, ExprKind, HirId, MutTy, Node, TyKind};
11+
use rustc_hir::{self as hir, Closure, ExprKind, HirId, MatchSource, MutTy, Node, TyKind};
1212
use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
1313
use rustc_lint::{EarlyContext, LateContext, LintContext};
1414
use rustc_middle::hir::place::ProjectionKind;
@@ -146,7 +146,9 @@ impl<'a> Sugg<'a> {
146146
| ExprKind::Let(..)
147147
| ExprKind::Closure { .. }
148148
| ExprKind::Unary(..)
149-
| ExprKind::Match(..) => Sugg::MaybeParen(get_snippet(expr.span)),
149+
| ExprKind::Match(_, _,
150+
MatchSource::Normal | MatchSource::Postfix | MatchSource::ForLoopDesugar
151+
) => Sugg::MaybeParen(get_snippet(expr.span)),
150152
ExprKind::Continue(..)
151153
| ExprKind::Yield(..)
152154
| ExprKind::Array(..)
@@ -169,7 +171,10 @@ impl<'a> Sugg<'a> {
169171
| ExprKind::Tup(..)
170172
| ExprKind::Use(..)
171173
| ExprKind::Err(_)
172-
| ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(get_snippet(expr.span)),
174+
| ExprKind::UnsafeBinderCast(..)
175+
| ExprKind::Match(_, _,
176+
MatchSource::AwaitDesugar | MatchSource::TryDesugar(_) | MatchSource::FormatArgs
177+
) => Sugg::NonParen(get_snippet(expr.span)),
173178
ExprKind::DropTemps(inner) => Self::hir_from_snippet(cx, inner, get_snippet),
174179
ExprKind::Assign(lhs, rhs, _) => {
175180
Sugg::BinOp(AssocOp::Assign, get_snippet(lhs.span), get_snippet(rhs.span))

tests/ui/cast.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,3 +582,13 @@ mod issue14150 {
582582
//~^ cast_possible_wrap
583583
}
584584
}
585+
586+
fn issue16045() {
587+
fn f() -> Result<(), ()> {
588+
let val = Ok::<_, ()>(0u8);
589+
_ = val? as i8;
590+
//~^ cast_possible_wrap
591+
592+
Ok(())
593+
}
594+
}

tests/ui/cast.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,5 +764,11 @@ error: casting `u8` to `i8` may wrap around the value
764764
LL | _ = 1u8 as i8;
765765
| ^^^^^^^^^
766766

767-
error: aborting due to 94 previous errors
767+
error: casting `u8` to `i8` may wrap around the value
768+
--> tests/ui/cast.rs:589:13
769+
|
770+
LL | _ = val? as i8;
771+
| ^^^^^^^^^^ help: if this is intentional, use `cast_signed()` instead: `val?.cast_signed()`
772+
773+
error: aborting due to 95 previous errors
768774

tests/ui/redundant_pattern_matching_option.fixed

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,32 @@ fn issue13902() {
166166
//~^ redundant_pattern_matching
167167
}
168168
}
169+
170+
fn issue16045() {
171+
fn f() -> Result<(), ()> {
172+
let x = Ok::<_, ()>(Some(123));
173+
if x?.is_some() {
174+
//~^ redundant_pattern_matching
175+
}
176+
177+
Ok(())
178+
}
179+
180+
async fn g() {
181+
struct F {
182+
x: Option<u32>,
183+
}
184+
185+
impl Future for F {
186+
type Output = Option<u32>;
187+
188+
fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
189+
std::task::Poll::Ready(self.x)
190+
}
191+
}
192+
let x = F { x: Some(123) };
193+
if x.await.is_some() {
194+
//~^ redundant_pattern_matching
195+
}
196+
}
197+
}

tests/ui/redundant_pattern_matching_option.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,32 @@ fn issue13902() {
202202
//~^ redundant_pattern_matching
203203
}
204204
}
205+
206+
fn issue16045() {
207+
fn f() -> Result<(), ()> {
208+
let x = Ok::<_, ()>(Some(123));
209+
if let Some(_) = x? {
210+
//~^ redundant_pattern_matching
211+
}
212+
213+
Ok(())
214+
}
215+
216+
async fn g() {
217+
struct F {
218+
x: Option<u32>,
219+
}
220+
221+
impl Future for F {
222+
type Output = Option<u32>;
223+
224+
fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
225+
std::task::Poll::Ready(self.x)
226+
}
227+
}
228+
let x = F { x: Some(123) };
229+
if let Some(_) = x.await {
230+
//~^ redundant_pattern_matching
231+
}
232+
}
233+
}

tests/ui/redundant_pattern_matching_option.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,5 +224,17 @@ error: redundant pattern matching, consider using `is_none()`
224224
LL | let _ = matches!(*p, None);
225225
| ^^^^^^^^^^^^^^^^^^ help: try: `(*p).is_none()`
226226

227-
error: aborting due to 31 previous errors
227+
error: redundant pattern matching, consider using `is_some()`
228+
--> tests/ui/redundant_pattern_matching_option.rs:209:16
229+
|
230+
LL | if let Some(_) = x? {
231+
| -------^^^^^^^----- help: try: `if x?.is_some()`
232+
233+
error: redundant pattern matching, consider using `is_some()`
234+
--> tests/ui/redundant_pattern_matching_option.rs:229:16
235+
|
236+
LL | if let Some(_) = x.await {
237+
| -------^^^^^^^---------- help: try: `if x.await.is_some()`
238+
239+
error: aborting due to 33 previous errors
228240

0 commit comments

Comments
 (0)