Skip to content

Commit 876d6d8

Browse files
authored
Merge pull request rust-lang#2166 from HMPerson1/fix_2160
Fix rust-lang#2160
2 parents 7d7fef1 + c2c324e commit 876d6d8

File tree

3 files changed

+74
-58
lines changed

3 files changed

+74
-58
lines changed

clippy_lints/src/is_unit_expr.rs

+50-58
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc::lint::*;
22
use syntax::ast::*;
33
use syntax::ext::quote::rt::Span;
4-
use utils::span_note_and_lint;
4+
use utils::{span_lint, span_note_and_lint};
55

66
/// **What it does:** Checks for
77
/// - () being assigned to a variable
@@ -24,6 +24,12 @@ declare_lint! {
2424
"unintended assignment or use of a unit typed value"
2525
}
2626

27+
#[derive(Copy, Clone)]
28+
enum UnitCause {
29+
SemiColon,
30+
EmptyBlock,
31+
}
32+
2733
#[derive(Copy, Clone)]
2834
pub struct UnitExpr;
2935

@@ -36,43 +42,16 @@ impl LintPass for UnitExpr {
3642
impl EarlyLintPass for UnitExpr {
3743
fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
3844
if let ExprKind::Assign(ref _left, ref right) = expr.node {
39-
if let Some(span) = is_unit_expr(right) {
40-
span_note_and_lint(
41-
cx,
42-
UNIT_EXPR,
43-
expr.span,
44-
"This expression evaluates to the Unit type ()",
45-
span,
46-
"Consider removing the trailing semicolon",
47-
);
48-
}
45+
check_for_unit(cx, right);
4946
}
5047
if let ExprKind::MethodCall(ref _left, ref args) = expr.node {
5148
for arg in args {
52-
if let Some(span) = is_unit_expr(arg) {
53-
span_note_and_lint(
54-
cx,
55-
UNIT_EXPR,
56-
expr.span,
57-
"This expression evaluates to the Unit type ()",
58-
span,
59-
"Consider removing the trailing semicolon",
60-
);
61-
}
49+
check_for_unit(cx, arg);
6250
}
6351
}
6452
if let ExprKind::Call(_, ref args) = expr.node {
6553
for arg in args {
66-
if let Some(span) = is_unit_expr(arg) {
67-
span_note_and_lint(
68-
cx,
69-
UNIT_EXPR,
70-
expr.span,
71-
"This expression evaluates to the Unit type ()",
72-
span,
73-
"Consider removing the trailing semicolon",
74-
);
75-
}
54+
check_for_unit(cx, arg);
7655
}
7756
}
7857
}
@@ -83,28 +62,41 @@ impl EarlyLintPass for UnitExpr {
8362
return;
8463
}
8564
if let Some(ref expr) = local.init {
86-
if let Some(span) = is_unit_expr(expr) {
87-
span_note_and_lint(
88-
cx,
89-
UNIT_EXPR,
90-
expr.span,
91-
"This expression evaluates to the Unit type ()",
92-
span,
93-
"Consider removing the trailing semicolon",
94-
);
95-
}
65+
check_for_unit(cx, expr);
9666
}
9767
}
9868
}
9969
}
10070

