Skip to content

Commit 956e50b

Browse files
authored
Rollup merge of #70789 - lcnr:macros, r=varkor
remove false positives of unused_braces fixes #70717 We could potentially be more aggressive when linting let bindings by checking if there are any explicit `ref`s. I have been unable to create a snippet which compiles when using braces but has a borrowck error without them. The closes I've gotten is [the following (playground)](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4a1552ebe9648cb13fcb8dd969189a6c). r? @eddyb
2 parents 42abbd8 + 817f059 commit 956e50b

File tree

5 files changed

+72
-25
lines changed

5 files changed

+72
-25
lines changed

src/librustc_lint/unused.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,19 @@ impl From<UnusedDelimsCtx> for &'static str {
355355
trait UnusedDelimLint {
356356
const DELIM_STR: &'static str;
357357

358+
/// Due to `ref` pattern, there can be a difference between using
359+
/// `{ expr }` and `expr` in pattern-matching contexts. This means
360+
/// that we should only lint `unused_parens` and not `unused_braces`
361+
/// in this case.
362+
///
363+
/// ```rust
364+
/// let mut a = 7;
365+
/// let ref b = { a }; // We actually borrow a copy of `a` here.
366+
/// a += 1; // By mutating `a` we invalidate any borrows of `a`.
367+
/// assert_eq!(b + 1, a); // `b` does not borrow `a`, so we can still use it here.
368+
/// ```
369+
const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool;
370+
358371
// this cannot be a constant is it refers to a static.
359372
fn lint(&self) -> &'static Lint;
360373

@@ -454,7 +467,10 @@ trait UnusedDelimLint {
454467
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
455468
use rustc_ast::ast::ExprKind::*;
456469
let (value, ctx, followed_by_block, left_pos, right_pos) = match e.kind {
457-
If(ref cond, ref block, ..) => {
470+
// Do not lint `unused_braces` in `if let` expressions.
471+
If(ref cond, ref block, ..)
472+
if !matches!(cond.kind, Let(_, _)) || Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX =>
473+
{
458474
let left = e.span.lo() + rustc_span::BytePos(2);
459475
let right = block.span.lo();
460476
(cond, UnusedDelimsCtx::IfCond, true, Some(left), Some(right))
@@ -470,7 +486,7 @@ trait UnusedDelimLint {
470486
(cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()))
471487
}
472488

473-
Match(ref head, _) => {
489+
Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
474490
let left = e.span.lo() + rustc_span::BytePos(5);
475491
(head, UnusedDelimsCtx::MatchScrutineeExpr, true, Some(left), None)
476492
}
@@ -512,7 +528,7 @@ trait UnusedDelimLint {
512528

513529
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
514530
match s.kind {
515-
StmtKind::Local(ref local) => {
531+
StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
516532
if let Some(ref value) = local.init {
517533
self.check_unused_delims_expr(
518534
cx,
@@ -565,6 +581,8 @@ declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
565581
impl UnusedDelimLint for UnusedParens {
566582
const DELIM_STR: &'static str = "parentheses";
567583

584+
const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = true;
585+
568586
fn lint(&self) -> &'static Lint {
569587
UNUSED_PARENS
570588
}
@@ -736,6 +754,8 @@ declare_lint_pass!(UnusedBraces => [UNUSED_BRACES]);
736754
impl UnusedDelimLint for UnusedBraces {
737755
const DELIM_STR: &'static str = "braces";
738756

757+
const LINT_EXPR_IN_PATTERN_MATCHING_CTX: bool = false;
758+
739759
fn lint(&self) -> &'static Lint {
740760
UNUSED_BRACES
741761
}

src/test/ui/lint/unused_braces.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,48 @@
11
// check-pass
22
#![warn(unused_braces, unused_parens)]
33

4+
fn consume<T>(_: T) {}
5+
46
fn main() {
57
let _ = (7);
68
//~^WARN unnecessary parentheses
79

8-
let _ = { 7 };
9-
//~^ WARN unnecessary braces
10+
// Do not emit a lint in these cases,
11+
// as we have to be careful with
12+
// `ref` patterns.
13+
{
14+
let _ = { 7 };
15+
16+
if let 7 = { 7 } { }
17+
18+
match { 7 } {
19+
_ => (),
20+
}
21+
}
1022

11-
if let 7 = { 7 } {
23+
if { true } {
24+
//~^ WARN unnecessary braces
25+
}
26+
27+
while { false } {
1228
//~^ WARN unnecessary braces
1329
}
1430

1531
let _: [u8; { 3 }];
1632
//~^ WARN unnecessary braces
1733

18-
// do not emit error for multiline blocks.
34+
consume({ 7 });
35+
//~^ WARN unnecessary braces
36+
37+
// Do not emit lint for multiline blocks.
1938
let _ = {
2039
7
2140
};
2241

23-
// do not emit error for unsafe blocks.
42+
// Do not emit lint for unsafe blocks.
2443
let _ = unsafe { 7 };
2544

26-
// do not emit error, as the `{` would then
45+
// Do not emit lint, as the `{` would then
2746
// be parsed as part of the `return`.
2847
if { return } {
2948

src/test/ui/lint/unused_braces.stderr

+16-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: unnecessary parentheses around assigned value
2-
--> $DIR/unused_braces.rs:5:13
2+
--> $DIR/unused_braces.rs:7:13
33
|
44
LL | let _ = (7);
55
| ^^^ help: remove these parentheses
@@ -10,27 +10,33 @@ note: the lint level is defined here
1010
LL | #![warn(unused_braces, unused_parens)]
1111
| ^^^^^^^^^^^^^
1212

13-
warning: unnecessary braces around assigned value
14-
--> $DIR/unused_braces.rs:8:13
13+
warning: unnecessary braces around `if` condition
14+
--> $DIR/unused_braces.rs:23:8
1515
|
16-
LL | let _ = { 7 };
17-
| ^^^^^ help: remove these braces
16+
LL | if { true } {
17+
| ^^^^^^^^ help: remove these braces
1818
|
1919
note: the lint level is defined here
2020
--> $DIR/unused_braces.rs:2:9
2121
|
2222
LL | #![warn(unused_braces, unused_parens)]
2323
| ^^^^^^^^^^^^^
2424

25-
warning: unnecessary braces around `let` scrutinee expression
26-
--> $DIR/unused_braces.rs:11:16
25+
warning: unnecessary braces around `while` condition
26+
--> $DIR/unused_braces.rs:27:11
2727
|
28-
LL | if let 7 = { 7 } {
29-
| ^^^^^ help: remove these braces
28+
LL | while { false } {
29+
| ^^^^^^^^^ help: remove these braces
3030

3131
warning: unnecessary braces around const expression
32-
--> $DIR/unused_braces.rs:15:17
32+
--> $DIR/unused_braces.rs:31:17
3333
|
3434
LL | let _: [u8; { 3 }];
3535
| ^^^^^ help: remove these braces
3636

37+
warning: unnecessary braces around function argument
38+
--> $DIR/unused_braces.rs:34:13
39+
|
40+
LL | consume({ 7 });
41+
| ^^^^^ help: remove these braces
42+

src/test/ui/lint/unused_parens_borrow.rs renamed to src/test/ui/lint/unused_braces_borrow.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ struct A {
1010
b: u32,
1111
}
1212

13+
fn consume<T>(_: T) {}
14+
1315
fn main() {
1416
let a = A {
1517
a: 42,
1618
b: 1729,
1719
};
1820

19-
let _ = &{ a.b };
20-
let _ = { a.b };
21+
consume(&{ a.b });
22+
consume({ a.b });
2123
//~^ WARN unnecessary braces
2224
}

src/test/ui/lint/unused_parens_borrow.stderr renamed to src/test/ui/lint/unused_braces_borrow.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
warning: unnecessary braces around assigned value
2-
--> $DIR/unused_parens_borrow.rs:20:13
1+
warning: unnecessary braces around function argument
2+
--> $DIR/unused_braces_borrow.rs:22:13
33
|
4-
LL | let _ = { a.b };
4+
LL | consume({ a.b });
55
| ^^^^^^^ help: remove these braces
66
|
77
note: the lint level is defined here
8-
--> $DIR/unused_parens_borrow.rs:2:9
8+
--> $DIR/unused_braces_borrow.rs:2:9
99
|
1010
LL | #![warn(unused_braces)]
1111
| ^^^^^^^^^^^^^

0 commit comments

Comments
 (0)