diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index 37a4bf5fdcad7..cad301812123b 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -5,7 +5,7 @@ use rustc_ast::{ token, tokenstream::{DelimSpan, TokenStream, TokenTree}, BorrowKind, Expr, ExprKind, ItemKind, MacArgs, MacCall, MacDelimiter, Mutability, Path, - PathSegment, Stmt, UseTree, UseTreeKind, DUMMY_NODE_ID, + PathSegment, Stmt, StructRest, UseTree, UseTreeKind, DUMMY_NODE_ID, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -167,15 +167,103 @@ impl<'cx, 'a> Context<'cx, 'a> { /// See [Self::manage_initial_capture] and [Self::manage_try_capture] fn manage_cond_expr(&mut self, expr: &mut P) { match (*expr).kind { + ExprKind::AddrOf(_, _, ref mut local_expr) => { + self.manage_cond_expr(local_expr); + } + ExprKind::Array(ref mut local_exprs) => { + for local_expr in local_exprs { + self.manage_cond_expr(local_expr); + } + } ExprKind::Binary(_, ref mut lhs, ref mut rhs) => { self.manage_cond_expr(lhs); self.manage_cond_expr(rhs); } + ExprKind::Call(_, ref mut local_exprs) => { + for local_expr in local_exprs { + self.manage_cond_expr(local_expr); + } + } + ExprKind::Cast(ref mut local_expr, _) => { + self.manage_cond_expr(local_expr); + } + ExprKind::Index(ref mut prefix, ref mut suffix) => { + self.manage_cond_expr(prefix); + self.manage_cond_expr(suffix); + } + ExprKind::MethodCall(_, ref mut local_exprs, _) => { + for local_expr in local_exprs.iter_mut().skip(1) { + self.manage_cond_expr(local_expr); + } + } ExprKind::Path(_, Path { ref segments, .. }) if let &[ref path_segment] = &segments[..] => { let path_ident = path_segment.ident; self.manage_initial_capture(expr, path_ident); } - _ => {} + ExprKind::Paren(ref mut local_expr) => { + self.manage_cond_expr(local_expr); + } + ExprKind::Range(ref mut prefix, ref mut suffix, _) => { + if let Some(ref mut elem) = prefix { + self.manage_cond_expr(elem); + } + if let Some(ref mut elem) = suffix { + self.manage_cond_expr(elem); + } + } + ExprKind::Repeat(ref mut local_expr, ref mut elem) => { + self.manage_cond_expr(local_expr); + self.manage_cond_expr(&mut elem.value); + } + ExprKind::Struct(ref mut elem) => { + for field in &mut elem.fields { + self.manage_cond_expr(&mut field.expr); + } + if let StructRest::Base(ref mut local_expr) = elem.rest { + self.manage_cond_expr(local_expr); + } + } + ExprKind::Tup(ref mut local_exprs) => { + for local_expr in local_exprs { + self.manage_cond_expr(local_expr); + } + } + ExprKind::Unary(_, ref mut local_expr) => { + self.manage_cond_expr(local_expr); + } + // Expressions that are not worth or can not be captured. + // + // Full list instead of `_` to catch possible future inclusions and to + // sync with the `rfc-2011-nicer-assert-messages/all-expr-kinds.rs` test. + ExprKind::Assign(_, _, _) + | ExprKind::AssignOp(_, _, _) + | ExprKind::Async(_, _, _) + | ExprKind::Await(_) + | ExprKind::Block(_, _) + | ExprKind::Box(_) + | ExprKind::Break(_, _) + | ExprKind::Closure(_, _, _, _, _, _) + | ExprKind::ConstBlock(_) + | ExprKind::Continue(_) + | ExprKind::Err + | ExprKind::Field(_, _) + | ExprKind::ForLoop(_, _, _, _) + | ExprKind::If(_, _, _) + | ExprKind::InlineAsm(_) + | ExprKind::Let(_, _, _) + | ExprKind::Lit(_) + | ExprKind::Loop(_, _) + | ExprKind::MacCall(_) + | ExprKind::Match(_, _) + | ExprKind::Path(_, _) + | ExprKind::Ret(_) + | ExprKind::Try(_) + | ExprKind::TryBlock(_) + | ExprKind::Type(_, _) + | ExprKind::Underscore + | ExprKind::While(_, _, _) + | ExprKind::Yeet(_) + | ExprKind::Yield(_) => {} } } diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs index c0e9f29fdbce0..f538ec643902e 100644 --- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs +++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs @@ -55,14 +55,56 @@ struct Foo { bar: i32 } +impl Foo { + fn add(&self, a: i32, b: i32) -> i32 { a + b } +} + +fn add(a: i32, b: i32) -> i32 { a + b } + fn main() { // ***** Allowed ***** tests!( let mut elem = 1i32; + // addr of + [ &elem == &3 ] => "Assertion failed: &elem == &3\nWith captures:\n elem = 1\n" + + // array + [ [elem][0] == 3 ] => "Assertion failed: [elem][0] == 3\nWith captures:\n elem = 1\n" + // binary [ elem + 1 == 3 ] => "Assertion failed: elem + 1 == 3\nWith captures:\n elem = 1\n" + + // call + [ add(elem, elem) == 3 ] => "Assertion failed: add(elem, elem) == 3\nWith captures:\n elem = 1\n" + + // cast + [ elem as i32 == 3 ] => "Assertion failed: elem as i32 == 3\nWith captures:\n elem = 1\n" + + // index + [ [1i32, 1][elem as usize] == 3 ] => "Assertion failed: [1i32, 1][elem as usize] == 3\nWith captures:\n elem = 1\n" + + // method call + [ FOO.add(elem, elem) == 3 ] => "Assertion failed: FOO.add(elem, elem) == 3\nWith captures:\n elem = 1\n" + + // paren + [ (elem) == 3 ] => "Assertion failed: (elem) == 3\nWith captures:\n elem = 1\n" + + // range + [ (0..elem) == (0..3) ] => "Assertion failed: (0..elem) == (0..3)\nWith captures:\n elem = 1\n" + + // repeat + [ [elem; 1] == [3; 1] ] => "Assertion failed: [elem; 1] == [3; 1]\nWith captures:\n elem = 1\n" + + // struct + [ Foo { bar: elem } == Foo { bar: 3 } ] => "Assertion failed: Foo { bar: elem } == Foo { bar: 3 }\nWith captures:\n elem = 1\n" + + // tuple + [ (elem, 1) == (3, 3) ] => "Assertion failed: (elem, 1) == (3, 3)\nWith captures:\n elem = 1\n" + + // unary + [ -elem == -3 ] => "Assertion failed: -elem == -3\nWith captures:\n elem = 1\n" ); // ***** Disallowed *****