101-
fn is_unit_expr(expr: &Expr) -> Option<Span> {
71+
fn check_for_unit(cx: &EarlyContext, expr: &Expr) {
72+
match is_unit_expr(expr) {
73+
Some((span, UnitCause::SemiColon)) => span_note_and_lint(
74+
cx,
75+
UNIT_EXPR,
76+
expr.span,
77+
"This expression evaluates to the Unit type ()",
78+
span,
79+
"Consider removing the trailing semicolon",
80+
),
81+
Some((_span, UnitCause::EmptyBlock)) => span_lint(
82+
cx,
83+
UNIT_EXPR,
84+
expr.span,
85+
"This expression evaluates to the Unit type ()",
86+
),
87+
None => (),
88+
}
89+
}
90+
91+
fn is_unit_expr(expr: &Expr) -> Option<(Span, UnitCause)> {
10292
match expr.node {
103-
ExprKind::Block(ref block) => if check_last_stmt_in_block(block) {
104-
Some(block.stmts[block.stmts.len() - 1].span)
105-
} else {
106-
None
107-
},
93+
ExprKind::Block(ref block) => match check_last_stmt_in_block(block) {
94+
Some(UnitCause::SemiColon) =>
95+
Some((block.stmts[block.stmts.len() - 1].span, UnitCause::SemiColon)),
96+
Some(UnitCause::EmptyBlock) =>
97+
Some((block.span, UnitCause::EmptyBlock)),
98+
None => None
99+
}
108100
ExprKind::If(_, ref then, ref else_) => {
109101
let check_then = check_last_stmt_in_block(then);
110102
if let Some(ref else_) = *else_ {
@@ -113,16 +105,15 @@ fn is_unit_expr(expr: &Expr) -> Option<Span> {
113105
return Some(*expr_else);
114106
}
115107
}
116-
if check_then {
117-
Some(expr.span)
118-
} else {
119-
None
108+
match check_then {
109+
Some(c) => Some((expr.span, c)),
110+
None => None,
120111
}
121112
},
122113
ExprKind::Match(ref _pattern, ref arms) => {
123114
for arm in arms {
124-
if let Some(expr) = is_unit_expr(&arm.body) {
125-
return Some(expr);
115+
if let Some(r) = is_unit_expr(&arm.body) {
116+
return Some(r);
126117
}
127118
}
128119
None
@@ -131,18 +122,19 @@ fn is_unit_expr(expr: &Expr) -> Option<Span> {
131122
}
132123
}
133124

134-
fn check_last_stmt_in_block(block: &Block) -> bool {
125+
fn check_last_stmt_in_block(block: &Block) -> Option<UnitCause> {
126+
if block.stmts.is_empty() { return Some(UnitCause::EmptyBlock); }
135127
let final_stmt = &block.stmts[block.stmts.len() - 1];
136128

137129

138130
// Made a choice here to risk false positives on divergent macro invocations
139131
// like `panic!()`
140132
match final_stmt.node {
141-
StmtKind::Expr(_) => false,
133+
StmtKind::Expr(_) => None,
142134
StmtKind::Semi(ref expr) => match expr.node {
143-
ExprKind::Break(_, _) | ExprKind::Continue(_) | ExprKind::Ret(_) => false,
144-
_ => true,
135+
ExprKind::Break(_, _) | ExprKind::Continue(_) | ExprKind::Ret(_) => None,
136+
_ => Some(UnitCause::SemiColon),
145137
},
146-
_ => true,
138+
_ => Some(UnitCause::SemiColon), // not sure what's happening here
147139
}
148140
}

tests/ui/is_unit_expr.rs

+6
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,9 @@ pub fn foo() -> i32 {
7171
};
7272
55
7373
}
74+
75+
pub fn issue_2160() {
76+
let x1 = {};
77+
let x2 = if true {} else {};
78+
let x3 = match None { Some(_) => {}, None => {}, };
79+
}

tests/ui/is_unit_expr.stderr

+18
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,21 @@ note: Consider removing the trailing semicolon
5151
42 | x;
5252
| ^^
5353

54+
error: This expression evaluates to the Unit type ()
55+
--> $DIR/is_unit_expr.rs:76:14
56+
|
57+
76 | let x1 = {};
58+
| ^^
59+
60+
error: This expression evaluates to the Unit type ()
61+
--> $DIR/is_unit_expr.rs:77:14
62+
|
63+
77 | let x2 = if true {} else {};
64+
| ^^^^^^^^^^^^^^^^^^
65+
66+
error: This expression evaluates to the Unit type ()
67+
--> $DIR/is_unit_expr.rs:78:14
68+
|
69+
78 | let x3 = match None { Some(_) => {}, None => {}, };
70+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71+

0 commit comments

Comments
 (0)