diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index de7e8bc861d2c8e2ef057c07b2cefaa691600777..a3dbe931daacdd9cb0beb8e3bd2a63d1f65f0a88 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1984,6 +1984,13 @@ pub fn is_safe_to_remove(&self) -> bool { } impl BorrowKind { + pub fn mutability(&self) -> Mutability { + match *self { + BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not, + BorrowKind::Mut { .. } => Mutability::Mut, + } + } + pub fn allows_two_phase_borrow(&self) -> bool { match *self { BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 82a7cf785173439daa484a8994bf19fda4984a96..7d79a13d3fde3d5737f9a85576b9e292220ab023 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -227,6 +227,9 @@ pub enum StmtKind<'tcx> { /// The lint level for this `let` statement. lint_level: LintLevel, + + /// Span of the `let = ` part. + span: Span, }, } @@ -594,6 +597,55 @@ pub fn simple_ident(&self) -> Option { _ => None, } } + + /// Call `f` on every "binding" in a pattern, e.g., on `a` in + /// `match foo() { Some(a) => (), None => () }` + pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) { + self.walk_always(|p| { + if let PatKind::Binding { name, mode, ty, .. } = p.kind { + f(name, mode, ty, p.span); + } + }); + } + + /// Walk the pattern in left-to-right order. + /// + /// If `it(pat)` returns `false`, the children are not visited. + pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) { + self.walk_(&mut it) + } + + fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) { + if !it(self) { + return; + } + + use PatKind::*; + match &self.kind { + Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {} + AscribeUserType { subpattern, .. } + | Binding { subpattern: Some(subpattern), .. } + | Deref { subpattern } => subpattern.walk_(it), + Leaf { subpatterns } | Variant { subpatterns, .. } => { + subpatterns.iter().for_each(|field| field.pattern.walk_(it)) + } + Or { pats } => pats.iter().for_each(|p| p.walk_(it)), + Array { box ref prefix, ref slice, box ref suffix } + | Slice { box ref prefix, ref slice, box ref suffix } => { + prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it)) + } + } + } + + /// Walk the pattern in left-to-right order. + /// + /// If you always want to recurse, prefer this method over `walk`. + pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) { + self.walk(|p| { + it(p); + true + }) + } } impl<'tcx> IntoDiagnosticArg for Pat<'tcx> { @@ -879,7 +931,7 @@ mod size_asserts { static_assert_size!(ExprKind<'_>, 40); static_assert_size!(Pat<'_>, 72); static_assert_size!(PatKind<'_>, 56); - static_assert_size!(Stmt<'_>, 48); - static_assert_size!(StmtKind<'_>, 40); + static_assert_size!(Stmt<'_>, 56); + static_assert_size!(StmtKind<'_>, 48); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 79a0e75aa7c788b6923047908692c748a3f8b417..5614528c4cb2524babf43a18b5d95d69bcb72432 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -175,6 +175,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm ref pattern, lint_level: _, else_block, + span: _, } => { if let Some(init) = initializer { visitor.visit_expr(&visitor.thir()[*init]); diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 2643d33cee00abde2688faf2b4f25186ff8ccf6b..609ab19289c9a494c691ad3105c472aa768ea83a 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -115,6 +115,7 @@ fn ast_block_stmts( initializer: Some(initializer), lint_level, else_block: Some(else_block), + span: _, } => { // When lowering the statement `let = else { };`, // the `` block is nested in the parent scope enclosing this statement. @@ -278,6 +279,7 @@ fn ast_block_stmts( initializer, lint_level, else_block: None, + span: _, } => { let ignores_expr_result = matches!(pattern.kind, PatKind::Wild); this.block_context.push(BlockFrame::Statement { ignores_expr_result }); diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 321353ca20bae01f30992f1137fe109c582afd29..8aacec53f94597d818cd98a55940d8fb0db117c6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -105,6 +105,10 @@ fn mirror_stmts( } } + let span = match local.init { + Some(init) => local.span.with_hi(init.span.hi()), + None => local.span, + }; let stmt = Stmt { kind: StmtKind::Let { remainder_scope, @@ -116,6 +120,7 @@ fn mirror_stmts( initializer: local.init.map(|init| self.mirror_expr(init)), else_block, lint_level: LintLevel::Explicit(local.hir_id), + span, }, opt_destruction_scope: opt_dxn_ext, }; diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 8028227aafd2acc4ac302aa06d757b1c0fc27227..ed61d6ee78b1d387c9fb5d067af001ea56e2958e 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -151,6 +151,7 @@ fn print_stmt(&mut self, stmt_id: StmtId, depth_lvl: usize) { initializer, else_block, lint_level, + span, } => { print_indented!(self, "kind: Let {", depth_lvl + 1); print_indented!( @@ -181,6 +182,7 @@ fn print_stmt(&mut self, stmt_id: StmtId, depth_lvl: usize) { } print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 2); + print_indented!(self, format!("span: {:?}", span), depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } }