diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8cab83707dcbc..c8eb6f899c10e 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -908,18 +908,26 @@ impl UnOp { /// A statement #[derive(Clone, Encodable, Decodable, Debug)] pub struct Stmt { - pub id: NodeId, pub kind: StmtKind, pub span: Span, } impl Stmt { + pub fn id(&self) -> NodeId { + match self.kind { + StmtKind::Local(ref local) => local.id, + StmtKind::Item(ref item) => item.id, + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.id, + StmtKind::Empty { id } => id, + StmtKind::MacCall(ref mac) => mac.id, + } + } pub fn tokens(&self) -> Option<&LazyTokenStream> { match self.kind { StmtKind::Local(ref local) => local.tokens.as_ref(), StmtKind::Item(ref item) => item.tokens.as_ref(), StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.tokens.as_ref(), - StmtKind::Empty => None, + StmtKind::Empty { id: _ } => None, StmtKind::MacCall(ref mac) => mac.tokens.as_ref(), } } @@ -943,8 +951,8 @@ impl Stmt { self.kind = match self.kind { StmtKind::Expr(expr) => StmtKind::Semi(expr), StmtKind::MacCall(mac) => { - StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs, tokens }| { - MacCallStmt { mac, style: MacStmtStyle::Semicolon, attrs, tokens } + StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs, tokens, id }| { + MacCallStmt { mac, style: MacStmtStyle::Semicolon, attrs, tokens, id } })) } kind => kind, @@ -973,13 +981,14 @@ pub enum StmtKind { /// Expr with a trailing semi-colon. Semi(P), /// Just a trailing semi-colon. - Empty, + Empty { id: NodeId }, /// Macro. MacCall(P), } #[derive(Clone, Encodable, Decodable, Debug)] pub struct MacCallStmt { + pub id: NodeId, pub mac: MacCall, pub style: MacStmtStyle, pub attrs: AttrVec, diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs index d586426d70ef0..c443f1a2ecca1 100644 --- a/compiler/rustc_ast/src/ast_like.rs +++ b/compiler/rustc_ast/src/ast_like.rs @@ -106,7 +106,7 @@ impl AstLike for StmtKind { StmtKind::Local(local) => local.attrs(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(), StmtKind::Item(item) => item.attrs(), - StmtKind::Empty => &[], + StmtKind::Empty { id: _ } => &[], StmtKind::MacCall(mac) => &mac.attrs, } } @@ -116,7 +116,7 @@ impl AstLike for StmtKind { StmtKind::Local(local) => local.visit_attrs(f), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), StmtKind::Item(item) => item.visit_attrs(f), - StmtKind::Empty => {} + StmtKind::Empty { id: _ } => {} StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f), } } @@ -125,7 +125,7 @@ impl AstLike for StmtKind { StmtKind::Local(local) => &mut local.tokens, StmtKind::Item(item) => &mut item.tokens, StmtKind::Expr(expr) | StmtKind::Semi(expr) => &mut expr.tokens, - StmtKind::Empty => return None, + StmtKind::Empty { id: _ } => return None, StmtKind::MacCall(mac) => &mut mac.tokens, }) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 87950b44083ef..bf330c5cd2612 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1369,12 +1369,19 @@ pub fn noop_filter_map_expr(mut e: P, vis: &mut T) -> Optio } pub fn noop_flat_map_stmt( - Stmt { kind, mut span, mut id }: Stmt, + Stmt { kind, span }: Stmt, vis: &mut T, ) -> SmallVec<[Stmt; 1]> { - vis.visit_id(&mut id); - vis.visit_span(&mut span); - noop_flat_map_stmt_kind(kind, vis).into_iter().map(|kind| Stmt { id, kind, span }).collect() + let res = noop_flat_map_stmt_kind(kind, vis) + .into_iter() + .map(|kind| { + let mut new_span = span; + vis.visit_span(&mut new_span); + Stmt { kind, span: new_span } + }) + .collect(); + tracing::info!("Made new statements: {:?}", res); + res } pub fn noop_flat_map_stmt_kind( @@ -1389,9 +1396,13 @@ pub fn noop_flat_map_stmt_kind( StmtKind::Item(item) => vis.flat_map_item(item).into_iter().map(StmtKind::Item).collect(), StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(), StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(), - StmtKind::Empty => smallvec![StmtKind::Empty], + StmtKind::Empty { mut id } => { + vis.visit_id(&mut id); + smallvec![StmtKind::Empty { id }] + } StmtKind::MacCall(mut mac) => { - let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut(); + let MacCallStmt { mac: mac_, style: _, attrs, tokens, id } = mac.deref_mut(); + vis.visit_id(id); vis.visit_mac_call(mac_); visit_thin_attrs(attrs, vis); visit_lazy_tts(tokens, vis); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1ebfcf367110f..0223f778851d3 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -691,9 +691,9 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { StmtKind::Local(ref local) => visitor.visit_local(local), StmtKind::Item(ref item) => visitor.visit_item(item), StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr), - StmtKind::Empty => {} + StmtKind::Empty { id: _ } => {} StmtKind::MacCall(ref mac) => { - let MacCallStmt { ref mac, style: _, ref attrs, tokens: _ } = **mac; + let MacCallStmt { ref mac, style: _, ref attrs, tokens: _, id: _ } = **mac; visitor.visit_mac_call(mac); for attr in attrs.iter() { visitor.visit_attribute(attr); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 581f177ad14f6..bfecfbfc2b7b1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2415,49 +2415,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt<'hir>; 1]> { - let (hir_id, kind) = match s.kind { + let kind = match s.kind { StmtKind::Local(ref l) => { let l = self.lower_local(l); - let hir_id = self.lower_node_id(s.id); - self.alias_attrs(hir_id, l.hir_id); return smallvec![hir::Stmt { - hir_id, kind: hir::StmtKind::Local(self.arena.alloc(l)), span: s.span, }]; } StmtKind::Item(ref it) => { - // Can only use the ID once. - let mut id = Some(s.id); return self .lower_item_id(it) .into_iter() - .map(|item_id| { - let hir_id = id - .take() - .map(|id| self.lower_node_id(id)) - .unwrap_or_else(|| self.next_id()); - - hir::Stmt { hir_id, kind: hir::StmtKind::Item(item_id), span: s.span } - }) + .map(|item_id| hir::Stmt { kind: hir::StmtKind::Item(item_id), span: s.span }) .collect(); } StmtKind::Expr(ref e) => { let e = self.lower_expr(e); - let hir_id = self.lower_node_id(s.id); - self.alias_attrs(hir_id, e.hir_id); - (hir_id, hir::StmtKind::Expr(e)) + hir::StmtKind::Expr(e) } StmtKind::Semi(ref e) => { let e = self.lower_expr(e); - let hir_id = self.lower_node_id(s.id); - self.alias_attrs(hir_id, e.hir_id); - (hir_id, hir::StmtKind::Semi(e)) + hir::StmtKind::Semi(e) } - StmtKind::Empty => return smallvec![], + StmtKind::Empty { id: _ } => return smallvec![], StmtKind::MacCall(..) => panic!("shouldn't exist here"), }; - smallvec![hir::Stmt { hir_id, kind, span: s.span }] + smallvec![hir::Stmt { kind, span: s.span }] } fn lower_block_check_mode(&mut self, b: &BlockCheckMode) -> hir::BlockCheckMode { @@ -2492,7 +2476,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Helper methods for building HIR. fn stmt(&mut self, span: Span, kind: hir::StmtKind<'hir>) -> hir::Stmt<'hir> { - hir::Stmt { span, kind, hir_id: self.next_id() } + hir::Stmt { span, kind } } fn stmt_expr(&mut self, span: Span, expr: hir::Expr<'hir>) -> hir::Stmt<'hir> { diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index b910431b1ddf1..ba5e445e65178 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1527,7 +1527,7 @@ impl<'a> State<'a> { self.print_expr_outer_attr_style(expr, false); self.s.word(";"); } - ast::StmtKind::Empty => { + ast::StmtKind::Empty { id: _ } => { self.space_if_not_bol(); self.s.word(";"); } diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index cc6dac52d7663..cc9c5cd6872cb 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -141,5 +141,5 @@ fn stmt_let_underscore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P) -> as attrs: ast::AttrVec::new(), tokens: None, }); - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp } + ast::Stmt { kind: ast::StmtKind::Local(local), span: sp } } diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 7dea6099f8f1b..472d7d431eaec 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -61,7 +61,6 @@ impl MultiItemModifier for BuiltinDerive { // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' // to the function items.push(Annotatable::Stmt(P(ast::Stmt { - id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(a.expect_item()), span, }))); diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b454737fb8077..ec0bea5a9a51c 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -337,13 +337,7 @@ where // Use a macro because forwarding to a simple function has type system issues macro_rules! make_stmts_default { ($me:expr) => { - $me.make_expr().map(|e| { - smallvec![ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: e.span, - kind: ast::StmtKind::Expr(e), - }] - }) + $me.make_expr().map(|e| smallvec![ast::Stmt { span: e.span, kind: ast::StmtKind::Expr(e) }]) }; } @@ -581,7 +575,6 @@ impl MacResult for DummyResult { fn make_stmts(self: Box) -> Option> { Some(smallvec![ast::Stmt { - id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.is_error)), span: self.span, }]) diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 824df2757ea90..da44d25b7e907 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -140,7 +140,7 @@ impl<'a> ExtCtxt<'a> { } pub fn stmt_expr(&self, expr: P) -> ast::Stmt { - ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) } + ast::Stmt { span: expr.span, kind: ast::StmtKind::Expr(expr) } } pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P) -> ast::Stmt { @@ -159,7 +159,7 @@ impl<'a> ExtCtxt<'a> { attrs: AttrVec::new(), tokens: None, }); - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp } + ast::Stmt { kind: ast::StmtKind::Local(local), span: sp } } // Generates `let _: Type;`, which is usually used for type assertions. @@ -173,22 +173,15 @@ impl<'a> ExtCtxt<'a> { attrs: AttrVec::new(), tokens: None, }); - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span } + ast::Stmt { kind: ast::StmtKind::Local(local), span } } pub fn stmt_item(&self, sp: Span, item: P) -> ast::Stmt { - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp } + ast::Stmt { kind: ast::StmtKind::Item(item), span: sp } } pub fn block_expr(&self, expr: P) -> P { - self.block( - expr.span, - vec![ast::Stmt { - id: ast::DUMMY_NODE_ID, - span: expr.span, - kind: ast::StmtKind::Expr(expr), - }], - ) + self.block(expr.span, vec![ast::Stmt { span: expr.span, kind: ast::StmtKind::Expr(expr) }]) } pub fn block(&self, span: Span, stmts: Vec) -> P { P(ast::Block { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 3629e668fa9f8..180dda91fcdfc 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -17,6 +17,7 @@ use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe}; use rustc_ast_pretty::pprust; use rustc_attr::is_builtin_attr; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::map_in_place::MapInPlace; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; @@ -50,6 +51,7 @@ macro_rules! ast_fragments { ) => { /// A fragment of AST that can be produced by a single macro expansion. /// Can also serve as an input and intermediate result for macro expansion operations. + #[derive(Debug)] pub enum AstFragment { OptExpr(Option>), $($Kind($AstTy),)* @@ -422,6 +424,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } }; self.cx.trace_macros_diag(); + check_ast(&mut krate); krate } @@ -528,6 +531,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let (fragment, collected_invocations) = self.collect_invocations(fragment, &derive_placeholders); + tracing::info!("Collected invocations: {:?}", fragment); // We choose to expand any derive invocations associated with this macro invocation // *before* any macro invocations collected from the output fragment derive_invocations.extend(collected_invocations); @@ -1312,7 +1316,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } if let StmtKind::MacCall(mac) = stmt.kind { - let MacCallStmt { mac, style, attrs, tokens: _ } = mac.into_inner(); + let MacCallStmt { mac, style, attrs, tokens: _, id: _ } = mac.into_inner(); self.check_attributes(&attrs, &mac); let mut placeholder = self.collect_bang(mac, stmt.span, AstFragmentKind::Stmts).make_stmts(); @@ -1627,3 +1631,22 @@ impl<'feat> ExpansionConfig<'feat> { self.features.map_or(false, |features| features.proc_macro_hygiene) } } + +fn check_ast(krate: &mut ast::Crate) { + struct AstChecker { + ids: FxHashSet, + } + impl MutVisitor for AstChecker { + fn visit_id(&mut self, id: &mut ast::NodeId) { + if *id != ast::DUMMY_NODE_ID && !self.ids.insert(*id) { + panic!("Duplicate id: {:?}", id); + } + } + fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { + tracing::info!("Visiting stmt: {:?}", stmt); + ast::mut_visit::noop_flat_map_stmt(stmt, self) + } + } + tracing::info!("Full ast: {:?}", krate); + //AstChecker { ids: Default::default() }.visit_crate(krate); +} diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs index 8e78fcbb8dbc1..f1d617929715a 100644 --- a/compiler/rustc_expand/src/placeholders.rs +++ b/compiler/rustc_expand/src/placeholders.rs @@ -104,8 +104,9 @@ pub fn placeholder( style: ast::MacStmtStyle::Braces, attrs: ast::AttrVec::new(), tokens: None, + id, }); - ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) } + ast::Stmt { span, kind: ast::StmtKind::MacCall(mac) } }]), AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm { attrs: Default::default(), @@ -297,7 +298,7 @@ impl MutVisitor for PlaceholderExpander { fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { let (style, mut stmts) = match stmt.kind { - ast::StmtKind::MacCall(mac) => (mac.style, self.remove(stmt.id).make_stmts()), + ast::StmtKind::MacCall(ref mac) => (mac.style, self.remove(stmt.id()).make_stmts()), _ => return noop_flat_map_stmt(stmt, self), }; @@ -324,7 +325,7 @@ impl MutVisitor for PlaceholderExpander { // FIXME: We will need to preserve the original semicolon token and // span as part of #15701 let empty_stmt = - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Empty, span: DUMMY_SP }; + ast::Stmt { kind: ast::StmtKind::Empty { id: ast::DUMMY_NODE_ID }, span: DUMMY_SP }; if let Some(stmt) = stmts.pop() { if stmt.has_trailing_semicolon() { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index fe1d190b4ec1a..a52af4ed42df3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1162,7 +1162,6 @@ impl UnOp { /// A statement. #[derive(Debug, HashStable_Generic)] pub struct Stmt<'hir> { - pub hir_id: HirId, pub kind: StmtKind<'hir>, pub span: Span, } @@ -1183,6 +1182,16 @@ pub enum StmtKind<'hir> { Semi(&'hir Expr<'hir>), } +impl<'hir> StmtKind<'hir> { + pub fn hir_id(&self) -> HirId { + match self { + StmtKind::Local(local) => local.hir_id, + StmtKind::Item(id) => id.hir_id(), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.hir_id, + } + } +} + /// Represents a `let` statement (i.e., `let : = ;`). #[derive(Debug, HashStable_Generic)] pub struct Local<'hir> { @@ -3233,7 +3242,6 @@ impl<'hir> Node<'hir> { Node::Field(FieldDef { hir_id, .. }) | Node::AnonConst(AnonConst { hir_id, .. }) | Node::Expr(Expr { hir_id, .. }) - | Node::Stmt(Stmt { hir_id, .. }) | Node::Ty(Ty { hir_id, .. }) | Node::Binding(Pat { hir_id, .. }) | Node::Pat(Pat { hir_id, .. }) @@ -3244,6 +3252,7 @@ impl<'hir> Node<'hir> { | Node::Param(Param { hir_id, .. }) | Node::Infer(InferArg { hir_id, .. }) | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id), + Node::Stmt(stmt) => Some(stmt.kind.hir_id()), Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id), Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id, Node::Variant(Variant { id, .. }) => Some(*id), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ae186d66004d7..d9f0db4c03366 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1102,7 +1102,6 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) { } pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) { - visitor.visit_id(statement.hir_id); match statement.kind { StmtKind::Local(ref local) => visitor.visit_local(local), StmtKind::Item(item) => visitor.visit_nested_item(item), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 8b41a0ff17693..f0022a3dfc3ef 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -822,11 +822,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { tokens: None, }); - ast::Stmt { - id: resolver.next_node_id(), - kind: ast::StmtKind::Expr(expr), - span: rustc_span::DUMMY_SP, - } + ast::Stmt { kind: ast::StmtKind::Expr(expr), span: rustc_span::DUMMY_SP } } let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.resolver); @@ -838,11 +834,8 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { tokens: None, }); - let loop_stmt = ast::Stmt { - id: self.resolver.next_node_id(), - span: rustc_span::DUMMY_SP, - kind: ast::StmtKind::Expr(loop_expr), - }; + let loop_stmt = + ast::Stmt { span: rustc_span::DUMMY_SP, kind: ast::StmtKind::Expr(loop_expr) }; if self.within_static_or_const { noop_visit_block(b, self) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 31d0d917f9093..13cb70f757e39 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1037,7 +1037,7 @@ impl EarlyLintPass for UnusedDocComment { // Disabled pending discussion in #78306 ast::StmtKind::Item(..) => return, // expressions will be reported by `check_expr`. - ast::StmtKind::Empty + ast::StmtKind::Empty { id: _ } | ast::StmtKind::Semi(_) | ast::StmtKind::Expr(_) | ast::StmtKind::MacCall(_) => return, diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 7a8b731da5c2e..d08fa07ce7ac3 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -135,9 +135,9 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> // // Note that statements get their attributes from // the AST struct that they wrap (e.g. an item) - self.with_lint_attrs(s.id, s.attrs(), |cx| { + self.with_lint_attrs(s.id(), s.attrs(), |cx| { run_early_pass!(cx, check_stmt, s); - cx.check_id(s.id); + cx.check_id(s.id()); }); // The visitor for the AST struct wrapped // by the statement (e.g. `Item`) will call diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 052efa851f7cf..b513e8cf98c37 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -180,7 +180,7 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) { // See `EarlyContextAndPass::visit_stmt` for an explanation // of why we call `walk_stmt` outside of `with_lint_attrs` - self.with_lint_attrs(s.hir_id, |cx| { + self.with_lint_attrs(s.kind.hir_id(), |cx| { lint_callback!(cx, check_stmt, s); }); hir_visit::walk_stmt(self, s); diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs index 0fe6564880f01..72a56fd56f0ed 100644 --- a/compiler/rustc_lint/src/redundant_semicolon.rs +++ b/compiler/rustc_lint/src/redundant_semicolon.rs @@ -31,8 +31,8 @@ impl EarlyLintPass for RedundantSemicolons { let mut seq = None; for stmt in block.stmts.iter() { match (&stmt.kind, &mut seq) { - (StmtKind::Empty, None) => seq = Some((stmt.span, false)), - (StmtKind::Empty, Some(seq)) => *seq = (seq.0.to(stmt.span), true), + (StmtKind::Empty { id: _ }, None) => seq = Some((stmt.span, false)), + (StmtKind::Empty { id: _ }, Some(seq)) => *seq = (seq.0.to(stmt.span), true), (_, seq) => maybe_lint_redundant_semis(cx, seq), } } diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index 5c166c74004a3..3592989d9fdf5 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -313,14 +313,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) { - self.insert(stmt.span, stmt.hir_id, Node::Stmt(stmt)); - - self.with_parent(stmt.hir_id, |this| { - intravisit::walk_stmt(this, stmt); - }); - } - fn visit_path_segment(&mut self, path_span: Span, path_segment: &'hir PathSegment<'hir>) { if let Some(hir_id) = path_segment.hir_id { self.insert(path_span, hir_id, Node::PathSegment(path_segment)); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c313146b07222..b368f44befa10 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -818,6 +818,22 @@ impl<'hir> Map<'hir> { self.tcx.hir_attrs(id.owner).get(id.local_id) } + pub fn stmt_span(&self, hir_id: HirId) -> Span { + match self.find(hir_id).unwrap() { + Node::Local(_) | Node::Item(_) | Node::Expr(_) => { + if let Some(Node::Block(block)) = self.find(self.get_parent_node(hir_id)) { + for stmt in block.stmts { + if stmt.kind.hir_id() == hir_id { + return stmt.span; + } + } + } + } + _ => {} + } + self.span(hir_id) + } + /// Gets the span of the definition of the specified HIR node. /// This is used by `tcx.get_span` pub fn span(&self, hir_id: HirId) -> Span { diff --git a/compiler/rustc_middle/src/ich/impls_hir.rs b/compiler/rustc_middle/src/ich/impls_hir.rs index 5dfd00bc6d42c..3c300422b4aab 100644 --- a/compiler/rustc_middle/src/ich/impls_hir.rs +++ b/compiler/rustc_middle/src/ich/impls_hir.rs @@ -123,6 +123,15 @@ impl<'a> ToStableHashKey> for hir::ItemLocalId { } } +impl<'a> ToStableHashKey> for (hir::ItemLocalId, bool) { + type KeyType = (hir::ItemLocalId, bool); + + #[inline] + fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> (hir::ItemLocalId, bool) { + *self + } +} + impl<'a> HashStable> for hir::Body<'_> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { params, value, generator_kind } = self; diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index f44267a404bf3..45978ae19d452 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -84,21 +84,25 @@ use std::fmt; #[derive(HashStable)] pub struct Scope { pub id: hir::ItemLocalId, + pub for_stmt: bool, pub data: ScopeData, } impl fmt::Debug for Scope { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.data { - ScopeData::Node => write!(fmt, "Node({:?})", self.id), - ScopeData::CallSite => write!(fmt, "CallSite({:?})", self.id), - ScopeData::Arguments => write!(fmt, "Arguments({:?})", self.id), - ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.id), + ScopeData::Node => write!(fmt, "Node({:?}, {:?})", self.id, self.for_stmt), + ScopeData::CallSite => write!(fmt, "CallSite({:?}. {:?})", self.id, self.for_stmt), + ScopeData::Arguments => write!(fmt, "Arguments({:?}, {:?})", self.id, self.for_stmt), + ScopeData::Destruction => { + write!(fmt, "Destruction({:?}, {:?})", self.id, self.for_stmt) + } ScopeData::Remainder(fsi) => write!( fmt, - "Remainder {{ block: {:?}, first_statement_index: {}}}", + "Remainder {{ block: {:?}, first_statement_index: {}, for_stmt: {:?}}}", self.id, fsi.as_u32(), + self.for_stmt, ), } } @@ -173,7 +177,8 @@ impl Scope { Some(hir_id) => hir_id, None => return DUMMY_SP, }; - let span = tcx.hir().span(hir_id); + let span = if self.for_stmt { tcx.hir().stmt_span(hir_id) } else { tcx.hir().span(hir_id) }; + if let ScopeData::Remainder(first_statement_index) = self.data { if let Node::Block(ref blk) = tcx.hir().get(hir_id) { // Want span for scope starting after the @@ -331,12 +336,12 @@ impl ScopeTree { if let Some(p) = parent { let prev = self.parent_map.insert(child, p); - assert!(prev.is_none()); + assert!(prev.is_none(), "Scope {:?} with parent {:?} has prev {:?}", child, p, prev); } // Record the destruction scopes for later so we can query them. if let ScopeData::Destruction = child.data { - self.destruction_scopes.insert(child.item_local_id(), child); + assert_eq!(self.destruction_scopes.insert(child.item_local_id(), child), None); } } @@ -372,7 +377,7 @@ impl ScopeTree { } /// Returns the scope when the temp created by `expr_id` will be cleaned up. - pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option { + pub fn temporary_scope(&self, expr_id: hir::ItemLocalId, for_stmt: bool) -> Option { // Check for a designated rvalue scope. if let Some(&s) = self.rvalue_scopes.get(&expr_id) { debug!("temporary_scope({:?}) = {:?} [custom]", expr_id, s); @@ -383,7 +388,7 @@ impl ScopeTree { // if there's one. Static items, for instance, won't // have an enclosing scope, hence no scope will be // returned. - let mut id = Scope { id: expr_id, data: ScopeData::Node }; + let mut id = Scope { id: expr_id, data: ScopeData::Node, for_stmt }; while let Some(&(p, _)) = self.parent_map.get(&id) { match p.data { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index cdefc9effa1e9..120200891aaa4 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -189,7 +189,7 @@ pub enum StmtKind<'tcx> { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Expr<'_>, 104); +rustc_data_structures::static_assert_size!(Expr<'_>, 112); /// A THIR expression. #[derive(Debug, HashStable)] diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 0d623806eb7e1..f023724c90d0c 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -624,10 +624,16 @@ where body.generator_kind, ); - let call_site_scope = - region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite }; - let arg_scope = - region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments }; + let call_site_scope = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::CallSite, + for_stmt: false, + }; + let arg_scope = region::Scope { + id: body.value.hir_id.local_id, + data: region::ScopeData::Arguments, + for_stmt: false, + }; let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| { diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 2d9b5c1d98aab..31a54263ff8ca 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -19,6 +19,7 @@ impl<'tcx> Cx<'tcx> { region_scope: region::Scope { id: block.hir_id.local_id, data: region::ScopeData::Node, + for_stmt: false, }, opt_destruction_scope, span: block.span, @@ -45,8 +46,12 @@ impl<'tcx> Cx<'tcx> { .iter() .enumerate() .filter_map(|(index, stmt)| { - let hir_id = stmt.hir_id; - let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id); + let hir_id = stmt.kind.hir_id(); + let dxn_scope = region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Destruction, + for_stmt: true, + }; match stmt.kind { hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { let stmt = Stmt { @@ -54,10 +59,11 @@ impl<'tcx> Cx<'tcx> { scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node, + for_stmt: true, }, expr: self.mirror_expr(expr), }, - opt_destruction_scope: opt_dxn_ext, + opt_destruction_scope: Some(dxn_scope), }; Some(self.thir.stmts.push(stmt)) } @@ -71,6 +77,7 @@ impl<'tcx> Cx<'tcx> { data: region::ScopeData::Remainder(region::FirstStatementIndex::new( index, )), + for_stmt: false, }; let mut pattern = self.pattern_from_hir(local.pat); @@ -101,12 +108,13 @@ impl<'tcx> Cx<'tcx> { init_scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node, + for_stmt: true, }, pattern, initializer: local.init.map(|init| self.mirror_expr(init)), lint_level: LintLevel::Explicit(local.hir_id), }, - opt_destruction_scope: opt_dxn_ext, + opt_destruction_scope: Some(dxn_scope), }; Some(self.thir.stmts.push(stmt)) } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index c3908ddd4fbe8..033555d1c477d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -31,9 +31,12 @@ impl<'tcx> Cx<'tcx> { } pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId { - let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id); - let expr_scope = - region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; + let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id, false); + let expr_scope = region::Scope { + id: hir_expr.hir_id.local_id, + data: region::ScopeData::Node, + for_stmt: false, + }; debug!("Expr::make_mirror(): id={}, span={:?}", hir_expr.hir_id, hir_expr.span); @@ -150,7 +153,7 @@ impl<'tcx> Cx<'tcx> { fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let expr_ty = self.typeck_results().expr_ty(expr); - let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id, false); let kind = match expr.kind { // Here comes the interesting stuff: @@ -498,8 +501,9 @@ impl<'tcx> Cx<'tcx> { expr.kind ), }; - let temp_lifetime = - self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let temp_lifetime = self + .region_scope_tree + .temporary_scope(expr.hir_id.local_id, false); let res = self.typeck_results().qpath_res(qpath, expr.hir_id); let ty; match res { @@ -579,14 +583,22 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Break(dest, ref value) => match dest.target_id { Ok(target_id) => ExprKind::Break { - label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, + label: region::Scope { + id: target_id.local_id, + data: region::ScopeData::Node, + for_stmt: false, + }, value: value.as_ref().map(|value| self.mirror_expr(value)), }, Err(err) => bug!("invalid loop id for break: {}", err), }, hir::ExprKind::Continue(dest) => match dest.target_id { Ok(loop_id) => ExprKind::Continue { - label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node }, + label: region::Scope { + id: loop_id.local_id, + data: region::ScopeData::Node, + for_stmt: false, + }, }, Err(err) => bug!("invalid loop id for continue: {}", err), }, @@ -601,7 +613,8 @@ impl<'tcx> Cx<'tcx> { }, hir::ExprKind::Loop(ref body, ..) => { let block_ty = self.typeck_results().node_type(body.hir_id); - let temp_lifetime = self.region_scope_tree.temporary_scope(body.hir_id.local_id); + let temp_lifetime = + self.region_scope_tree.temporary_scope(body.hir_id.local_id, false); let block = self.mirror_block(body); let body = self.thir.exprs.push(Expr { ty: block_ty, @@ -800,7 +813,7 @@ impl<'tcx> Cx<'tcx> { span: Span, overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, ) -> Expr<'tcx> { - let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id, false); let (def_id, substs, user_ty) = match overloaded_callee { Some((def_id, substs)) => (def_id, substs, None), None => { @@ -837,7 +850,11 @@ impl<'tcx> Cx<'tcx> { }), body: self.mirror_expr(arm.body), lint_level: LintLevel::Explicit(arm.hir_id), - scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node }, + scope: region::Scope { + id: arm.hir_id.local_id, + data: region::ScopeData::Node, + for_stmt: false, + }, span: arm.span, }; self.thir.arms.push(arm) @@ -922,7 +939,8 @@ impl<'tcx> Cx<'tcx> { // a constant reference (or constant raw pointer for `static mut`) in MIR Res::Def(DefKind::Static, id) => { let ty = self.tcx.static_ptr_ty(id); - let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let temp_lifetime = + self.region_scope_tree.temporary_scope(expr.hir_id.local_id, false); let kind = if self.tcx.is_thread_local_static(id) { ExprKind::ThreadLocalRef(id) } else { @@ -1006,7 +1024,7 @@ impl<'tcx> Cx<'tcx> { // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type - let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id, false); let fun = self.method_callee(expr, span, overloaded_callee); let fun = self.thir.exprs.push(fun); let fun_ty = self.thir[fun].ty; @@ -1026,7 +1044,8 @@ impl<'tcx> Cx<'tcx> { closure_expr: &'tcx hir::Expr<'tcx>, place: HirPlace<'tcx>, ) -> Expr<'tcx> { - let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); + let temp_lifetime = + self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id, false); let var_ty = place.base_ty; // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path @@ -1081,7 +1100,8 @@ impl<'tcx> Cx<'tcx> { let upvar_capture = captured_place.info.capture_kind; let captured_place_expr = self.convert_captured_hir_place(closure_expr, captured_place.place.clone()); - let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); + let temp_lifetime = + self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id, false); match upvar_capture { ty::UpvarCapture::ByValue(_) => captured_place_expr, diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index ed3b51dc14a78..328455d9b0977 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -263,7 +263,7 @@ pub fn nt_to_tokenstream( Nonterminal::NtItem(ref item) => prepend_attrs(&item.attrs, item.tokens.as_ref()), Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()), Nonterminal::NtStmt(ref stmt) => { - if let ast::StmtKind::Empty = stmt.kind { + if let ast::StmtKind::Empty { id: _ } = stmt.kind { let tokens = AttrAnnotatedTokenStream::new(vec![( tokenstream::AttrAnnotatedTokenTree::Token(Token::new( TokenKind::Semi, diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 9ef3f61ec346b..1463106ed5d00 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -86,7 +86,7 @@ impl<'a> Parser<'a> { } else if self.eat(&token::Semi) { // Do not attempt to parse an expression if we're done here. self.error_outer_attrs(&attrs.take_for_recovery()); - self.mk_stmt(lo, StmtKind::Empty) + self.mk_stmt(lo, StmtKind::Empty { id: DUMMY_NODE_ID }) } else if self.token != token::CloseDelim(token::Brace) { // Remainder are line-expr stmts. let e = if force_collect == ForceCollect::Yes { @@ -156,7 +156,7 @@ impl<'a> Parser<'a> { let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof { - StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None })) + StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None, id: DUMMY_NODE_ID })) } else { // Since none of the above applied, this is an expression statement macro. let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new()); @@ -507,7 +507,7 @@ impl<'a> Parser<'a> { } eat_semi = false; } - StmtKind::Empty | StmtKind::Item(_) | StmtKind::Semi(_) => eat_semi = false, + StmtKind::Empty { id: _ } | StmtKind::Item(_) | StmtKind::Semi(_) => eat_semi = false, } if eat_semi && self.eat(&token::Semi) { @@ -522,7 +522,7 @@ impl<'a> Parser<'a> { } pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { - Stmt { id: DUMMY_NODE_ID, kind, span } + Stmt { kind, span } } pub(super) fn mk_stmt_err(&self, span: Span) -> Stmt { diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 2bed8cadeb95d..624a527010d69 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -145,7 +145,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { - self.record("Stmt", Id::Node(s.hir_id), s); + self.record("Stmt", Id::Node(s.kind.hir_id()), s); hir_visit::walk_stmt(self, s) } diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs index c133f1a041719..469c6d28fbc58 100644 --- a/compiler/rustc_passes/src/region.rs +++ b/compiler/rustc_passes/src/region.rs @@ -137,6 +137,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h visitor.enter_scope(Scope { id: blk.hir_id.local_id, data: ScopeData::Remainder(FirstStatementIndex::new(i)), + for_stmt: false, }); visitor.cx.var_parent = visitor.cx.parent; } @@ -153,7 +154,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h fn resolve_arm<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, arm: &'tcx hir::Arm<'tcx>) { let prev_cx = visitor.cx; - visitor.enter_scope(Scope { id: arm.hir_id.local_id, data: ScopeData::Node }); + visitor.enter_scope(Scope { id: arm.hir_id.local_id, data: ScopeData::Node, for_stmt: false }); visitor.cx.var_parent = visitor.cx.parent; visitor.terminating_scopes.insert(arm.body.hir_id.local_id); @@ -168,7 +169,11 @@ fn resolve_arm<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, arm: &'tcx hir } fn resolve_pat<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, pat: &'tcx hir::Pat<'tcx>) { - visitor.record_child_scope(Scope { id: pat.hir_id.local_id, data: ScopeData::Node }); + visitor.record_child_scope(Scope { + id: pat.hir_id.local_id, + data: ScopeData::Node, + for_stmt: false, + }); // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.kind { @@ -185,18 +190,25 @@ fn resolve_pat<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, pat: &'tcx hir } fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx hir::Stmt<'tcx>) { - let stmt_id = stmt.hir_id.local_id; - debug!("resolve_stmt(stmt.id={:?})", stmt_id); + debug!("resolve_stmt(stmt.kind.hir_id={:?})", stmt.kind.hir_id()); // Every statement will clean up the temporaries created during // execution of that statement. Therefore each statement has an // associated destruction scope that represents the scope of the // statement plus its destructors, and thus the scope for which // regions referenced by the destructors need to survive. - visitor.terminating_scopes.insert(stmt_id); + // let prev_parent = visitor.cx.parent; - visitor.enter_node_scope_with_dtor(stmt_id); + + match &stmt.kind { + kind @ (hir::StmtKind::Local(_) | hir::StmtKind::Expr(_) | hir::StmtKind::Semi(_)) => { + let id = kind.hir_id().local_id; + visitor.enter_scope(Scope { id, data: ScopeData::Destruction, for_stmt: true }); + visitor.enter_scope(Scope { id, data: ScopeData::Node, for_stmt: true }); + } + hir::StmtKind::Item(_) => {} + } intravisit::walk_stmt(visitor, stmt); @@ -401,7 +413,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h if let hir::ExprKind::Yield(_, source) = &expr.kind { // Mark this expr's scope and all parent scopes as containing `yield`. - let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node }; + let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node, for_stmt: false }; loop { let data = YieldData { span: expr.span, @@ -693,9 +705,9 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { // account for the destruction scope representing the scope of // the destructors that run immediately after it completes. if self.terminating_scopes.contains(&id) { - self.enter_scope(Scope { id, data: ScopeData::Destruction }); + self.enter_scope(Scope { id, data: ScopeData::Destruction, for_stmt: false }); } - self.enter_scope(Scope { id, data: ScopeData::Node }); + self.enter_scope(Scope { id, data: ScopeData::Node, for_stmt: false }); } } @@ -735,8 +747,16 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { let outer_pessimistic_yield = mem::replace(&mut self.pessimistic_yield, false); self.terminating_scopes.insert(body.value.hir_id.local_id); - self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::CallSite }); - self.enter_scope(Scope { id: body.value.hir_id.local_id, data: ScopeData::Arguments }); + self.enter_scope(Scope { + id: body.value.hir_id.local_id, + data: ScopeData::CallSite, + for_stmt: false, + }); + self.enter_scope(Scope { + id: body.value.hir_id.local_id, + data: ScopeData::Arguments, + for_stmt: false, + }); // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 178d727418d74..1c2d24fa8eba0 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1349,7 +1349,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { if let ast::StmtKind::MacCall(..) = stmt.kind { - self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id); + self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id()); } else { visit::walk_stmt(self, stmt); } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6f4f1bdaea1b7..66d9c5ba96ef0 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -300,7 +300,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> { fn visit_stmt(&mut self, stmt: &'a Stmt) { match stmt.kind { - StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id), + StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id()), _ => visit::walk_stmt(self, stmt), } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index f65cc429fbd48..b7dc534869726 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -567,7 +567,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} } - self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); + self.warn_if_unreachable(stmt.kind.hir_id(), stmt.span, "statement"); // Hide the outer diverging and `has_errors` flags. let old_diverges = self.diverges.replace(Diverges::Maybe); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 0acf1d26e257d..b40a7baa98b3f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -8,7 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; -use rustc_hir::{Expr, ExprKind, ItemKind, Node, Stmt, StmtKind}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node}; use rustc_infer::infer; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::{self, Binder, Ty}; @@ -569,6 +569,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_local_statement(&self, id: hir::HirId) -> bool { let node = self.tcx.hir().get(id); - matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) + matches!(node, Node::Local(_)) } } diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index 5f26e701c0ab7..c908402e5a9dd 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -337,7 +337,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { self.expr_count += 1; - let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id, false); // If there are adjustments, then record the final type -- // this is the actual value that is being produced. diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout index 389eaf5e715b2..f63dda434fdb7 100644 --- a/src/test/ui/thir-tree.stdout +++ b/src/test/ui/thir-tree.stdout @@ -5,13 +5,13 @@ Thir { Expr { ty: (), temp_lifetime: Some( - Node(2), + Node(2, false), ), span: $DIR/thir-tree.rs:4:15: 4:17 (#0), kind: Block { body: Block { targeted_by_break: false, - region_scope: Node(1), + region_scope: Node(1, false), opt_destruction_scope: None, span: $DIR/thir-tree.rs:4:15: 4:17 (#0), stmts: [], @@ -23,11 +23,11 @@ Thir { Expr { ty: (), temp_lifetime: Some( - Node(2), + Node(2, false), ), span: $DIR/thir-tree.rs:4:15: 4:17 (#0), kind: Scope { - region_scope: Node(2), + region_scope: Node(2, false), lint_level: Explicit( HirId { owner: DefId(0:3 ~ thir_tree[348d]::main), @@ -40,11 +40,11 @@ Thir { Expr { ty: (), temp_lifetime: Some( - Node(2), + Node(2, false), ), span: $DIR/thir-tree.rs:4:15: 4:17 (#0), kind: Scope { - region_scope: Destruction(2), + region_scope: Destruction(2, false), lint_level: Inherited, value: e1, }, diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index db8f2171348f7..fa375c5c62f8b 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -134,7 +134,7 @@ impl LateLintPass<'_> for Default { if adt.is_struct(); let variant = adt.non_enum_variant(); if adt.did.is_local() || !variant.is_field_list_non_exhaustive(); - let module_did = cx.tcx.parent_module(stmt.hir_id).to_def_id(); + let module_did = cx.tcx.parent_module(stmt.kind.hir_id()).to_def_id(); if variant .fields .iter() diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs index 429c6ed7d2d77..245cf05d6e81b 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs @@ -63,7 +63,7 @@ impl EarlyLintPass for ItemsAfterStatements { .stmts .iter() .map(|stmt| &stmt.kind) - .skip_while(|s| matches!(**s, StmtKind::Item(..) | StmtKind::Empty)); + .skip_while(|s| matches!(**s, StmtKind::Item(..) | StmtKind::Empty { id: _ })); // lint on all further items for stmt in stmts { diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs index 2f7360210ba4d..dfc63edae4840 100644 --- a/src/tools/clippy/clippy_lints/src/loops/utils.rs +++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs @@ -256,14 +256,6 @@ pub(super) struct LoopNestVisitor { impl<'tcx> Visitor<'tcx> for LoopNestVisitor { type Map = Map<'tcx>; - fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { - if stmt.hir_id == self.hir_id { - self.nesting = LookFurther; - } else if self.nesting == Unknown { - walk_stmt(self, stmt); - } - } - fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { if self.nesting != Unknown { return; diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 3d039e1306560..198e820574432 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -106,7 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { len_expr: len_arg, }; - Self::search_initialization(cx, vi, stmt.hir_id); + Self::search_initialization(cx, vi, stmt.kind.hir_id()); } } } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 61fd375a9892c..bd24f06de794b 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -130,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for Author { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) { - if !has_attr(cx, stmt.hir_id) { + if !has_attr(cx, stmt.kind.hir_id()) { return; } match stmt.kind { diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs index f7ddee12dcf64..20e24fd66f87e 100644 --- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs @@ -110,7 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for DeepCodeInspector { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) { - if !has_attr(cx.sess(), cx.tcx.hir().attrs(stmt.hir_id)) { + if !has_attr(cx.sess(), cx.tcx.hir().attrs(stmt.kind.hir_id())) { return; } match stmt.kind { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 30c2260d15cac..c62e13bd5485f 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -226,7 +226,7 @@ pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { }, (Item(l), Item(r)) => eq_item(l, r, eq_item_kind), (Expr(l), Expr(r)) | (Semi(l), Semi(r)) => eq_expr(l, r), - (Empty, Empty) => true, + (Empty { id: _ }, Empty { id : _ }) => true, (MacCall(l), MacCall(r)) => { l.style == r.style && eq_mac_call(&l.mac, &r.mac) && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) }, diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 315eb10a9dbc0..2d3341177c816 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -43,7 +43,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { ast::StmtKind::Item(ref item) => item.span, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, ast::StmtKind::MacCall(ref mac_stmt) => mac_stmt.mac.span(), - ast::StmtKind::Empty => stmt.span, + ast::StmtKind::Empty { id: _ } => stmt.span, } } diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs index c9d46aef294a0..1c0756d186b15 100644 --- a/src/tools/rustfmt/src/closures.rs +++ b/src/tools/rustfmt/src/closures.rs @@ -148,7 +148,6 @@ fn rewrite_closure_with_block( let block = ast::Block { stmts: vec![ast::Stmt { - id: ast::NodeId::root(), kind: ast::StmtKind::Expr(ptr::P(body.clone())), span: body.span, }], diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index 6cfeb9977a966..7b6a5aa8e669f 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -1138,7 +1138,7 @@ fn block_has_statements(block: &ast::Block) -> bool { block .stmts .iter() - .any(|stmt| !matches!(stmt.kind, ast::StmtKind::Empty)) + .any(|stmt| !matches!(stmt.kind, ast::StmtKind::Empty { id: _ })) } /// Checks whether a block contains no statements, expressions, comments, or diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 7e3786b7cd94c..978e81c04c2d1 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -73,7 +73,7 @@ impl Spanned for ast::Stmt { mk_sp(mac_stmt.attrs[0].span.lo(), self.span.hi()) } } - ast::StmtKind::Empty => self.span, + ast::StmtKind::Empty { id: _ } => self.span, } } } diff --git a/src/tools/rustfmt/src/stmt.rs b/src/tools/rustfmt/src/stmt.rs index 0b3854425ea5f..14b13d0e135e9 100644 --- a/src/tools/rustfmt/src/stmt.rs +++ b/src/tools/rustfmt/src/stmt.rs @@ -53,7 +53,7 @@ impl<'a> Stmt<'a> { } pub(crate) fn is_empty(&self) -> bool { - matches!(self.inner.kind, ast::StmtKind::Empty) + matches!(self.inner.kind, ast::StmtKind::Empty { id: _ }) } fn is_last_expr(&self) -> bool { @@ -110,7 +110,7 @@ fn format_stmt( let shape = shape.sub_width(suffix.len())?; format_expr(ex, expr_type, context, shape).map(|s| s + suffix) } - ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None, + ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty { id: _ } => None, }; result.and_then(|res| recover_comment_removed(res, stmt.span(), context)) } diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 3f251bf7c16b3..b30b4549ad605 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -180,7 +180,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } self.format_missing(stmt.span().hi()); } - ast::StmtKind::Empty => (), + ast::StmtKind::Empty { id: _ } => (), } } @@ -955,7 +955,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let include_next_empty = if stmts.len() > 1 { matches!( (&stmts[0].as_ast_node().kind, &stmts[1].as_ast_node().kind), - (ast::StmtKind::Item(_), ast::StmtKind::Empty) + (ast::StmtKind::Item(_), ast::StmtKind::Empty { id: _ }) ) } else { false