From 5abfb3775da61ed9059c6efa3f9bec5b86b67c7a Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Sat, 24 Feb 2024 15:22:42 -0500 Subject: [PATCH] Move visitor utils to `rustc_ast_ir` --- compiler/rustc_ast/src/visit.rs | 68 +-------------- compiler/rustc_ast_ir/src/lib.rs | 3 + compiler/rustc_ast_ir/src/visit.rs | 82 +++++++++++++++++++ .../rustc_ast_passes/src/ast_validation.rs | 3 +- .../src/deriving/default.rs | 3 +- compiler/rustc_expand/src/expand.rs | 3 +- compiler/rustc_hir/src/intravisit.rs | 3 +- .../rustc_hir_analysis/src/check/region.rs | 2 +- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_lint/src/early.rs | 4 +- compiler/rustc_middle/src/hir/map/mod.rs | 3 +- compiler/rustc_resolve/src/late.rs | 2 +- 12 files changed, 99 insertions(+), 79 deletions(-) create mode 100644 compiler/rustc_ast_ir/src/visit.rs diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index f29022386a9..9efb87e53cd 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -15,11 +15,12 @@ use crate::ast::*; -use core::ops::ControlFlow; - use rustc_span::symbol::Ident; use rustc_span::Span; +pub use rustc_ast_ir::visit::VisitorResult; +pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list}; + #[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { Trait, @@ -101,51 +102,6 @@ pub enum LifetimeCtxt { GenericArg, } -/// Similar to the `Try` trait, but also implemented for `()`. -pub trait VisitorResult { - type Residual; - fn output() -> Self; - fn from_residual(residual: Self::Residual) -> Self; - fn branch(self) -> ControlFlow; -} - -impl VisitorResult for () { - type Residual = !; - - fn output() -> Self {} - fn from_residual(_: !) -> Self {} - fn branch(self) -> ControlFlow { - ControlFlow::Continue(()) - } -} - -impl VisitorResult for ControlFlow { - type Residual = T; - - fn output() -> Self { - ControlFlow::Continue(()) - } - fn from_residual(residual: Self::Residual) -> Self { - ControlFlow::Break(residual) - } - fn branch(self) -> ControlFlow { - self - } -} - -#[macro_export] -macro_rules! try_visit { - ($e:expr) => { - match $crate::visit::VisitorResult::branch($e) { - core::ops::ControlFlow::Continue(()) => (), - #[allow(unreachable_code)] - core::ops::ControlFlow::Break(r) => { - return $crate::visit::VisitorResult::from_residual(r); - } - } - }; -} - /// Each method of the `Visitor` trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -316,24 +272,6 @@ pub trait Visitor<'ast>: Sized { } } -#[macro_export] -macro_rules! walk_list { - ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { - for elem in $list { - $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); - } - } -} - -#[macro_export] -macro_rules! visit_opt { - ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { - if let Some(x) = $opt { - $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); - } - } -} - pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result { walk_list!(visitor, visit_item, &krate.items); walk_list!(visitor, visit_attribute, &krate.attrs); diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 9fe13709213..ff7a1552047 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -1,3 +1,4 @@ +#![cfg_attr(feature = "nightly", feature(never_type))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![cfg_attr(feature = "nightly", allow(internal_features))] @@ -5,6 +6,8 @@ #[macro_use] extern crate rustc_macros; +pub mod visit; + /// The movability of a coroutine / closure literal: /// whether a coroutine contains self-references, causing it to be `!Unpin`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] diff --git a/compiler/rustc_ast_ir/src/visit.rs b/compiler/rustc_ast_ir/src/visit.rs new file mode 100644 index 00000000000..dec9f7a47d0 --- /dev/null +++ b/compiler/rustc_ast_ir/src/visit.rs @@ -0,0 +1,82 @@ +use core::ops::ControlFlow; + +/// Similar to the `Try` trait, but also implemented for `()`. +pub trait VisitorResult { + type Residual; + fn output() -> Self; + fn from_residual(residual: Self::Residual) -> Self; + fn from_branch(b: ControlFlow) -> Self; + fn branch(self) -> ControlFlow; +} + +impl VisitorResult for () { + #[cfg(feature = "nightly")] + type Residual = !; + + #[cfg(not(feature = "nightly"))] + type Residual = core::ops::Infallible; + + fn output() -> Self {} + fn from_residual(_: Self::Residual) -> Self {} + fn from_branch(_: ControlFlow) -> Self {} + fn branch(self) -> ControlFlow { + ControlFlow::Continue(()) + } +} + +impl VisitorResult for ControlFlow { + type Residual = T; + + fn output() -> Self { + ControlFlow::Continue(()) + } + fn from_residual(residual: Self::Residual) -> Self { + ControlFlow::Break(residual) + } + fn from_branch(b: Self) -> Self { + b + } + fn branch(self) -> Self { + self + } +} + +#[macro_export] +macro_rules! try_visit { + ($e:expr) => { + match $crate::visit::VisitorResult::branch($e) { + core::ops::ControlFlow::Continue(()) => (), + #[allow(unreachable_code)] + core::ops::ControlFlow::Break(r) => { + return $crate::visit::VisitorResult::from_residual(r); + } + } + }; +} + +#[macro_export] +macro_rules! visit_opt { + ($visitor: expr, $method: ident, $opt: expr $(, $($extra_args: expr),* )?) => { + if let Some(x) = $opt { + $crate::try_visit!($visitor.$method(x $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_list { + ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!($visitor.$method(elem $(, $($extra_args,)* )?)); + } + } +} + +#[macro_export] +macro_rules! walk_visitable_list { + ($visitor: expr, $list: expr $(, $($extra_args: expr),* )?) => { + for elem in $list { + $crate::try_visit!(elem.visit_with($visitor $(, $($extra_args,)* )?)); + } + } +} diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 8921883d94e..5321ba8a7cb 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -8,8 +8,7 @@ use itertools::{Either, Itertools}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 386d4a54b65..fae0e1d380c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -2,7 +2,8 @@ use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::errors; use rustc_ast as ast; -use rustc_ast::{attr, walk_list, EnumDef, VariantData}; +use rustc_ast::visit::walk_list; +use rustc_ast::{attr, EnumDef, VariantData}; use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt}; use rustc_span::symbol::Ident; use rustc_span::symbol::{kw, sym}; diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9d6daf1f47f..169973200aa 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -14,8 +14,7 @@ use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult}; -use rustc_ast::{try_visit, walk_list}; +use rustc_ast::visit::{self, try_visit, walk_list, AssocCtxt, Visitor, VisitorResult}; use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, ExprKind}; use rustc_ast::{ForeignItemKind, HasAttrs, HasNodeId}; use rustc_ast::{Inline, ItemKind, MacStmtStyle, MetaItemKind, ModKind}; diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 1c38a45d3a3..88e0238b523 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -65,8 +65,7 @@ //! example coroutine inference, and possibly also HIR borrowck. use crate::hir::*; -use rustc_ast::visit::VisitorResult; -use rustc_ast::{try_visit, visit_opt, walk_list}; +use rustc_ast::visit::{try_visit, visit_opt, walk_list, VisitorResult}; use rustc_ast::{Attribute, Label}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::{Ident, Symbol}; diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 0f5fd7e99b7..2a4dd6b0e0e 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -6,7 +6,7 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc_ast::walk_list; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index ae01bf84575..4a73ea57339 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -6,7 +6,7 @@ //! the types in HIR to identify late-bound lifetimes and assign their Debruijn indices. This file //! is also responsible for assigning their semantics to implicit lifetimes in trait objects. -use rustc_ast::walk_list; +use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 0862204d88e..d78ec8c0dd3 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -17,8 +17,8 @@ use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self as ast_visit, Visitor}; -use rustc_ast::{self as ast, walk_list, HasAttrs}; +use rustc_ast::visit::{self as ast_visit, walk_list, Visitor}; +use rustc_ast::{self as ast, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_feature::Features; use rustc_middle::ty::RegisteredTools; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index db27e2bd630..4960369a0a7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -3,8 +3,7 @@ use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::LocalCrate; use crate::ty::TyCtxt; use rustc_ast as ast; -use rustc_ast::visit::VisitorResult; -use rustc_ast::walk_list; +use rustc_ast::visit::{walk_list, VisitorResult}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index de6e121c79b..2c80fbdab36 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -13,7 +13,7 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{