rustc: update the unnecessary parens lint for struct literals.
Things like `match X { x: 1 } { ... }` now need to be written with parentheses, so the lint should avoid warning in cases like that.
This commit is contained in:
parent
8fe47bc3bb
commit
64019e764f
2 changed files with 74 additions and 13 deletions
|
@ -975,14 +975,52 @@ declare_lint!(UNNECESSARY_PARENS, Warn,
|
||||||
pub struct UnnecessaryParens;
|
pub struct UnnecessaryParens;
|
||||||
|
|
||||||
impl UnnecessaryParens {
|
impl UnnecessaryParens {
|
||||||
fn check_unnecessary_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str) {
|
fn check_unnecessary_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str,
|
||||||
|
struct_lit_needs_parens: bool) {
|
||||||
match value.node {
|
match value.node {
|
||||||
ast::ExprParen(_) => {
|
ast::ExprParen(ref inner) => {
|
||||||
|
let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner);
|
||||||
|
if !necessary {
|
||||||
cx.span_lint(UNNECESSARY_PARENS, value.span,
|
cx.span_lint(UNNECESSARY_PARENS, value.span,
|
||||||
format!("unnecessary parentheses around {}", msg).as_slice())
|
format!("unnecessary parentheses around {}",
|
||||||
|
msg).as_slice())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expressions that syntatically contain an "exterior" struct
|
||||||
|
/// literal i.e. not surrounded by any parens or other
|
||||||
|
/// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo
|
||||||
|
/// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X {
|
||||||
|
/// y: 1 }) == foo` does not.
|
||||||
|
fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
|
||||||
|
match value.node {
|
||||||
|
ast::ExprStruct(..) => true,
|
||||||
|
|
||||||
|
ast::ExprAssign(ref lhs, ref rhs) |
|
||||||
|
ast::ExprAssignOp(_, ref lhs, ref rhs) |
|
||||||
|
ast::ExprBinary(_, ref lhs, ref rhs) => {
|
||||||
|
// X { y: 1 } + X { y: 2 }
|
||||||
|
contains_exterior_struct_lit(&**lhs) ||
|
||||||
|
contains_exterior_struct_lit(&**rhs)
|
||||||
|
}
|
||||||
|
ast::ExprUnary(_, ref x) |
|
||||||
|
ast::ExprCast(ref x, _) |
|
||||||
|
ast::ExprField(ref x, _, _) |
|
||||||
|
ast::ExprIndex(ref x, _) => {
|
||||||
|
// &X { y: 1 }, X { y: 1 }.y
|
||||||
|
contains_exterior_struct_lit(&**x)
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::ExprMethodCall(_, _, ref exprs) => {
|
||||||
|
// X { y: 1 }.bar(...)
|
||||||
|
contains_exterior_struct_lit(&**exprs.get(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,16 +1030,16 @@ impl LintPass for UnnecessaryParens {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
|
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
|
||||||
let (value, msg) = match e.node {
|
let (value, msg, struct_lit_needs_parens) = match e.node {
|
||||||
ast::ExprIf(cond, _, _) => (cond, "`if` condition"),
|
ast::ExprIf(cond, _, _) => (cond, "`if` condition", true),
|
||||||
ast::ExprWhile(cond, _) => (cond, "`while` condition"),
|
ast::ExprWhile(cond, _) => (cond, "`while` condition", true),
|
||||||
ast::ExprMatch(head, _) => (head, "`match` head expression"),
|
ast::ExprMatch(head, _) => (head, "`match` head expression", true),
|
||||||
ast::ExprRet(Some(value)) => (value, "`return` value"),
|
ast::ExprRet(Some(value)) => (value, "`return` value", false),
|
||||||
ast::ExprAssign(_, value) => (value, "assigned value"),
|
ast::ExprAssign(_, value) => (value, "assigned value", false),
|
||||||
ast::ExprAssignOp(_, _, value) => (value, "assigned value"),
|
ast::ExprAssignOp(_, _, value) => (value, "assigned value", false),
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
self.check_unnecessary_parens_core(cx, &*value, msg);
|
self.check_unnecessary_parens_core(cx, &*value, msg, struct_lit_needs_parens);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
|
fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
|
||||||
|
@ -1015,7 +1053,7 @@ impl LintPass for UnnecessaryParens {
|
||||||
},
|
},
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
self.check_unnecessary_parens_core(cx, &*value, msg);
|
self.check_unnecessary_parens_core(cx, &*value, msg, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,41 @@
|
||||||
|
|
||||||
#![deny(unnecessary_parens)]
|
#![deny(unnecessary_parens)]
|
||||||
|
|
||||||
|
#[deriving(Eq, PartialEq)]
|
||||||
|
struct X { y: bool }
|
||||||
|
impl X {
|
||||||
|
fn foo(&self) -> bool { self.y }
|
||||||
|
}
|
||||||
|
|
||||||
fn foo() -> int {
|
fn foo() -> int {
|
||||||
return (1); //~ ERROR unnecessary parentheses around `return` value
|
return (1); //~ ERROR unnecessary parentheses around `return` value
|
||||||
}
|
}
|
||||||
|
fn bar() -> X {
|
||||||
|
return (X { y: true }); //~ ERROR unnecessary parentheses around `return` value
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
foo();
|
foo();
|
||||||
|
bar();
|
||||||
|
|
||||||
if (true) {} //~ ERROR unnecessary parentheses around `if` condition
|
if (true) {} //~ ERROR unnecessary parentheses around `if` condition
|
||||||
while (true) {} //~ ERROR unnecessary parentheses around `while` condition
|
while (true) {} //~ ERROR unnecessary parentheses around `while` condition
|
||||||
match (true) { //~ ERROR unnecessary parentheses around `match` head expression
|
match (true) { //~ ERROR unnecessary parentheses around `match` head expression
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
let v = X { y: false };
|
||||||
|
// struct lits needs parens, so these shouldn't warn.
|
||||||
|
if (v == X { y: true }) {}
|
||||||
|
if (X { y: true } == v) {}
|
||||||
|
if (X { y: false }.y) {}
|
||||||
|
|
||||||
|
while (X { y: false }.foo()) {}
|
||||||
|
while (true | X { y: false }.y) {}
|
||||||
|
|
||||||
|
match (X { y: false }) {
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
|
let mut _a = (0); //~ ERROR unnecessary parentheses around assigned value
|
||||||
_a = (0); //~ ERROR unnecessary parentheses around assigned value
|
_a = (0); //~ ERROR unnecessary parentheses around assigned value
|
||||||
_a += (1); //~ ERROR unnecessary parentheses around assigned value
|
_a += (1); //~ ERROR unnecessary parentheses around assigned value
|
||||||
|
|
Loading…
Reference in a new issue