diff options
| author | bors <bors@rust-lang.org> | 2025-06-10 17:51:43 +0000 | 
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-06-10 17:51:43 +0000 | 
| commit | 8ce228758651aa58c4d34e3bd65bf70a251da27e (patch) | |
| tree | 6ffa069bf3faf20d8cc79f3e9a8735ed7f08a9b5 /compiler | |
| parent | c6a955468b025dbe3d1de3e8f3e30496d1fb7f40 (diff) | |
| parent | 9f5c10ed43da38cf0a9b76f58f74bff948bf224e (diff) | |
| download | rust-8ce228758651aa58c4d34e3bd65bf70a251da27e.tar.gz rust-8ce228758651aa58c4d34e3bd65bf70a251da27e.zip | |
Auto merge of #142299 - fmease:rollup-u86s80a, r=fmease
Rollup of 16 pull requests Successful merges: - rust-lang/rust#134442 (Specify the behavior of `file!`) - rust-lang/rust#140372 (Exhaustively handle parsed attributes in CheckAttr) - rust-lang/rust#140766 (Stabilize keylocker) - rust-lang/rust#141642 (Note the version and PR of removed features when using it) - rust-lang/rust#141818 (Don't create .msi installer for gnullvm hosts) - rust-lang/rust#141909 (Add central execution context to bootstrap) - rust-lang/rust#141992 (use `#[naked]` for `__rust_probestack`) - rust-lang/rust#142101 (core::ptr: deduplicate more method docs) - rust-lang/rust#142102 (docs: Small clarification on the usage of read_to_string and read_to_end trait methods) - rust-lang/rust#142124 (Allow transmute casts in pre-runtime-MIR) - rust-lang/rust#142240 (deduplicate the rest of AST walker functions) - rust-lang/rust#142258 (platform-support.md: Mention specific Linux kernel version or later) - rust-lang/rust#142262 (Mark `core::slice::memchr` as `#[doc(hidden)]`) - rust-lang/rust#142271 (compiler: fn ptrs should hit different lints based on ABI) - rust-lang/rust#142275 (rustdoc: Refractor `clean_ty_generics`) - rust-lang/rust#142288 (const_eval: fix some outdated comments) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/mut_visit.rs | 616 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/visit.rs | 1215 | ||||
| -rw-r--r-- | compiler/rustc_attr_data_structures/src/attributes.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/attributes.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/check_consts/check.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/intern.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_expand/messages.ftl | 1 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/config.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/errors.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/accepted.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/removed.rs | 182 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/unstable.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 42 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/syntax.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/validate.rs | 48 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/check_attr.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_target/src/target_features.rs | 4 | 
17 files changed, 880 insertions, 1340 deletions
| diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 77cbdde61a4..71a47dcfcba 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -11,7 +11,7 @@ use std::ops::DerefMut; use std::panic; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; -use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span}; use smallvec::{Array, SmallVec, smallvec}; use thin_vec::ThinVec; @@ -19,7 +19,7 @@ use thin_vec::ThinVec; use crate::ast::*; use crate::ptr::P; use crate::tokenstream::*; -use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit, visit_opt, walk_list}; +use crate::visit::{AssocCtxt, BoundKind, FnCtxt, VisitorResult, try_visit, visit_opt, walk_list}; pub trait ExpectOne<A: Array> { fn expect_one(self, err: &'static str) -> A::Item; @@ -32,7 +32,22 @@ impl<A: Array> ExpectOne<A> for SmallVec<A> { } } -pub trait MutVisitor: Sized { +mod sealed { + use rustc_ast_ir::visit::VisitorResult; + + /// This is for compatibility with the regular `Visitor`. + pub trait MutVisitorResult { + type Result: VisitorResult; + } + + impl<T> MutVisitorResult for T { + type Result = (); + } +} + +use sealed::MutVisitorResult; + +pub trait MutVisitor: Sized + MutVisitorResult<Result = ()> { // Methods in this trait have one of three forms: // // fn visit_t(&mut self, t: &mut T); // common @@ -227,14 +242,6 @@ pub trait MutVisitor: Sized { walk_generic_args(self, p); } - fn visit_angle_bracketed_parameter_data(&mut self, p: &mut AngleBracketedArgs) { - walk_angle_bracketed_parameter_data(self, p); - } - - fn visit_parenthesized_parameter_data(&mut self, p: &mut ParenthesizedArgs) { - walk_parenthesized_parameter_data(self, p); - } - fn visit_local(&mut self, l: &mut Local) { walk_local(self, l); } @@ -303,10 +310,6 @@ pub trait MutVisitor: Sized { walk_flat_map_expr_field(self, f) } - fn visit_where_clause(&mut self, where_clause: &mut WhereClause) { - walk_where_clause(self, where_clause); - } - fn flat_map_where_predicate( &mut self, where_predicate: WherePredicate, @@ -385,19 +388,14 @@ generate_flat_map_visitor_fns! { visit_generic_params, GenericParam, flat_map_generic_param; visit_stmts, Stmt, flat_map_stmt; visit_exprs, P<Expr>, filter_map_expr; + visit_expr_fields, ExprField, flat_map_expr_field; visit_pat_fields, PatField, flat_map_pat_field; visit_variants, Variant, flat_map_variant; visit_assoc_items, P<AssocItem>, flat_map_assoc_item, ctxt: AssocCtxt; -} - -#[inline] -fn visit_vec<T, F>(elems: &mut Vec<T>, mut visit_elem: F) -where - F: FnMut(&mut T), -{ - for elem in elems { - visit_elem(elem); - } + visit_where_predicates, WherePredicate, flat_map_where_predicate; + visit_params, Param, flat_map_param; + visit_field_defs, FieldDef, flat_map_field_def; + visit_arms, Arm, flat_map_arm; } #[inline] @@ -410,40 +408,12 @@ where } } -#[inline] -fn visit_opt<T, F>(opt: &mut Option<T>, mut visit_elem: F) -where - F: FnMut(&mut T), -{ - if let Some(elem) = opt { - visit_elem(elem); - } -} - fn visit_attrs<T: MutVisitor>(vis: &mut T, attrs: &mut AttrVec) { for attr in attrs.iter_mut() { vis.visit_attribute(attr); } } -fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) { - match args { - AttrArgs::Empty => {} - AttrArgs::Delimited(args) => visit_delim_args(vis, args), - AttrArgs::Eq { eq_span, expr } => { - vis.visit_expr(expr); - vis.visit_span(eq_span); - } - } -} - -fn visit_delim_args<T: MutVisitor>(vis: &mut T, args: &mut DelimArgs) { - let DelimArgs { dspan, delim: _, tokens: _ } = args; - let DelimSpan { open, close } = dspan; - vis.visit_span(open); - vis.visit_span(close); -} - pub fn walk_flat_map_pat_field<T: MutVisitor>( vis: &mut T, mut fp: PatField, @@ -461,40 +431,11 @@ fn visit_nested_use_tree<V: MutVisitor>( vis.visit_use_tree(nested_tree); } -pub fn walk_arm<T: MutVisitor>(vis: &mut T, arm: &mut Arm) { - let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_pat(pat); - visit_opt(guard, |guard| vis.visit_expr(guard)); - visit_opt(body, |body| vis.visit_expr(body)); - vis.visit_span(span); -} - pub fn walk_flat_map_arm<T: MutVisitor>(vis: &mut T, mut arm: Arm) -> SmallVec<[Arm; 1]> { vis.visit_arm(&mut arm); smallvec![arm] } -fn walk_assoc_item_constraint<T: MutVisitor>( - vis: &mut T, - AssocItemConstraint { id, ident, gen_args, kind, span }: &mut AssocItemConstraint, -) { - vis.visit_id(id); - vis.visit_ident(ident); - if let Some(gen_args) = gen_args { - vis.visit_generic_args(gen_args); - } - match kind { - AssocItemConstraintKind::Equality { term } => match term { - Term::Ty(ty) => vis.visit_ty(ty), - Term::Const(c) => vis.visit_anon_const(c), - }, - AssocItemConstraintKind::Bound { bounds } => visit_bounds(vis, bounds, BoundKind::Bound), - } - vis.visit_span(span); -} - pub fn walk_flat_map_variant<T: MutVisitor>( vis: &mut T, mut variant: Variant, @@ -503,64 +444,6 @@ pub fn walk_flat_map_variant<T: MutVisitor>( smallvec![variant] } -fn walk_generic_args<T: MutVisitor>(vis: &mut T, generic_args: &mut GenericArgs) { - match generic_args { - GenericArgs::AngleBracketed(data) => vis.visit_angle_bracketed_parameter_data(data), - GenericArgs::Parenthesized(data) => vis.visit_parenthesized_parameter_data(data), - GenericArgs::ParenthesizedElided(span) => vis.visit_span(span), - } -} - -fn walk_generic_arg<T: MutVisitor>(vis: &mut T, arg: &mut GenericArg) { - match arg { - GenericArg::Lifetime(lt) => vis.visit_lifetime(lt), - GenericArg::Type(ty) => vis.visit_ty(ty), - GenericArg::Const(ct) => vis.visit_anon_const(ct), - } -} - -fn walk_angle_bracketed_parameter_data<T: MutVisitor>(vis: &mut T, data: &mut AngleBracketedArgs) { - let AngleBracketedArgs { args, span } = data; - visit_thin_vec(args, |arg| match arg { - AngleBracketedArg::Arg(arg) => vis.visit_generic_arg(arg), - AngleBracketedArg::Constraint(constraint) => vis.visit_assoc_item_constraint(constraint), - }); - vis.visit_span(span); -} - -fn walk_parenthesized_parameter_data<T: MutVisitor>(vis: &mut T, args: &mut ParenthesizedArgs) { - let ParenthesizedArgs { inputs, output, span, inputs_span } = args; - visit_thin_vec(inputs, |input| vis.visit_ty(input)); - vis.visit_fn_ret_ty(output); - vis.visit_span(span); - vis.visit_span(inputs_span); -} - -fn walk_attribute<T: MutVisitor>(vis: &mut T, attr: &mut Attribute) { - let Attribute { kind, id: _, style: _, span } = attr; - match kind { - AttrKind::Normal(normal) => { - let NormalAttr { item: AttrItem { unsafety: _, path, args, tokens: _ }, tokens: _ } = - &mut **normal; - vis.visit_path(path); - visit_attr_args(vis, args); - } - AttrKind::DocComment(_kind, _sym) => {} - } - vis.visit_span(span); -} - -fn walk_mac<T: MutVisitor>(vis: &mut T, mac: &mut MacCall) { - let MacCall { path, args } = mac; - vis.visit_path(path); - visit_delim_args(vis, args); -} - -fn walk_macro_def<T: MutVisitor>(vis: &mut T, macro_def: &mut MacroDef) { - let MacroDef { body, macro_rules: _ } = macro_def; - visit_delim_args(vis, body); -} - fn walk_meta_list_item<T: MutVisitor>(vis: &mut T, li: &mut MetaItemInner) { match li { MetaItemInner::MetaItem(mi) => vis.visit_meta_item(mi), @@ -578,138 +461,11 @@ fn walk_meta_item<T: MutVisitor>(vis: &mut T, mi: &mut MetaItem) { vis.visit_span(span); } -pub fn walk_param<T: MutVisitor>(vis: &mut T, param: &mut Param) { - let Param { attrs, id, pat, span, ty, is_placeholder: _ } = param; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_pat(pat); - vis.visit_ty(ty); - vis.visit_span(span); -} - pub fn walk_flat_map_param<T: MutVisitor>(vis: &mut T, mut param: Param) -> SmallVec<[Param; 1]> { vis.visit_param(&mut param); smallvec![param] } -fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) { - match binder { - ClosureBinder::NotPresent => {} - ClosureBinder::For { span: _, generic_params } => { - generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); - } - } -} - -fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) { - match kind { - FnKind::Fn( - _ctxt, - _vis, - Fn { - defaultness, - ident, - generics, - contract, - body, - sig: FnSig { header, decl, span }, - define_opaque, - }, - ) => { - // Visibility is visited as a part of the item. - visit_defaultness(vis, defaultness); - vis.visit_ident(ident); - vis.visit_fn_header(header); - vis.visit_generics(generics); - vis.visit_fn_decl(decl); - if let Some(contract) = contract { - vis.visit_contract(contract); - } - if let Some(body) = body { - vis.visit_block(body); - } - vis.visit_span(span); - - walk_define_opaques(vis, define_opaque); - } - FnKind::Closure(binder, coroutine_kind, decl, body) => { - vis.visit_closure_binder(binder); - coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind)); - vis.visit_fn_decl(decl); - vis.visit_expr(body); - } - } -} - -fn walk_contract<T: MutVisitor>(vis: &mut T, contract: &mut FnContract) { - let FnContract { requires, ensures } = contract; - if let Some(pred) = requires { - vis.visit_expr(pred); - } - if let Some(pred) = ensures { - vis.visit_expr(pred); - } -} - -fn walk_fn_decl<T: MutVisitor>(vis: &mut T, decl: &mut FnDecl) { - let FnDecl { inputs, output } = decl; - inputs.flat_map_in_place(|param| vis.flat_map_param(param)); - vis.visit_fn_ret_ty(output); -} - -fn walk_fn_ret_ty<T: MutVisitor>(vis: &mut T, fn_ret_ty: &mut FnRetTy) { - match fn_ret_ty { - FnRetTy::Default(span) => vis.visit_span(span), - FnRetTy::Ty(ty) => vis.visit_ty(ty), - } -} - -fn walk_param_bound<T: MutVisitor>(vis: &mut T, pb: &mut GenericBound) { - match pb { - GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref), - GenericBound::Outlives(lifetime) => walk_lifetime(vis, lifetime), - GenericBound::Use(args, span) => { - for arg in args { - vis.visit_precise_capturing_arg(arg); - } - vis.visit_span(span); - } - } -} - -fn walk_precise_capturing_arg<T: MutVisitor>(vis: &mut T, arg: &mut PreciseCapturingArg) { - match arg { - PreciseCapturingArg::Lifetime(lt) => { - vis.visit_lifetime(lt); - } - PreciseCapturingArg::Arg(path, id) => { - vis.visit_id(id); - vis.visit_path(path); - } - } -} - -pub fn walk_generic_param<T: MutVisitor>(vis: &mut T, param: &mut GenericParam) { - let GenericParam { id, ident, attrs, bounds, kind, colon_span, is_placeholder: _ } = param; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_ident(ident); - visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); - match kind { - GenericParamKind::Lifetime => {} - GenericParamKind::Type { default } => { - visit_opt(default, |default| vis.visit_ty(default)); - } - GenericParamKind::Const { ty, kw_span: _, default } => { - vis.visit_ty(ty); - visit_opt(default, |default| vis.visit_anon_const(default)); - } - } - if let Some(colon_span) = colon_span { - vis.visit_span(colon_span); - } -} - pub fn walk_flat_map_generic_param<T: MutVisitor>( vis: &mut T, mut param: GenericParam, @@ -718,13 +474,6 @@ pub fn walk_flat_map_generic_param<T: MutVisitor>( smallvec![param] } -fn walk_generics<T: MutVisitor>(vis: &mut T, generics: &mut Generics) { - let Generics { params, where_clause, span } = generics; - params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); - vis.visit_where_clause(where_clause); - vis.visit_span(span); -} - fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWhereClauses) { let TyAliasWhereClauses { before, after, split: _ } = tawcs; let TyAliasWhereClause { has_where_token: _, span: span_before } = before; @@ -733,70 +482,14 @@ fn walk_ty_alias_where_clauses<T: MutVisitor>(vis: &mut T, tawcs: &mut TyAliasWh vis.visit_span(span_after); } -fn walk_where_clause<T: MutVisitor>(vis: &mut T, wc: &mut WhereClause) { - let WhereClause { has_where_token: _, predicates, span } = wc; - predicates.flat_map_in_place(|predicate| vis.flat_map_where_predicate(predicate)); - vis.visit_span(span); -} - pub fn walk_flat_map_where_predicate<T: MutVisitor>( vis: &mut T, mut pred: WherePredicate, ) -> SmallVec<[WherePredicate; 1]> { - let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = &mut pred; - vis.visit_id(id); - visit_attrs(vis, attrs); - vis.visit_where_predicate_kind(kind); - vis.visit_span(span); + walk_where_predicate(vis, &mut pred); smallvec![pred] } -pub fn walk_where_predicate_kind<T: MutVisitor>(vis: &mut T, kind: &mut WherePredicateKind) { - match kind { - WherePredicateKind::BoundPredicate(bp) => { - let WhereBoundPredicate { bound_generic_params, bounded_ty, bounds } = bp; - bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); - vis.visit_ty(bounded_ty); - visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); - } - WherePredicateKind::RegionPredicate(rp) => { - let WhereRegionPredicate { lifetime, bounds } = rp; - vis.visit_lifetime(lifetime); - visit_vec(bounds, |bound| vis.visit_param_bound(bound, BoundKind::Bound)); - } - WherePredicateKind::EqPredicate(ep) => { - let WhereEqPredicate { lhs_ty, rhs_ty } = ep; - vis.visit_ty(lhs_ty); - vis.visit_ty(rhs_ty); - } - } -} - -fn walk_variant_data<T: MutVisitor>(vis: &mut T, vdata: &mut VariantData) { - match vdata { - VariantData::Struct { fields, recovered: _ } => { - fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); - } - VariantData::Tuple(fields, id) => { - vis.visit_id(id); - fields.flat_map_in_place(|field| vis.flat_map_field_def(field)); - } - VariantData::Unit(id) => vis.visit_id(id), - } -} - -pub fn walk_field_def<T: MutVisitor>(visitor: &mut T, fd: &mut FieldDef) { - let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _, safety, default } = fd; - visitor.visit_id(id); - visit_attrs(visitor, attrs); - visitor.visit_vis(vis); - visit_safety(visitor, safety); - visit_opt(ident, |ident| visitor.visit_ident(ident)); - visitor.visit_ty(ty); - visit_opt(default, |default| visitor.visit_anon_const(default)); - visitor.visit_span(span); -} - pub fn walk_flat_map_field_def<T: MutVisitor>( vis: &mut T, mut fd: FieldDef, @@ -846,255 +539,6 @@ pub fn walk_flat_map_assoc_item( smallvec![item] } -fn walk_inline_asm<T: MutVisitor>(vis: &mut T, asm: &mut InlineAsm) { - // FIXME: Visit spans inside all this currently ignored stuff. - let InlineAsm { - asm_macro: _, - template: _, - template_strs: _, - operands, - clobber_abis: _, - options: _, - line_spans: _, - } = asm; - for (op, span) in operands { - match op { - InlineAsmOperand::In { expr, reg: _ } - | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ } - | InlineAsmOperand::InOut { expr, reg: _, late: _ } => vis.visit_expr(expr), - InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} - InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { - vis.visit_expr(in_expr); - if let Some(out_expr) = out_expr { - vis.visit_expr(out_expr); - } - } - InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const), - InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym), - InlineAsmOperand::Label { block } => vis.visit_block(block), - } - vis.visit_span(span); - } -} - -fn walk_inline_asm_sym<T: MutVisitor>( - vis: &mut T, - InlineAsmSym { id, qself, path }: &mut InlineAsmSym, -) { - vis.visit_id(id); - vis.visit_qself(qself); - vis.visit_path(path); -} - -fn walk_format_args<T: MutVisitor>(vis: &mut T, fmt: &mut FormatArgs) { - // FIXME: visit the template exhaustively. - let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt; - for FormatArgument { kind, expr } in arguments.all_args_mut() { - match kind { - FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { - vis.visit_ident(ident) - } - FormatArgumentKind::Normal => {} - } - vis.visit_expr(expr); - } - vis.visit_span(span); -} - -pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, tokens: _ }: &mut Expr) { - vis.visit_id(id); - visit_attrs(vis, attrs); - match kind { - ExprKind::Array(exprs) => visit_exprs(vis, exprs), - ExprKind::ConstBlock(anon_const) => { - vis.visit_anon_const(anon_const); - } - ExprKind::Repeat(expr, count) => { - vis.visit_expr(expr); - vis.visit_anon_const(count); - } - ExprKind::Tup(exprs) => visit_exprs(vis, exprs), - ExprKind::Call(f, args) => { - vis.visit_expr(f); - visit_exprs(vis, args); - } - ExprKind::MethodCall(box MethodCall { - seg: PathSegment { ident, id, args: seg_args }, - receiver, - args: call_args, - span, - }) => { - vis.visit_method_receiver_expr(receiver); - vis.visit_id(id); - vis.visit_ident(ident); - visit_opt(seg_args, |args| vis.visit_generic_args(args)); - visit_exprs(vis, call_args); - vis.visit_span(span); - } - ExprKind::Binary(binop, lhs, rhs) => { - vis.visit_expr(lhs); - vis.visit_expr(rhs); - vis.visit_span(&mut binop.span); - } - ExprKind::Unary(_unop, ohs) => vis.visit_expr(ohs), - ExprKind::Cast(expr, ty) => { - vis.visit_expr(expr); - vis.visit_ty(ty); - } - ExprKind::Type(expr, ty) => { - vis.visit_expr(expr); - vis.visit_ty(ty); - } - ExprKind::AddrOf(_kind, _mut, ohs) => vis.visit_expr(ohs), - ExprKind::Let(pat, scrutinee, span, _recovered) => { - vis.visit_pat(pat); - vis.visit_expr(scrutinee); - vis.visit_span(span); - } - ExprKind::If(cond, tr, fl) => { - vis.visit_expr(cond); - vis.visit_block(tr); - visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl))); - } - ExprKind::While(cond, body, label) => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_expr(cond); - vis.visit_block(body); - } - ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_pat(pat); - vis.visit_expr(iter); - vis.visit_block(body); - } - ExprKind::Loop(body, label, span) => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_block(body); - vis.visit_span(span); - } - ExprKind::Match(expr, arms, _kind) => { - vis.visit_expr(expr); - arms.flat_map_in_place(|arm| vis.flat_map_arm(arm)); - } - ExprKind::Closure(box Closure { - binder, - capture_clause, - constness, - coroutine_kind, - movability: _, - fn_decl, - body, - fn_decl_span, - fn_arg_span, - }) => { - visit_constness(vis, constness); - vis.visit_capture_by(capture_clause); - vis.visit_fn(FnKind::Closure(binder, coroutine_kind, fn_decl, body), *span, *id); - vis.visit_span(fn_decl_span); - vis.visit_span(fn_arg_span); - } - ExprKind::Block(blk, label) => { - visit_opt(label, |label| vis.visit_label(label)); - vis.visit_block(blk); - } - ExprKind::Gen(_capture_by, body, _kind, decl_span) => { - vis.visit_block(body); - vis.visit_span(decl_span); - } - ExprKind::Await(expr, await_kw_span) => { - vis.visit_expr(expr); - vis.visit_span(await_kw_span); - } - ExprKind::Use(expr, use_kw_span) => { - vis.visit_expr(expr); - vis.visit_span(use_kw_span); - } - ExprKind::Assign(el, er, span) => { - vis.visit_expr(el); - vis.visit_expr(er); - vis.visit_span(span); - } - ExprKind::AssignOp(_op, el, er) => { - vis.visit_expr(el); - vis.visit_expr(er); - } - ExprKind::Field(el, ident) => { - vis.visit_expr(el); - vis.visit_ident(ident); - } - ExprKind::Index(el, er, brackets_span) => { - vis.visit_expr(el); - vis.visit_expr(er); - vis.visit_span(brackets_span); - } - ExprKind::Range(e1, e2, _lim) => { - visit_opt(e1, |e1| vis.visit_expr(e1)); - visit_opt(e2, |e2| vis.visit_expr(e2)); - } - ExprKind::Underscore => {} - ExprKind::Path(qself, path) => { - vis.visit_qself(qself); - vis.visit_path(path); - } - ExprKind::Break(label, expr) => { - visit_opt(label, |label| vis.visit_label(label)); - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Continue(label) => { - visit_opt(label, |label| vis.visit_label(label)); - } - ExprKind::Ret(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Yeet(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); - } - ExprKind::Become(expr) => vis.visit_expr(expr), - ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm), - ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt), - ExprKind::OffsetOf(container, fields) => { - vis.visit_ty(container); - for field in fields.iter_mut() { - vis.visit_ident(field); - } - } - ExprKind::MacCall(mac) => vis.visit_mac_call(mac), - ExprKind::Struct(se) => { - let StructExpr { qself, path, fields, rest } = se.deref_mut(); - vis.visit_qself(qself); - vis.visit_path(path); - fields.flat_map_in_place(|field| vis.flat_map_expr_field(field)); - match rest { - StructRest::Base(expr) => vis.visit_expr(expr), - StructRest::Rest(_span) => {} - StructRest::None => {} - } - } - ExprKind::Paren(expr) => { - vis.visit_expr(expr); - } - ExprKind::Yield(kind) => { - let expr = kind.expr_mut(); - if let Some(expr) = expr { - vis.visit_expr(expr); - } - } - ExprKind::Try(expr) => vis.visit_expr(expr), - ExprKind::TryBlock(body) => vis.visit_block(body), - ExprKind::Lit(_token) => {} - ExprKind::IncludedBytes(_bytes) => {} - ExprKind::UnsafeBinderCast(_kind, expr, ty) => { - vis.visit_expr(expr); - if let Some(ty) = ty { - vis.visit_ty(ty); - } - } - ExprKind::Err(_guar) => {} - ExprKind::Dummy => {} - } - vis.visit_span(span); -} - pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> { vis.visit_expr(&mut e); Some(e) @@ -1139,18 +583,6 @@ fn walk_flat_map_stmt_kind<T: MutVisitor>(vis: &mut T, kind: StmtKind) -> SmallV } } -fn walk_vis<T: MutVisitor>(vis: &mut T, visibility: &mut Visibility) { - let Visibility { kind, span, tokens: _ } = visibility; - match kind { - VisibilityKind::Public | VisibilityKind::Inherited => {} - VisibilityKind::Restricted { path, id, shorthand: _ } => { - vis.visit_id(id); - vis.visit_path(path); - } - } - vis.visit_span(span); -} - fn walk_capture_by<T: MutVisitor>(vis: &mut T, capture_by: &mut CaptureBy) { match capture_by { CaptureBy::Ref => {} diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index d2f22b04a67..c88aa5c33ea 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -15,11 +15,13 @@ pub use rustc_ast_ir::visit::VisitorResult; pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list}; +use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span}; use thin_vec::ThinVec; use crate::ast::*; use crate::ptr::P; +use crate::tokenstream::DelimSpan; #[derive(Copy, Clone, Debug, PartialEq)] pub enum AssocCtxt { @@ -237,8 +239,8 @@ pub trait Visitor<'ast>: Sized { fn visit_id(&mut self, _id: NodeId) -> Self::Result { Self::Result::output() } - fn visit_macro_def(&mut self, _mac: &'ast MacroDef) -> Self::Result { - Self::Result::output() + fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) -> Self::Result { + walk_macro_def(self, macro_def) } fn visit_path(&mut self, path: &'ast Path) -> Self::Result { walk_path(self, path) @@ -320,8 +322,8 @@ macro_rules! common_visitor_and_walkers { id: NodeId, visibility: &$($lt)? $($mut)? Visibility, ctxt: Self::Ctxt, - visitor: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)?; + vis: &mut V, + ) -> V::Result; } // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier @@ -329,12 +331,12 @@ macro_rules! common_visitor_and_walkers { #[expect(unused, rustc::pass_by_value)] #[inline] )? - fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($mut)? Span) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, span: &$($lt)? $($mut)? Span) -> V::Result { $( ${ignore($mut)} - visitor.visit_span(span); + vis.visit_span(span); )? - $(${ignore($lt)}V::Result::output())? + V::Result::output() } /// helper since `Visitor` wants `NodeId` but `MutVisitor` wants `&mut NodeId` @@ -342,34 +344,34 @@ macro_rules! common_visitor_and_walkers { #[expect(rustc::pass_by_value)] )? #[inline] - fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, id: &$($lt)? $($mut)? NodeId) -> V::Result { // deref `&NodeId` into `NodeId` only for `Visitor` - visitor.visit_id( $(${ignore($lt)} * )? id) + vis.visit_id( $(${ignore($lt)} * )? id) } // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier - fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) -> V::Result { match safety { Safety::Unsafe(span) => visit_span(vis, span), Safety::Safe(span) => visit_span(vis, span), - Safety::Default => { $(${ignore($lt)}V::Result::output())? } + Safety::Default => { V::Result::output() } } } - fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) -> V::Result { match constness { Const::Yes(span) => visit_span(vis, span), Const::No => { - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } - fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_defaultness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, defaultness: &$($lt)? $($mut)? Defaultness) -> V::Result { match defaultness { Defaultness::Default(span) => visit_span(vis, span), Defaultness::Final => { - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } @@ -377,9 +379,9 @@ macro_rules! common_visitor_and_walkers { fn visit_polarity<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, polarity: &$($lt)? $($mut)? ImplPolarity, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match polarity { - ImplPolarity::Positive => { $(<V as Visitor<$lt>>::Result::output())? } + ImplPolarity::Positive => { V::Result::output() } ImplPolarity::Negative(span) => visit_span(vis, span), } } @@ -390,7 +392,7 @@ macro_rules! common_visitor_and_walkers { fn visit_modifiers<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, m: &$($lt)? $($mut)? TraitBoundModifiers - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let TraitBoundModifiers { constness, asyncness, polarity } = m; match constness { BoundConstness::Never => {} @@ -404,26 +406,26 @@ macro_rules! common_visitor_and_walkers { BoundPolarity::Positive => {} BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => try_visit!(visit_span(vis, span)), } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } - fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) $(-> <V as Visitor<$lt>>::Result)? { + fn visit_bounds<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, bounds: &$($lt)? $($mut)? GenericBounds, ctxt: BoundKind) -> V::Result { walk_list!(visitor, visit_param_bound, bounds, ctxt); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } - pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> <V as Visitor<$lt>>::Result)? { + pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) -> V::Result { visitor.visit_ident(ident) } - pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) $(-> <V as Visitor<$lt>>::Result)? { + pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) -> V::Result { let FnHeader { safety, coroutine_kind, constness, ext: _ } = header; try_visit!(visit_constness(visitor, constness)); visit_opt!(visitor, visit_coroutine_kind, coroutine_kind); visit_safety(visitor, safety) } - pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) $(-> <V as Visitor<$lt>>::Result)? { + pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) -> V::Result { try_visit!(visit_id(visitor, id)); visitor.visit_ident(ident) } @@ -432,7 +434,7 @@ macro_rules! common_visitor_and_walkers { visitor: &mut V, item: &$($mut)? $($lt)? Item<K>, ctxt: K::Ctxt, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Item { attrs, id, kind, vis, span, tokens: _ } = item; try_visit!(visit_id(visitor, id)); walk_list!(visitor, visit_attribute, attrs); @@ -444,7 +446,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_item<$($lt,)? V: $Visitor$(<$lt>)?, K: WalkItemKind<Ctxt = ()>>( visitor: &mut V, item: &$($mut)? $($lt)? Item<K>, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { walk_item_ctxt(visitor, item, ()) } @@ -452,7 +454,7 @@ macro_rules! common_visitor_and_walkers { visitor: &mut V, item: &$($mut)? $($lt)? AssocItem, ctxt: AssocCtxt, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { walk_item_ctxt(visitor, item, ctxt) } @@ -465,7 +467,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, _ctxt: Self::Ctxt, vis: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match self { ItemKind::ExternCrate(_orig_name, ident) => vis.visit_ident(ident), ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), @@ -505,7 +507,7 @@ macro_rules! common_visitor_and_walkers { } ModKind::Unloaded => {} } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm), @@ -526,7 +528,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ItemKind::Enum(ident, generics, enum_definition) => { try_visit!(vis.visit_ident(ident)); @@ -590,7 +592,7 @@ macro_rules! common_visitor_and_walkers { try_visit!(vis.visit_ident(ident)); visit_opt!(vis, visit_ident, rename); visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(vis.visit_qself(qself)); @@ -602,7 +604,7 @@ macro_rules! common_visitor_and_walkers { } } visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } @@ -611,7 +613,7 @@ macro_rules! common_visitor_and_walkers { fn walk_const_item<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, item: &$($lt)? $($mut)? ConstItem, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let ConstItem { defaultness, ident, generics, ty, expr, define_opaque } = item; try_visit!(visit_defaultness(vis, defaultness)); try_visit!(vis.visit_ident(ident)); @@ -621,7 +623,7 @@ macro_rules! common_visitor_and_walkers { walk_define_opaques(vis, define_opaque) } - fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) $(-> <V as Visitor<$lt>>::Result)? { + fn walk_foreign_mod<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, foreign_mod: &$($lt)? $($mut)? ForeignMod) -> V::Result { let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod; try_visit!(visit_safety(vis, safety)); visit_foreign_items(vis, items) @@ -630,14 +632,14 @@ macro_rules! common_visitor_and_walkers { fn walk_define_opaques<$($lt,)? V: $Visitor$(<$lt>)?>( visitor: &mut V, define_opaque: &$($lt)? $($mut)? Option<ThinVec<(NodeId, Path)>>, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { if let Some(define_opaque) = define_opaque { for (id, path) in define_opaque { try_visit!(visit_id(visitor, id)); try_visit!(visitor.visit_path(path)); } } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } impl WalkItemKind for AssocItemKind { @@ -649,7 +651,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, ctxt: Self::Ctxt, vis: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match self { AssocItemKind::Const(item) => { walk_const_item(vis, item) @@ -674,7 +676,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } AssocItemKind::MacCall(mac) => { vis.visit_mac_call(mac) @@ -694,7 +696,7 @@ macro_rules! common_visitor_and_walkers { try_visit!(vis.visit_ident(ident)); visit_opt!(vis, visit_ident, rename); visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { try_visit!(vis.visit_qself(qself)); @@ -706,7 +708,7 @@ macro_rules! common_visitor_and_walkers { } } visit_opt!(vis, visit_block, body); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } } } @@ -721,7 +723,7 @@ macro_rules! common_visitor_and_walkers { visibility: &$($lt)? $($mut)? Visibility, _ctxt: Self::Ctxt, vis: &mut V, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { match self { ForeignItemKind::Static(box StaticItem { ident, @@ -756,7 +758,7 @@ macro_rules! common_visitor_and_walkers { $(${ignore($mut)} walk_ty_alias_where_clauses(vis, where_clauses); )? - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } ForeignItemKind::MacCall(mac) => { vis.visit_mac_call(mac) @@ -768,7 +770,7 @@ macro_rules! common_visitor_and_walkers { fn walk_coroutine_kind<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, coroutine_kind: &$($lt)? $($mut)? CoroutineKind, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let (CoroutineKind::Async { span, closure_id, return_impl_trait_id } | CoroutineKind::Gen { span, closure_id, return_impl_trait_id } | CoroutineKind::AsyncGen { span, closure_id, return_impl_trait_id }) @@ -781,7 +783,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_pat<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, pattern: &$($lt)? $($mut)? Pat - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Pat { id, kind, span, tokens: _ } = pattern; try_visit!(visit_id(vis, id)); match kind { @@ -832,7 +834,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_anon_const<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, constant: &$($lt)? $($mut)? AnonConst, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let AnonConst { id, value } = constant; try_visit!(visit_id(vis, id)); vis.visit_expr(value) @@ -841,18 +843,18 @@ macro_rules! common_visitor_and_walkers { pub fn walk_path_segment<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, segment: &$($lt)? $($mut)? PathSegment, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let PathSegment { ident, id, args } = segment; try_visit!(visit_id(vis, id)); try_visit!(vis.visit_ident(ident)); visit_opt!(vis, visit_generic_args, args); - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } pub fn walk_block<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, block: &$($lt)? $($mut)? Block - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Block { stmts, id, rules: _, span, tokens: _ } = block; try_visit!(visit_id(vis, id)); try_visit!(visit_stmts(vis, stmts)); @@ -862,7 +864,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_ty<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, ty: &$($lt)? $($mut)? Ty - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Ty { id, kind, span, tokens: _ } = ty; try_visit!(visit_id(vis, id)); match kind { @@ -920,7 +922,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_crate<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, krate: &$($lt)? $($mut)? Crate, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Crate { attrs, items, spans, id, is_placeholder: _ } = krate; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); @@ -933,7 +935,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_local<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, local: &$($lt)? $($mut)? Local, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Local { id, super_, pat, ty, kind, span, colon_sp, attrs, tokens: _ } = local; if let Some(sp) = super_ { try_visit!(visit_span(vis, sp)); @@ -961,7 +963,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_poly_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, p: &$($lt)? $($mut)? PolyTraitRef, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span } = p; try_visit!(visit_modifiers(vis, modifiers)); try_visit!(visit_generic_params(vis, bound_generic_params)); @@ -972,7 +974,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_trait_ref<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, TraitRef { path, ref_id }: &$($lt)? $($mut)? TraitRef, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { try_visit!(vis.visit_path(path)); visit_id(vis, ref_id) } @@ -980,7 +982,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_variant<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, variant: &$($lt)? $($mut)? Variant, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Variant { attrs, id, span, vis: visibility, ident, data, disr_expr, is_placeholder: _ } = variant; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); @@ -995,7 +997,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_expr_field<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, f: &$($lt)? $($mut)? ExprField, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let ExprField { attrs, id, span, ident, expr, is_shorthand: _, is_placeholder: _ } = f; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); @@ -1007,7 +1009,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_pat_field<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, fp: &$($lt)? $($mut)? PatField, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let PatField { ident, pat, is_shorthand: _, attrs, id, span, is_placeholder: _ } = fp; try_visit!(visit_id(vis, id)); walk_list!(vis, visit_attribute, attrs); @@ -1019,7 +1021,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_ty_pat<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, tp: &$($lt)? $($mut)? TyPat, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let TyPat { id, kind, span, tokens: _ } = tp; try_visit!(visit_id(vis, id)); match kind { @@ -1036,19 +1038,19 @@ macro_rules! common_visitor_and_walkers { fn walk_qself<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, qself: &$($lt)? $($mut)? Option<P<QSelf>>, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { if let Some(qself) = qself { let QSelf { ty, path_span, position: _ } = &$($mut)? **qself; try_visit!(vis.visit_ty(ty)); try_visit!(visit_span(vis, path_span)); } - $(<V as Visitor<$lt>>::Result::output())? + V::Result::output() } pub fn walk_path<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, path: &$($lt)? $($mut)? Path, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let Path { span, segments, tokens: _ } = path; walk_list!(vis, visit_path_segment, segments); visit_span(vis, span) @@ -1057,7 +1059,7 @@ macro_rules! common_visitor_and_walkers { pub fn walk_use_tree<$($lt,)? V: $Visitor$(<$lt>)?>( vis: &mut V, use_tree: &$($lt)? $($mut)? UseTree, - ) $(-> <V as Visitor<$lt>>::Result)? { + ) -> V::Result { let UseTree { prefix, kind, span } = use_tree; try_visit!(vis.visit_path(prefix)); match kind { @@ -1075,573 +1077,640 @@ macro_rules! common_visitor_and_walkers { } visit_span(vis, span) } - }; -} - -common_visitor_and_walkers!(Visitor<'a>); -macro_rules! generate_list_visit_fns { - ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => { - $( - fn $name<'a, V: Visitor<'a>>( - vis: &mut V, - values: &'a ThinVec<$Ty>, - $( - $param: $ParamTy, - )* - ) -> V::Result { - walk_list!(vis, $visit_fn, values$(,$param)*); - V::Result::output() + pub fn walk_generic_args<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + generic_args: &$($lt)? $($mut)? GenericArgs + ) -> V::Result { + match generic_args { + GenericArgs::AngleBracketed(AngleBracketedArgs { span, args }) => { + for arg in args { + match arg { + AngleBracketedArg::Arg(a) => try_visit!(vis.visit_generic_arg(a)), + AngleBracketedArg::Constraint(c) => { + try_visit!(vis.visit_assoc_item_constraint(c)) + } + } + } + visit_span(vis, span) + } + GenericArgs::Parenthesized(data) => { + let ParenthesizedArgs { span, inputs, inputs_span, output } = data; + walk_list!(vis, visit_ty, inputs); + try_visit!(vis.visit_fn_ret_ty(output)); + try_visit!(visit_span(vis, span)); + visit_span(vis, inputs_span) + } + GenericArgs::ParenthesizedElided(span) => visit_span(vis, span) } - )+ - } -} + } -generate_list_visit_fns! { - visit_items, P<Item>, visit_item; - visit_foreign_items, P<ForeignItem>, visit_foreign_item; - visit_generic_params, GenericParam, visit_generic_param; - visit_stmts, Stmt, visit_stmt; - visit_pat_fields, PatField, visit_pat_field; - visit_variants, Variant, visit_variant; - visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt; -} + pub fn walk_generic_arg<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + generic_arg: &$($lt)? $($mut)? GenericArg, + ) -> V::Result { + match generic_arg { + GenericArg::Lifetime(lt) => vis.visit_lifetime(lt, $(${ignore($lt)} LifetimeCtxt::GenericArg)? ), + GenericArg::Type(ty) => vis.visit_ty(ty), + GenericArg::Const(ct) => vis.visit_anon_const(ct), + } + } -#[expect(rustc::pass_by_value)] // needed for symmetry with mut_visit -fn visit_nested_use_tree<'a, V: Visitor<'a>>( - vis: &mut V, - nested_tree: &'a UseTree, - &nested_id: &NodeId, -) -> V::Result { - vis.visit_nested_use_tree(nested_tree, nested_id) -} + pub fn walk_assoc_item_constraint<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + constraint: &$($lt)? $($mut)? AssocItemConstraint, + ) -> V::Result { + let AssocItemConstraint { id, ident, gen_args, kind, span } = constraint; + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_ident(ident)); + visit_opt!(vis, visit_generic_args, gen_args); + match kind { + AssocItemConstraintKind::Equality { term } => match term { + Term::Ty(ty) => try_visit!(vis.visit_ty(ty)), + Term::Const(c) => try_visit!(vis.visit_anon_const(c)), + }, + AssocItemConstraintKind::Bound { bounds } => { + try_visit!(visit_bounds(vis, bounds, BoundKind::Bound)); + } + } + visit_span(vis, span) + } -pub fn walk_generic_args<'a, V>(visitor: &mut V, generic_args: &'a GenericArgs) -> V::Result -where - V: Visitor<'a>, -{ - match generic_args { - GenericArgs::AngleBracketed(AngleBracketedArgs { span: _, args }) => { - for arg in args { - match arg { - AngleBracketedArg::Arg(a) => try_visit!(visitor.visit_generic_arg(a)), - AngleBracketedArg::Constraint(c) => { - try_visit!(visitor.visit_assoc_item_constraint(c)) - } + pub fn walk_param_bound<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, bound: &$($lt)? $($mut)? GenericBound) -> V::Result { + match bound { + GenericBound::Trait(trait_ref) => vis.visit_poly_trait_ref(trait_ref), + GenericBound::Outlives(lifetime) => vis.visit_lifetime(lifetime, $(${ignore($lt)} LifetimeCtxt::Bound)?), + GenericBound::Use(args, span) => { + walk_list!(vis, visit_precise_capturing_arg, args); + visit_span(vis, span) } } } - GenericArgs::Parenthesized(data) => { - let ParenthesizedArgs { span: _, inputs, inputs_span: _, output } = data; - walk_list!(visitor, visit_ty, inputs); - try_visit!(visitor.visit_fn_ret_ty(output)); + + pub fn walk_precise_capturing_arg<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + arg: &$($lt)? $($mut)? PreciseCapturingArg, + ) -> V::Result { + match arg { + PreciseCapturingArg::Lifetime(lt) => vis.visit_lifetime(lt, $(${ignore($lt)} LifetimeCtxt::GenericArg)?), + PreciseCapturingArg::Arg(path, id) => { + try_visit!(visit_id(vis, id)); + vis.visit_path(path) + } + } } - GenericArgs::ParenthesizedElided(_span) => {} - } - V::Result::output() -} -pub fn walk_generic_arg<'a, V>(visitor: &mut V, generic_arg: &'a GenericArg) -> V::Result -where - V: Visitor<'a>, -{ - match generic_arg { - GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg), - GenericArg::Type(ty) => visitor.visit_ty(ty), - GenericArg::Const(ct) => visitor.visit_anon_const(ct), - } -} + pub fn walk_generic_param<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + param: &$($lt)? $($mut)? GenericParam, + ) -> V::Result { + let GenericParam { id, ident, attrs, bounds, is_placeholder: _, kind, colon_span } = + param; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_ident(ident)); + walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound); + match kind { + GenericParamKind::Lifetime => (), + GenericParamKind::Type { default } => visit_opt!(vis, visit_ty, default), + GenericParamKind::Const { ty, default, kw_span: _ } => { + try_visit!(vis.visit_ty(ty)); + visit_opt!(vis, visit_anon_const, default); + } + } + if let Some(sp) = colon_span { + try_visit!(visit_span(vis, sp)) + } + V::Result::output() + } -pub fn walk_assoc_item_constraint<'a, V: Visitor<'a>>( - visitor: &mut V, - constraint: &'a AssocItemConstraint, -) -> V::Result { - let AssocItemConstraint { id: _, ident, gen_args, kind, span: _ } = constraint; - try_visit!(visitor.visit_ident(ident)); - visit_opt!(visitor, visit_generic_args, gen_args); - match kind { - AssocItemConstraintKind::Equality { term } => match term { - Term::Ty(ty) => try_visit!(visitor.visit_ty(ty)), - Term::Const(c) => try_visit!(visitor.visit_anon_const(c)), - }, - AssocItemConstraintKind::Bound { bounds } => { - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); + pub fn walk_generics<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, generics: &$($lt)? $($mut)? Generics) -> V::Result { + let Generics { params, where_clause, span } = generics; + let WhereClause { has_where_token: _, predicates, span: where_clause_span } = where_clause; + try_visit!(visit_generic_params(vis, params)); + try_visit!(visit_where_predicates(vis, predicates)); + try_visit!(visit_span(vis, span)); + visit_span(vis, where_clause_span) } - } - V::Result::output() -} -pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result { - match bound { - GenericBound::Trait(trait_ref) => visitor.visit_poly_trait_ref(trait_ref), - GenericBound::Outlives(lifetime) => visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound), - GenericBound::Use(args, _span) => { - walk_list!(visitor, visit_precise_capturing_arg, args); + pub fn walk_contract<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, c: &$($lt)? $($mut)? FnContract) -> V::Result { + let FnContract { requires, ensures } = c; + visit_opt!(vis, visit_expr, requires); + visit_opt!(vis, visit_expr, ensures); V::Result::output() } - } -} -pub fn walk_precise_capturing_arg<'a, V: Visitor<'a>>( - visitor: &mut V, - arg: &'a PreciseCapturingArg, -) -> V::Result { - match arg { - PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt, LifetimeCtxt::GenericArg), - PreciseCapturingArg::Arg(path, id) => { - try_visit!(visitor.visit_id(*id)); - visitor.visit_path(path) + pub fn walk_where_predicate<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + predicate: &$($lt)? $($mut)? WherePredicate, + ) -> V::Result { + let WherePredicate { attrs, kind, id, span, is_placeholder: _ } = predicate; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(visit_span(vis, span)); + vis.visit_where_predicate_kind(kind) } - } -} -pub fn walk_generic_param<'a, V: Visitor<'a>>( - visitor: &mut V, - param: &'a GenericParam, -) -> V::Result { - let GenericParam { id: _, ident, attrs, bounds, is_placeholder: _, kind, colon_span: _ } = - param; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_ident(ident)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); - match kind { - GenericParamKind::Lifetime => (), - GenericParamKind::Type { default } => visit_opt!(visitor, visit_ty, default), - GenericParamKind::Const { ty, default, kw_span: _ } => { - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_anon_const, default); + pub fn walk_closure_binder<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + binder: &$($lt)? $($mut)? ClosureBinder, + ) -> V::Result { + match binder { + ClosureBinder::NotPresent => {} + ClosureBinder::For { generic_params, span } => { + try_visit!(visit_generic_params(vis, generic_params)); + try_visit!(visit_span(vis, span)); + } + } + V::Result::output() } - } - V::Result::output() -} - -pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) -> V::Result { - let Generics { params, where_clause, span: _ } = generics; - let WhereClause { has_where_token: _, predicates, span: _ } = where_clause; - walk_list!(visitor, visit_generic_param, params); - walk_list!(visitor, visit_where_predicate, predicates); - V::Result::output() -} -pub fn walk_closure_binder<'a, V: Visitor<'a>>( - visitor: &mut V, - binder: &'a ClosureBinder, -) -> V::Result { - match binder { - ClosureBinder::NotPresent => {} - ClosureBinder::For { generic_params, span: _ } => { - walk_list!(visitor, visit_generic_param, generic_params) + pub fn walk_where_predicate_kind<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + kind: &$($lt)? $($mut)? WherePredicateKind, + ) -> V::Result { + match kind { + WherePredicateKind::BoundPredicate(WhereBoundPredicate { + bounded_ty, + bounds, + bound_generic_params, + }) => { + visit_generic_params(vis, bound_generic_params); + try_visit!(vis.visit_ty(bounded_ty)); + walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound); + } + WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => { + try_visit!(vis.visit_lifetime(lifetime, $(${ignore($lt)} LifetimeCtxt::Bound )?)); + walk_list!(vis, visit_param_bound, bounds, BoundKind::Bound); + } + WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => { + try_visit!(vis.visit_ty(lhs_ty)); + try_visit!(vis.visit_ty(rhs_ty)); + } + } + V::Result::output() } - } - V::Result::output() -} -pub fn walk_contract<'a, V: Visitor<'a>>(visitor: &mut V, c: &'a FnContract) -> V::Result { - let FnContract { requires, ensures } = c; - if let Some(pred) = requires { - visitor.visit_expr(pred); - } - if let Some(pred) = ensures { - visitor.visit_expr(pred); - } - V::Result::output() -} + pub fn walk_fn_decl<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + FnDecl { inputs, output }: &$($lt)? $($mut)? FnDecl, + ) -> V::Result { + try_visit!(visit_params(vis, inputs)); + vis.visit_fn_ret_ty(output) + } -pub fn walk_where_predicate<'a, V: Visitor<'a>>( - visitor: &mut V, - predicate: &'a WherePredicate, -) -> V::Result { - let WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate; - walk_list!(visitor, visit_attribute, attrs); - visitor.visit_where_predicate_kind(kind) -} + pub fn walk_fn_ret_ty<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, ret_ty: &$($lt)? $($mut)? FnRetTy) -> V::Result { + match ret_ty { + FnRetTy::Default(span) => visit_span(vis, span), + FnRetTy::Ty(output_ty) => vis.visit_ty(output_ty), + } + } -pub fn walk_where_predicate_kind<'a, V: Visitor<'a>>( - visitor: &mut V, - kind: &'a WherePredicateKind, -) -> V::Result { - match kind { - WherePredicateKind::BoundPredicate(WhereBoundPredicate { - bounded_ty, - bounds, - bound_generic_params, - }) => { - walk_list!(visitor, visit_generic_param, bound_generic_params); - try_visit!(visitor.visit_ty(bounded_ty)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); + pub fn walk_fn<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, kind: FnKind<$($lt)? $(${ignore($mut)} '_)?>) -> V::Result { + match kind { + FnKind::Fn( + _ctxt, + _vis, + Fn { + defaultness, + ident, + sig: FnSig { header, decl, span }, + generics, + contract, + body, + define_opaque, + }, + ) => { + // Visibility is visited as a part of the item. + try_visit!(visit_defaultness(vis, defaultness)); + try_visit!(vis.visit_ident(ident)); + try_visit!(vis.visit_fn_header(header)); + try_visit!(vis.visit_generics(generics)); + try_visit!(vis.visit_fn_decl(decl)); + visit_opt!(vis, visit_contract, contract); + visit_opt!(vis, visit_block, body); + try_visit!(visit_span(vis, span)); + walk_define_opaques(vis, define_opaque) + } + FnKind::Closure(binder, coroutine_kind, decl, body) => { + try_visit!(vis.visit_closure_binder(binder)); + visit_opt!(vis, visit_coroutine_kind, coroutine_kind); + try_visit!(vis.visit_fn_decl(decl)); + vis.visit_expr(body) + } + } } - WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => { - try_visit!(visitor.visit_lifetime(lifetime, LifetimeCtxt::Bound)); - walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound); + + pub fn walk_variant_data<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, data: &$($lt)? $($mut)? VariantData) -> V::Result { + match data { + VariantData::Struct { fields, recovered: _ } => { + visit_field_defs(vis, fields) + } + VariantData::Tuple(fields, id) => { + try_visit!(visit_id(vis, id)); + visit_field_defs(vis, fields) + } + VariantData::Unit(id) => visit_id(vis, id), + } } - WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => { - try_visit!(visitor.visit_ty(lhs_ty)); - try_visit!(visitor.visit_ty(rhs_ty)); + + pub fn walk_field_def<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, field: &$($lt)? $($mut)? FieldDef) -> V::Result { + let FieldDef { attrs, id, span, vis: visibility, ident, ty, is_placeholder: _, safety: _, default } = + field; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_vis(visibility)); + visit_opt!(vis, visit_ident, ident); + try_visit!(vis.visit_ty(ty)); + visit_opt!(vis, visit_anon_const, default); + visit_span(vis, span) } - } - V::Result::output() -} -pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) -> V::Result { - match ret_ty { - FnRetTy::Default(_span) => {} - FnRetTy::Ty(output_ty) => try_visit!(visitor.visit_ty(output_ty)), - } - V::Result::output() -} + fn visit_delim_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, args: &$($lt)? $($mut)? DelimArgs) -> V::Result { + let DelimArgs { dspan, delim: _, tokens: _ } = args; + let DelimSpan { open, close } = dspan; + try_visit!(visit_span(vis, open)); + visit_span(vis, close) + } -pub fn walk_fn_decl<'a, V: Visitor<'a>>( - visitor: &mut V, - FnDecl { inputs, output }: &'a FnDecl, -) -> V::Result { - walk_list!(visitor, visit_param, inputs); - visitor.visit_fn_ret_ty(output) -} + pub fn walk_mac<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, mac: &$($lt)? $($mut)? MacCall) -> V::Result { + let MacCall { path, args } = mac; + try_visit!(vis.visit_path(path)); + visit_delim_args(vis, args) + } + + fn walk_macro_def<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, macro_def: &$($lt)? $($mut)? MacroDef) -> V::Result { + let MacroDef { body, macro_rules: _ } = macro_def; + visit_delim_args(vis, body) + } + + pub fn walk_inline_asm<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, asm: &$($lt)? $($mut)? InlineAsm) -> V::Result { + // FIXME: Visit spans inside all this currently ignored stuff. + let InlineAsm { + asm_macro: _, + template: _, + template_strs: _, + operands, + clobber_abis: _, + options: _, + line_spans: _, + } = asm; + for (op, span) in operands { + match op { + InlineAsmOperand::In { expr, reg: _ } + | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ } + | InlineAsmOperand::InOut { expr, reg: _, late: _ } => { + try_visit!(vis.visit_expr(expr)) + } + InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} + InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { + try_visit!(vis.visit_expr(in_expr)); + visit_opt!(vis, visit_expr, out_expr); + } + InlineAsmOperand::Const { anon_const } => { + try_visit!(vis.visit_anon_const(anon_const)) + } + InlineAsmOperand::Sym { sym } => try_visit!(vis.visit_inline_asm_sym(sym)), + InlineAsmOperand::Label { block } => try_visit!(vis.visit_block(block)), + } + try_visit!(visit_span(vis, span)); + } + V::Result::output() + } -pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Result { - match kind { - FnKind::Fn( - _ctxt, - _vis, - Fn { - defaultness: _, - ident, - sig: FnSig { header, decl, span: _ }, - generics, - contract, - body, - define_opaque, - }, - ) => { - // Visibility is visited as a part of the item. - try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_fn_header(header)); - try_visit!(visitor.visit_generics(generics)); - try_visit!(visitor.visit_fn_decl(decl)); - visit_opt!(visitor, visit_contract, contract); - visit_opt!(visitor, visit_block, body); - try_visit!(walk_define_opaques(visitor, define_opaque)); - } - FnKind::Closure(binder, coroutine_kind, decl, body) => { - try_visit!(visitor.visit_closure_binder(binder)); - visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref()); - try_visit!(visitor.visit_fn_decl(decl)); - try_visit!(visitor.visit_expr(body)); + pub fn walk_inline_asm_sym<$($lt,)? V: $Visitor$(<$lt>)?>( + vis: &mut V, + InlineAsmSym { id, qself, path }: &$($lt)? $($mut)? InlineAsmSym, + ) -> V::Result { + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_qself(qself)); + vis.visit_path(path) + } + + // FIXME: visit the template exhaustively. + pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result { + let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt; + let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ; + for FormatArgument { kind, expr } in args { + match kind { + FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { + try_visit!(vis.visit_ident(ident)) + } + FormatArgumentKind::Normal => {} + } + try_visit!(vis.visit_expr(expr)); + } + visit_span(vis, span) } - } - V::Result::output() -} -pub fn walk_variant_data<'a, V: Visitor<'a>>(visitor: &mut V, data: &'a VariantData) -> V::Result { - visit_opt!(visitor, visit_id, data.ctor_node_id()); - walk_list!(visitor, visit_field_def, data.fields()); - V::Result::output() -} + pub fn walk_expr<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, expression: &$($lt)? $($mut)? Expr) -> V::Result { + let Expr { id, kind, span, attrs, tokens: _ } = expression; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + match kind { + ExprKind::Array(exprs) => { + try_visit!(visit_exprs(vis, exprs)); + } + ExprKind::ConstBlock(anon_const) => try_visit!(vis.visit_anon_const(anon_const)), + ExprKind::Repeat(element, count) => { + try_visit!(vis.visit_expr(element)); + try_visit!(vis.visit_anon_const(count)); + } + ExprKind::Struct(se) => { + let StructExpr { qself, path, fields, rest } = &$($mut)?**se; + try_visit!(vis.visit_qself(qself)); + try_visit!(vis.visit_path(path)); + visit_expr_fields(vis, fields); + match rest { + StructRest::Base(expr) => try_visit!(vis.visit_expr(expr)), + StructRest::Rest(_span) => {} + StructRest::None => {} + } + } + ExprKind::Tup(exprs) => { + try_visit!(visit_exprs(vis, exprs)); + } + ExprKind::Call(callee_expression, arguments) => { + try_visit!(vis.visit_expr(callee_expression)); + try_visit!(visit_exprs(vis, arguments)); + } + ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => { + try_visit!(vis.visit_method_receiver_expr(receiver)); + try_visit!(vis.visit_path_segment(seg)); + try_visit!(visit_exprs(vis, args)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Binary(Spanned { span, node: _ }, left_expression, right_expression) => { + try_visit!(vis.visit_expr(left_expression)); + try_visit!(vis.visit_expr(right_expression)); + try_visit!(visit_span(vis, span)) + } + ExprKind::AddrOf(_kind, _mutbl, subexpression) => { + try_visit!(vis.visit_expr(subexpression)); + } + ExprKind::Unary(_op, subexpression) => { + try_visit!(vis.visit_expr(subexpression)); + } + ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => { + try_visit!(vis.visit_expr(subexpression)); + try_visit!(vis.visit_ty(typ)); + } + ExprKind::Let(pat, expr, span, _recovered) => { + try_visit!(vis.visit_pat(pat)); + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, span)) + } + ExprKind::If(head_expression, if_block, optional_else) => { + try_visit!(vis.visit_expr(head_expression)); + try_visit!(vis.visit_block(if_block)); + visit_opt!(vis, visit_expr, optional_else); + } + ExprKind::While(subexpression, block, opt_label) => { + visit_opt!(vis, visit_label, opt_label); + try_visit!(vis.visit_expr(subexpression)); + try_visit!(vis.visit_block(block)); + } + ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { + visit_opt!(vis, visit_label, label); + try_visit!(vis.visit_pat(pat)); + try_visit!(vis.visit_expr(iter)); + try_visit!(vis.visit_block(body)); + } + ExprKind::Loop(block, opt_label, span) => { + visit_opt!(vis, visit_label, opt_label); + try_visit!(vis.visit_block(block)); + try_visit!(visit_span(vis, span)) + } + ExprKind::Match(subexpression, arms, _kind) => { + try_visit!(vis.visit_expr(subexpression)); + try_visit!(visit_arms(vis, arms)); + } + ExprKind::Closure(box Closure { + binder, + capture_clause, + coroutine_kind, + constness, + movability: _, + fn_decl, + body, + fn_decl_span, + fn_arg_span, + }) => { + try_visit!(visit_constness(vis, constness)); + try_visit!(vis.visit_capture_by(capture_clause)); + try_visit!(vis.visit_fn( + FnKind::Closure(binder, coroutine_kind, fn_decl, body), + *span, + *id + )); + try_visit!(visit_span(vis, fn_decl_span)); + try_visit!(visit_span(vis, fn_arg_span)); + } + ExprKind::Block(block, opt_label) => { + visit_opt!(vis, visit_label, opt_label); + try_visit!(vis.visit_block(block)); + } + ExprKind::Gen(_capt, body, _kind, decl_span) => { + try_visit!(vis.visit_block(body)); + try_visit!(visit_span(vis, decl_span)); + } + ExprKind::Await(expr, span) => { + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Use(expr, span) => { + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Assign(lhs, rhs, span) => { + try_visit!(vis.visit_expr(lhs)); + try_visit!(vis.visit_expr(rhs)); + try_visit!(visit_span(vis, span)); + } + ExprKind::AssignOp(_op, left_expression, right_expression) => { + try_visit!(vis.visit_expr(left_expression)); + try_visit!(vis.visit_expr(right_expression)); + } + ExprKind::Field(subexpression, ident) => { + try_visit!(vis.visit_expr(subexpression)); + try_visit!(vis.visit_ident(ident)); + } + ExprKind::Index(main_expression, index_expression, span) => { + try_visit!(vis.visit_expr(main_expression)); + try_visit!(vis.visit_expr(index_expression)); + try_visit!(visit_span(vis, span)); + } + ExprKind::Range(start, end, _limit) => { + visit_opt!(vis, visit_expr, start); + visit_opt!(vis, visit_expr, end); + } + ExprKind::Underscore => {} + ExprKind::Path(maybe_qself, path) => { + try_visit!(vis.visit_qself(maybe_qself)); + try_visit!(vis.visit_path(path)); + } + ExprKind::Break(opt_label, opt_expr) => { + visit_opt!(vis, visit_label, opt_label); + visit_opt!(vis, visit_expr, opt_expr); + } + ExprKind::Continue(opt_label) => { + visit_opt!(vis, visit_label, opt_label); + } + ExprKind::Ret(optional_expression) => { + visit_opt!(vis, visit_expr, optional_expression); + } + ExprKind::Yeet(optional_expression) => { + visit_opt!(vis, visit_expr, optional_expression); + } + ExprKind::Become(expr) => try_visit!(vis.visit_expr(expr)), + ExprKind::MacCall(mac) => try_visit!(vis.visit_mac_call(mac)), + ExprKind::Paren(subexpression) => try_visit!(vis.visit_expr(subexpression)), + ExprKind::InlineAsm(asm) => try_visit!(vis.visit_inline_asm(asm)), + ExprKind::FormatArgs(f) => try_visit!(vis.visit_format_args(f)), + ExprKind::OffsetOf(container, fields) => { + try_visit!(vis.visit_ty(container)); + walk_list!(vis, visit_ident, fields); + } + ExprKind::Yield(kind) => { + match kind { + YieldKind::Postfix(expr) => { + try_visit!(vis.visit_expr(expr)); + } + YieldKind::Prefix(expr) => { + visit_opt!(vis, visit_expr, expr); + } + } + } + ExprKind::Try(subexpression) => try_visit!(vis.visit_expr(subexpression)), + ExprKind::TryBlock(body) => try_visit!(vis.visit_block(body)), + ExprKind::Lit(_token) => {} + ExprKind::IncludedBytes(_bytes) => {} + ExprKind::UnsafeBinderCast(_kind, expr, ty) => { + try_visit!(vis.visit_expr(expr)); + visit_opt!(vis, visit_ty, ty); + } + ExprKind::Err(_guar) => {} + ExprKind::Dummy => {} + } -pub fn walk_field_def<'a, V: Visitor<'a>>(visitor: &mut V, field: &'a FieldDef) -> V::Result { - let FieldDef { attrs, id: _, span: _, vis, ident, ty, is_placeholder: _, safety: _, default } = - field; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_vis(vis)); - visit_opt!(visitor, visit_ident, ident); - try_visit!(visitor.visit_ty(ty)); - visit_opt!(visitor, visit_anon_const, &*default); - V::Result::output() -} + visit_span(vis, span) + } -pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { - let Stmt { id: _, kind, span: _ } = statement; - match kind { - StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), - StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), - StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), - StmtKind::Empty => {} - StmtKind::MacCall(mac) => { - let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_mac_call(mac)); + pub fn walk_param<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, param: &$($lt)? $($mut)? Param) -> V::Result { + let Param { attrs, ty, pat, id, span, is_placeholder: _ } = param; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_pat(pat)); + try_visit!(vis.visit_ty(ty)); + visit_span(vis, span) } - } - V::Result::output() -} -pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) -> V::Result { - let MacCall { path, args: _ } = mac; - visitor.visit_path(path) -} + pub fn walk_arm<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, arm: &$($lt)? $($mut)? Arm) -> V::Result { + let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = arm; + try_visit!(visit_id(vis, id)); + walk_list!(vis, visit_attribute, attrs); + try_visit!(vis.visit_pat(pat)); + visit_opt!(vis, visit_expr, guard); + visit_opt!(vis, visit_expr, body); + visit_span(vis, span) + } -pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) -> V::Result { - let InlineAsm { - asm_macro: _, - template: _, - template_strs: _, - operands, - clobber_abis: _, - options: _, - line_spans: _, - } = asm; - for (op, _span) in operands { - match op { - InlineAsmOperand::In { expr, reg: _ } - | InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ } - | InlineAsmOperand::InOut { expr, reg: _, late: _ } => { - try_visit!(visitor.visit_expr(expr)) - } - InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {} - InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => { - try_visit!(visitor.visit_expr(in_expr)); - visit_opt!(visitor, visit_expr, out_expr); - } - InlineAsmOperand::Const { anon_const } => { - try_visit!(visitor.visit_anon_const(anon_const)) + pub fn walk_vis<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, visibility: &$($lt)? $($mut)? Visibility) -> V::Result { + let Visibility { kind, span, tokens: _ } = visibility; + match kind { + VisibilityKind::Restricted { path, id, shorthand: _ } => { + try_visit!(visit_id(vis, id)); + try_visit!(vis.visit_path(path)); + } + VisibilityKind::Public | VisibilityKind::Inherited => {} } - InlineAsmOperand::Sym { sym } => try_visit!(visitor.visit_inline_asm_sym(sym)), - InlineAsmOperand::Label { block } => try_visit!(visitor.visit_block(block)), + visit_span(vis, span) } - } - V::Result::output() -} -pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>( - visitor: &mut V, - InlineAsmSym { id, qself, path }: &'a InlineAsmSym, -) -> V::Result { - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_id(*id)); - visitor.visit_path(path) -} - -pub fn walk_format_args<'a, V: Visitor<'a>>(visitor: &mut V, fmt: &'a FormatArgs) -> V::Result { - let FormatArgs { span: _, template: _, arguments, uncooked_fmt_str: _ } = fmt; - for FormatArgument { kind, expr } in arguments.all_args() { - match kind { - FormatArgumentKind::Named(ident) | FormatArgumentKind::Captured(ident) => { - try_visit!(visitor.visit_ident(ident)) + pub fn walk_attribute<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, attr: &$($lt)? $($mut)? Attribute) -> V::Result { + let Attribute { kind, id: _, style: _, span } = attr; + match kind { + AttrKind::Normal(normal) => { + let NormalAttr { item, tokens: _ } = &$($mut)?**normal; + let AttrItem { unsafety: _, path, args, tokens: _ } = item; + try_visit!(vis.visit_path(path)); + try_visit!(walk_attr_args(vis, args)); + } + AttrKind::DocComment(_kind, _sym) => {} } - FormatArgumentKind::Normal => {} + visit_span(vis, span) } - try_visit!(visitor.visit_expr(expr)); - } - V::Result::output() -} -pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V::Result { - let Expr { id, kind, span, attrs, tokens: _ } = expression; - walk_list!(visitor, visit_attribute, attrs); - match kind { - ExprKind::Array(subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)), - ExprKind::Repeat(element, count) => { - try_visit!(visitor.visit_expr(element)); - try_visit!(visitor.visit_anon_const(count)); - } - ExprKind::Struct(se) => { - let StructExpr { qself, path, fields, rest } = &**se; - try_visit!(visitor.visit_qself(qself)); - try_visit!(visitor.visit_id(*id)); - try_visit!(visitor.visit_path(path)); - walk_list!(visitor, visit_expr_field, fields); - match rest { - StructRest::Base(expr) => try_visit!(visitor.visit_expr(expr)), - StructRest::Rest(_span) => {} - StructRest::None => {} + pub fn walk_attr_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, args: &$($lt)? $($mut)? AttrArgs) -> V::Result { + match args { + AttrArgs::Empty => {} + AttrArgs::Delimited(args) => try_visit!(visit_delim_args(vis, args)), + AttrArgs::Eq { eq_span, expr } => { + try_visit!(vis.visit_expr(expr)); + try_visit!(visit_span(vis, eq_span)); + } } + V::Result::output() } - ExprKind::Tup(subexpressions) => { - walk_list!(visitor, visit_expr, subexpressions); - } - ExprKind::Call(callee_expression, arguments) => { - try_visit!(visitor.visit_expr(callee_expression)); - walk_list!(visitor, visit_expr, arguments); - } - ExprKind::MethodCall(box MethodCall { seg, receiver, args, span: _ }) => { - try_visit!(visitor.visit_expr(receiver)); - try_visit!(visitor.visit_path_segment(seg)); - walk_list!(visitor, visit_expr, args); - } - ExprKind::Binary(_op, left_expression, right_expression) => { - try_visit!(visitor.visit_expr(left_expression)); - try_visit!(visitor.visit_expr(right_expression)); - } - ExprKind::AddrOf(_kind, _mutbl, subexpression) => { - try_visit!(visitor.visit_expr(subexpression)); - } - ExprKind::Unary(_op, subexpression) => { - try_visit!(visitor.visit_expr(subexpression)); - } - ExprKind::Cast(subexpression, typ) | ExprKind::Type(subexpression, typ) => { - try_visit!(visitor.visit_expr(subexpression)); - try_visit!(visitor.visit_ty(typ)); - } - ExprKind::Let(pat, expr, _span, _recovered) => { - try_visit!(visitor.visit_pat(pat)); - try_visit!(visitor.visit_expr(expr)); - } - ExprKind::If(head_expression, if_block, optional_else) => { - try_visit!(visitor.visit_expr(head_expression)); - try_visit!(visitor.visit_block(if_block)); - visit_opt!(visitor, visit_expr, optional_else); - } - ExprKind::While(subexpression, block, opt_label) => { - visit_opt!(visitor, visit_label, opt_label); - try_visit!(visitor.visit_expr(subexpression)); - try_visit!(visitor.visit_block(block)); - } - ExprKind::ForLoop { pat, iter, body, label, kind: _ } => { - visit_opt!(visitor, visit_label, label); - try_visit!(visitor.visit_pat(pat)); - try_visit!(visitor.visit_expr(iter)); - try_visit!(visitor.visit_block(body)); - } - ExprKind::Loop(block, opt_label, _span) => { - visit_opt!(visitor, visit_label, opt_label); - try_visit!(visitor.visit_block(block)); - } - ExprKind::Match(subexpression, arms, _kind) => { - try_visit!(visitor.visit_expr(subexpression)); - walk_list!(visitor, visit_arm, arms); - } - ExprKind::Closure(box Closure { - binder, - capture_clause, - coroutine_kind, - constness: _, - movability: _, - fn_decl, - body, - fn_decl_span: _, - fn_arg_span: _, - }) => { - try_visit!(visitor.visit_capture_by(capture_clause)); - try_visit!(visitor.visit_fn( - FnKind::Closure(binder, coroutine_kind, fn_decl, body), - *span, - *id - )); - } - ExprKind::Block(block, opt_label) => { - visit_opt!(visitor, visit_label, opt_label); - try_visit!(visitor.visit_block(block)); - } - ExprKind::Gen(_capt, body, _kind, _decl_span) => try_visit!(visitor.visit_block(body)), - ExprKind::Await(expr, _span) => try_visit!(visitor.visit_expr(expr)), - ExprKind::Use(expr, _span) => try_visit!(visitor.visit_expr(expr)), - ExprKind::Assign(lhs, rhs, _span) => { - try_visit!(visitor.visit_expr(lhs)); - try_visit!(visitor.visit_expr(rhs)); - } - ExprKind::AssignOp(_op, left_expression, right_expression) => { - try_visit!(visitor.visit_expr(left_expression)); - try_visit!(visitor.visit_expr(right_expression)); - } - ExprKind::Field(subexpression, ident) => { - try_visit!(visitor.visit_expr(subexpression)); - try_visit!(visitor.visit_ident(ident)); - } - ExprKind::Index(main_expression, index_expression, _span) => { - try_visit!(visitor.visit_expr(main_expression)); - try_visit!(visitor.visit_expr(index_expression)); - } - ExprKind::Range(start, end, _limit) => { - visit_opt!(visitor, visit_expr, start); - visit_opt!(visitor, visit_expr, end); - } - ExprKind::Underscore => {} - ExprKind::Path(maybe_qself, path) => { - try_visit!(visitor.visit_qself(maybe_qself)); - try_visit!(visitor.visit_id(*id)); - try_visit!(visitor.visit_path(path)); - } - ExprKind::Break(opt_label, opt_expr) => { - visit_opt!(visitor, visit_label, opt_label); - visit_opt!(visitor, visit_expr, opt_expr); - } - ExprKind::Continue(opt_label) => { - visit_opt!(visitor, visit_label, opt_label); - } - ExprKind::Ret(optional_expression) => { - visit_opt!(visitor, visit_expr, optional_expression); - } - ExprKind::Yeet(optional_expression) => { - visit_opt!(visitor, visit_expr, optional_expression); - } - ExprKind::Become(expr) => try_visit!(visitor.visit_expr(expr)), - ExprKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)), - ExprKind::Paren(subexpression) => try_visit!(visitor.visit_expr(subexpression)), - ExprKind::InlineAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), - ExprKind::FormatArgs(f) => try_visit!(visitor.visit_format_args(f)), - ExprKind::OffsetOf(container, fields) => { - try_visit!(visitor.visit_ty(container)); - walk_list!(visitor, visit_ident, fields.iter()); - } - ExprKind::Yield(kind) => { - visit_opt!(visitor, visit_expr, kind.expr()); - } - ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), - ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), - ExprKind::Lit(_token) => {} - ExprKind::IncludedBytes(_bytes) => {} - ExprKind::UnsafeBinderCast(_kind, expr, ty) => { - try_visit!(visitor.visit_expr(expr)); - visit_opt!(visitor, visit_ty, ty); - } - ExprKind::Err(_guar) => {} - ExprKind::Dummy => {} - } - - V::Result::output() + }; } -pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) -> V::Result { - let Param { attrs, ty, pat, id: _, span: _, is_placeholder: _ } = param; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_pat(pat)); - try_visit!(visitor.visit_ty(ty)); - V::Result::output() +common_visitor_and_walkers!(Visitor<'a>); + +macro_rules! generate_list_visit_fns { + ($($name:ident, $Ty:ty, $visit_fn:ident$(, $param:ident: $ParamTy:ty)*;)+) => { + $( + fn $name<'a, V: Visitor<'a>>( + vis: &mut V, + values: &'a ThinVec<$Ty>, + $( + $param: $ParamTy, + )* + ) -> V::Result { + walk_list!(vis, $visit_fn, values$(,$param)*); + V::Result::output() + } + )+ + } } -pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) -> V::Result { - let Arm { attrs, pat, guard, body, span: _, id: _, is_placeholder: _ } = arm; - walk_list!(visitor, visit_attribute, attrs); - try_visit!(visitor.visit_pat(pat)); - visit_opt!(visitor, visit_expr, guard); - visit_opt!(visitor, visit_expr, body); - V::Result::output() +generate_list_visit_fns! { + visit_items, P<Item>, visit_item; + visit_foreign_items, P<ForeignItem>, visit_foreign_item; + visit_generic_params, GenericParam, visit_generic_param; + visit_stmts, Stmt, visit_stmt; + visit_exprs, P<Expr>, visit_expr; + visit_expr_fields, ExprField, visit_expr_field; + visit_pat_fields, PatField, visit_pat_field; + visit_variants, Variant, visit_variant; + visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt; + visit_where_predicates, WherePredicate, visit_where_predicate; + visit_params, Param, visit_param; + visit_field_defs, FieldDef, visit_field_def; + visit_arms, Arm, visit_arm; } -pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) -> V::Result { - let Visibility { kind, span: _, tokens: _ } = vis; - match kind { - VisibilityKind::Restricted { path, id, shorthand: _ } => { - try_visit!(visitor.visit_id(*id)); - try_visit!(visitor.visit_path(path)); - } - VisibilityKind::Public | VisibilityKind::Inherited => {} - } - V::Result::output() +#[expect(rustc::pass_by_value)] // needed for symmetry with mut_visit +fn visit_nested_use_tree<'a, V: Visitor<'a>>( + vis: &mut V, + nested_tree: &'a UseTree, + &nested_id: &NodeId, +) -> V::Result { + vis.visit_nested_use_tree(nested_tree, nested_id) } -pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) -> V::Result { - let Attribute { kind, id: _, style: _, span: _ } = attr; +pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { + let Stmt { id: _, kind, span: _ } = statement; match kind { - AttrKind::Normal(normal) => { - let NormalAttr { item, tokens: _ } = &**normal; - let AttrItem { unsafety: _, path, args, tokens: _ } = item; - try_visit!(visitor.visit_path(path)); - try_visit!(walk_attr_args(visitor, args)); + StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), + StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), + StmtKind::Empty => {} + StmtKind::MacCall(mac) => { + let MacCallStmt { mac, attrs, style: _, tokens: _ } = &**mac; + walk_list!(visitor, visit_attribute, attrs); + try_visit!(visitor.visit_mac_call(mac)); } - AttrKind::DocComment(_kind, _sym) => {} - } - V::Result::output() -} - -pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -> V::Result { - match args { - AttrArgs::Empty => {} - AttrArgs::Delimited(_args) => {} - AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)), } V::Result::output() } diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index d2d1285b075..845e4d5e5d0 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -57,14 +57,6 @@ impl OptimizeAttr { } } -#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic, PrintAttribute)] -pub enum DiagnosticAttribute { - // tidy-alphabetical-start - DoNotRecommend, - OnUnimplemented, - // tidy-alphabetical-end -} - #[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone, HashStable_Generic, PrintAttribute)] pub enum ReprAttr { ReprInt(IntType), @@ -160,40 +152,52 @@ impl Deprecation { #[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] pub enum AttributeKind { // tidy-alphabetical-start + /// Represents `#[rustc_allow_const_fn_unstable]`. AllowConstFnUnstable(ThinVec<Symbol>), + + /// Represents `#[allow_internal_unstable]`. AllowInternalUnstable(ThinVec<(Symbol, Span)>), + + /// Represents `#[rustc_default_body_unstable]`. BodyStability { stability: DefaultBodyStability, /// Span of the `#[rustc_default_body_unstable(...)]` attribute span: Span, }, + + /// Represents `#[rustc_confusables]`. Confusables { symbols: ThinVec<Symbol>, // FIXME(jdonszelmann): remove when target validation code is moved first_span: Span, }, + + /// Represents `#[rustc_const_stable]` and `#[rustc_const_unstable]`. ConstStability { stability: PartialConstStability, /// Span of the `#[rustc_const_stable(...)]` or `#[rustc_const_unstable(...)]` attribute span: Span, }, + + /// Represents `#[rustc_const_stable_indirect]`. ConstStabilityIndirect, - Deprecation { - deprecation: Deprecation, - span: Span, - }, - Diagnostic(DiagnosticAttribute), - DocComment { - style: AttrStyle, - kind: CommentKind, - span: Span, - comment: Symbol, - }, + + /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute). + Deprecation { deprecation: Deprecation, span: Span }, + + /// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html). + DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol }, + + /// Represents `#[rustc_macro_transparency]`. MacroTransparency(Transparency), + + /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr(ThinVec<(ReprAttr, Span)>), + + /// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`. Stability { stability: Stability, - /// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute + /// Span of the attribute. span: Span, }, // tidy-alphabetical-end diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 443c2eace55..27fd09745ff 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -5,6 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry}; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::{BranchProtection, FunctionReturn, OptLevel, PAuthKey, PacRet}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtector}; use smallvec::SmallVec; @@ -256,11 +257,11 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { StackProbeType::Inline => "inline-asm", // Flag our internal `__rust_probestack` function as the stack probe symbol. // This is defined in the `compiler-builtins` crate for each architecture. - StackProbeType::Call => "__rust_probestack", + StackProbeType::Call => &mangle_internal_symbol(cx.tcx, "__rust_probestack"), // Pick from the two above based on the LLVM version. StackProbeType::InlineOrCall { min_llvm_version_for_inline } => { if llvm_util::get_version() < min_llvm_version_for_inline { - "__rust_probestack" + &mangle_internal_symbol(cx.tcx, "__rust_probestack") } else { "inline-asm" } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 9719d405259..4f252f3ccd4 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -356,10 +356,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { hir::ConstContext::ConstFn => true, _ => { // For indirect places, we are not creating a new permanent borrow, it's just as - // transient as the already existing one. For reborrowing references this is handled - // at the top of `visit_rvalue`, but for raw pointers we handle it here. - // Pointers/references to `static mut` and cases where the `*` is not the first - // projection also end up here. + // transient as the already existing one. // Locals with StorageDead do not live beyond the evaluation and can // thus safely be borrowed without being able to be leaked to the final // value of the constant. diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 1dd96297d1f..f0f958d069e 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -227,12 +227,11 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval // Keep interning as long as there are things to intern. // We show errors if there are dangling pointers, or mutable pointers in immutable contexts - // (i.e., everything except for `static mut`). When these errors affect references, it is - // unfortunate that we show these errors here and not during validation, since validation can - // show much nicer errors. However, we do need these checks to be run on all pointers, including - // raw pointers, so we cannot rely on validation to catch them -- and since interning runs - // before validation, and interning doesn't know the type of anything, this means we can't show - // better errors. Maybe we should consider doing validation before interning in the future. + // (i.e., everything except for `static mut`). We only return these errors as a `Result` + // so that the caller can run validation, and subsequently only report interning errors + // if validation fails. Validation has the better error messages so we prefer those, but + // interning has better coverage since it "sees" *all* pointers, including raw pointers and + // references stored in unions. while let Some(prov) = todo.pop() { trace!(?prov); let alloc_id = prov.alloc_id(); @@ -279,12 +278,12 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval // when there is memory there that someone might expect to be mutable, but we make it immutable. let dangling = !is_already_global && !ecx.memory.alloc_map.contains_key(&alloc_id); if !dangling { - // Found a mutable reference inside a const where inner allocations should be + // Found a mutable pointer inside a const where inner allocations should be // immutable. if !ecx.tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you { span_bug!( ecx.tcx.span, - "the static const safety checks accepted mutable references they should not have accepted" + "the static const safety checks accepted a mutable pointer they should not have accepted" ); } // Prefer dangling pointer errors over mutable pointer errors diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index f26c7c1ba0b..08b7a362083 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -62,6 +62,7 @@ expand_feature_not_allowed = expand_feature_removed = feature has been removed .label = feature has been removed + .note = removed in {$removed_rustc_version} (you are using {$current_rustc_version}){$pull_note} .reason = {$reason} expand_glob_delegation_outside_impls = diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index c50ab5959e2..9a359e9b031 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -80,9 +80,20 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) - // If the enabled feature has been removed, issue an error. if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| name == f.feature.name) { + let pull_note = if let Some(pull) = f.pull { + format!( + "; see <https://github.com/rust-lang/rust/pull/{}> for more information", + pull + ) + } else { + "".to_owned() + }; sess.dcx().emit_err(FeatureRemoved { span: mi.span(), reason: f.reason.map(|reason| FeatureRemovedReason { reason }), + removed_rustc_version: f.feature.since, + current_rustc_version: sess.cfg_version, + pull_note, }); continue; } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 89bdc7b6dfa..ec0af67c046 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -154,12 +154,16 @@ pub(crate) struct HelperAttributeNameInvalid { #[derive(Diagnostic)] #[diag(expand_feature_removed, code = E0557)] +#[note] pub(crate) struct FeatureRemoved<'a> { #[primary_span] #[label] pub span: Span, #[subdiagnostic] pub reason: Option<FeatureRemovedReason<'a>>, + pub removed_rustc_version: &'a str, + pub current_rustc_version: &'a str, + pub pull_note: String, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 10c5cb194f4..b1c185220f4 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -259,6 +259,8 @@ declare_features! ( /// Allows some increased flexibility in the name resolution rules, /// especially around globs and shadowing (RFC 1560). (accepted, item_like_imports, "1.15.0", Some(35120)), + // Allows using the `kl` and `widekl` target features and the associated intrinsics + (accepted, keylocker_x86, "CURRENT_RUSTC_VERSION", Some(134813)), /// Allows `'a: { break 'a; }`. (accepted, label_break_value, "1.65.0", Some(48594)), /// Allows `let...else` statements. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 013e1d5d0fa..9738f169595 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -1,5 +1,7 @@ //! List of the removed feature gates. +use std::num::{NonZero, NonZeroU32}; + use rustc_span::sym; use super::{Feature, to_nonzero}; @@ -7,11 +9,21 @@ use super::{Feature, to_nonzero}; pub struct RemovedFeature { pub feature: Feature, pub reason: Option<&'static str>, + pub pull: Option<NonZero<u32>>, +} + +macro_rules! opt_nonzero_u32 { + () => { + None + }; + ($val:expr) => { + Some(NonZeroU32::new($val).unwrap()) + }; } macro_rules! declare_features { ($( - $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr), + $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr $(, $pull:expr)?), )+) => { /// Formerly unstable features that have now been removed. pub static REMOVED_LANG_FEATURES: &[RemovedFeature] = &[ @@ -21,7 +33,8 @@ macro_rules! declare_features { since: $ver, issue: to_nonzero($issue), }, - reason: $reason + reason: $reason, + pull: opt_nonzero_u32!($($pull)?), }),+ ]; }; @@ -40,64 +53,64 @@ declare_features! ( // version they got originally added in.) /// Allows using the `amdgpu-kernel` ABI. - (removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None), - (removed, advanced_slice_patterns, "1.0.0", Some(62254), - Some("merged into `#![feature(slice_patterns)]`")), + (removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None, 120495), + (removed, advanced_slice_patterns, "1.42.0", Some(62254), + Some("merged into `#![feature(slice_patterns)]`"), 67712), (removed, allocator, "1.0.0", None, None), /// Allows a test to fail without failing the whole suite. - (removed, allow_fail, "1.19.0", Some(46488), Some("removed due to no clear use cases")), + (removed, allow_fail, "1.60.0", Some(46488), Some("removed due to no clear use cases"), 93416), (removed, await_macro, "1.38.0", Some(50547), - Some("subsumed by `.await` syntax")), + Some("subsumed by `.await` syntax"), 62293), /// Allows using the `box $expr` syntax. - (removed, box_syntax, "1.70.0", Some(49733), Some("replaced with `#[rustc_box]`")), + (removed, box_syntax, "1.70.0", Some(49733), Some("replaced with `#[rustc_box]`"), 108471), /// Allows capturing disjoint fields in a closure/coroutine (RFC 2229). - (removed, capture_disjoint_fields, "1.49.0", Some(53488), Some("stabilized in Rust 2021")), + (removed, capture_disjoint_fields, "1.69.0", Some(53488), Some("stabilized in Rust 2021"), 108550), /// Allows comparing raw pointers during const eval. (removed, const_compare_raw_pointers, "1.46.0", Some(53020), - Some("cannot be allowed in const eval in any meaningful way")), + Some("cannot be allowed in const eval in any meaningful way"), 73398), /// Allows limiting the evaluation steps of const expressions - (removed, const_eval_limit, "1.43.0", Some(67217), Some("removed the limit entirely")), + (removed, const_eval_limit, "1.72.0", Some(67217), Some("removed the limit entirely"), 103877), /// Allows non-trivial generic constants which have to be manually propagated upwards. - (removed, const_evaluatable_checked, "1.48.0", Some(76560), Some("renamed to `generic_const_exprs`")), + (removed, const_evaluatable_checked, "1.56.0", Some(76560), Some("renamed to `generic_const_exprs`"), 88369), /// Allows the definition of `const` functions with some advanced features. (removed, const_fn, "1.54.0", Some(57563), - Some("split into finer-grained feature gates")), + Some("split into finer-grained feature gates"), 85109), /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`). - (removed, const_generics, "1.34.0", Some(44580), - Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")), + (removed, const_generics, "1.56.0", Some(44580), + Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`"), 88369), /// Allows `[x; N]` where `x` is a constant (RFC 2203). - (removed, const_in_array_repeat_expressions, "1.37.0", Some(49147), - Some("removed due to causing promotable bugs")), + (removed, const_in_array_repeat_expressions, "1.51.0", Some(49147), + Some("removed due to causing promotable bugs"), 80404), /// Allows casting raw pointers to `usize` during const eval. (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), - Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")), + Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported"), 87020), /// Allows `T: ?const Trait` syntax in bounds. - (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), - Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")), + (removed, const_trait_bound_opt_out, "1.56.0", Some(67794), + Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]"), 88328), /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. - (removed, crate_visibility_modifier, "1.63.0", Some(53120), Some("removed in favor of `pub(crate)`")), + (removed, crate_visibility_modifier, "1.63.0", Some(53120), Some("removed in favor of `pub(crate)`"), 97254), /// Allows using custom attributes (RFC 572). (removed, custom_attribute, "1.0.0", Some(29642), - Some("removed in favor of `#![register_tool]` and `#![register_attr]`")), + Some("removed in favor of `#![register_tool]` and `#![register_attr]`"), 66070), /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. (removed, custom_derive, "1.32.0", Some(29644), Some("subsumed by `#[proc_macro_derive]`")), /// Allows default type parameters to influence type inference. (removed, default_type_parameter_fallback, "1.82.0", Some(27336), - Some("never properly implemented; requires significant design work")), + Some("never properly implemented; requires significant design work"), 127655), /// Allows deriving traits as per `SmartPointer` specification - (removed, derive_smart_pointer, "1.79.0", Some(123430), Some("replaced by `CoercePointee`")), + (removed, derive_smart_pointer, "1.84.0", Some(123430), Some("replaced by `CoercePointee`"), 131284), /// Allows using `#[doc(keyword = "...")]`. - (removed, doc_keyword, "1.28.0", Some(51315), - Some("merged into `#![feature(rustdoc_internals)]`")), + (removed, doc_keyword, "1.58.0", Some(51315), + Some("merged into `#![feature(rustdoc_internals)]`"), 90420), /// Allows using `doc(primitive)` without a future-incompat warning. - (removed, doc_primitive, "1.56.0", Some(88070), - Some("merged into `#![feature(rustdoc_internals)]`")), + (removed, doc_primitive, "1.58.0", Some(88070), + Some("merged into `#![feature(rustdoc_internals)]`"), 90420), /// Allows `#[doc(spotlight)]`. /// The attribute was renamed to `#[doc(notable_trait)]` /// and the feature to `doc_notable_trait`. - (removed, doc_spotlight, "1.22.0", Some(45040), - Some("renamed to `doc_notable_trait`")), + (removed, doc_spotlight, "1.53.0", Some(45040), + Some("renamed to `doc_notable_trait`"), 80965), /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (removed, dropck_parametricity, "1.38.0", Some(28498), None), /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible[^1]. @@ -107,161 +120,162 @@ declare_features! ( /// Renamed from `object_safe_for_dispatch`. /// /// [^1]: Formerly known as "object safe". - (removed, dyn_compatible_for_dispatch, "1.83.0", Some(43561), - Some("removed, not used heavily and represented additional complexity in dyn compatibility")), + (removed, dyn_compatible_for_dispatch, "1.87.0", Some(43561), + Some("removed, not used heavily and represented additional complexity in dyn compatibility"), 136522), /// Uses generic effect parameters for ~const bounds (removed, effects, "1.84.0", Some(102090), - Some("removed, redundant with `#![feature(const_trait_impl)]`")), + Some("removed, redundant with `#![feature(const_trait_impl)]`"), 132479), /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), /// Paths of the form: `extern::foo::bar` (removed, extern_in_paths, "1.33.0", Some(55600), - Some("subsumed by `::foo::bar` paths")), + Some("subsumed by `::foo::bar` paths"), 57572), /// Allows `#[doc(include = "some-file")]`. (removed, external_doc, "1.54.0", Some(44732), - Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), + Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations"), 85457), /// Allows using `#[ffi_returns_twice]` on foreign functions. (removed, ffi_returns_twice, "1.78.0", Some(58314), - Some("being investigated by the ffi-unwind project group")), + Some("being investigated by the ffi-unwind project group"), 120502), /// Allows generators to be cloned. - (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")), + (removed, generator_clone, "1.75.0", Some(95360), Some("renamed to `coroutine_clone`"), 116958), /// Allows defining generators. - (removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")), + (removed, generators, "1.75.0", Some(43122), Some("renamed to `coroutines`"), 116958), /// An extension to the `generic_associated_types` feature, allowing incomplete features. (removed, generic_associated_types_extended, "1.85.0", Some(95451), Some( "feature needs overhaul and reimplementation pending \ better implied higher-ranked implied bounds support" - ) + ), + 133768 ), (removed, import_shadowing, "1.0.0", None, None), /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). - (removed, in_band_lifetimes, "1.23.0", Some(44524), - Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity")), + (removed, in_band_lifetimes, "1.61.0", Some(44524), + Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity"), 93845), /// Allows inferring `'static` outlives requirements (RFC 2093). (removed, infer_static_outlives_requirements, "1.63.0", Some(54185), - Some("removed as it caused some confusion and discussion was inactive for years")), + Some("removed as it caused some confusion and discussion was inactive for years"), 97875), /// Allow anonymous constants from an inline `const` block in pattern position (removed, inline_const_pat, "1.88.0", Some(76001), - Some("removed due to implementation concerns as it requires significant refactorings")), + Some("removed due to implementation concerns as it requires significant refactorings"), 138492), /// Lazily evaluate constants. This allows constants to depend on type parameters. - (removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")), + (removed, lazy_normalization_consts, "1.56.0", Some(72219), Some("superseded by `generic_const_exprs`"), 88369), /// Changes `impl Trait` to capture all lifetimes in scope. - (removed, lifetime_capture_rules_2024, "1.76.0", None, Some("unnecessary -- use edition 2024 instead")), + (removed, lifetime_capture_rules_2024, "1.87.0", None, Some("unnecessary -- use edition 2024 instead"), 136787), /// Allows using the `#[link_args]` attribute. (removed, link_args, "1.53.0", Some(29596), Some("removed in favor of using `-C link-arg=ARG` on command line, \ - which is available from cargo build scripts with `cargo:rustc-link-arg` now")), + which is available from cargo build scripts with `cargo:rustc-link-arg` now"), 83820), (removed, macro_reexport, "1.0.0", Some(29638), - Some("subsumed by `pub use`")), + Some("subsumed by `pub use`"), 49982), /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. - (removed, main, "1.53.0", Some(29634), None), + (removed, main, "1.53.0", Some(29634), None, 84217), (removed, managed_boxes, "1.0.0", None, None), /// Allows the use of type alias impl trait in function return positions (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), - Some("removed in favor of full type_alias_impl_trait")), + Some("removed in favor of full type_alias_impl_trait"), 87564), /// Make `mut` not reset the binding mode on edition >= 2024. - (removed, mut_preserve_binding_mode_2024, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`")), + (removed, mut_preserve_binding_mode_2024, "1.80.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`"), 125168), (removed, needs_allocator, "1.4.0", Some(27389), Some("subsumed by `#![feature(allocator_internals)]`")), /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 (removed, negate_unsigned, "1.0.0", Some(29645), None), /// Allows `#[no_coverage]` on functions. /// The feature was renamed to `coverage_attribute` and the attribute to `#[coverage(on|off)]` - (removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`")), + (removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`"), 114656), /// Allows `#[no_debug]`. - (removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand")), + (removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand"), 69667), /// Note: this feature was previously recorded in a separate /// `STABLE_REMOVED` list because it, uniquely, was once stable but was /// then removed. But there was no utility storing it separately, so now /// it's in this list. - (removed, no_stack_check, "1.0.0", None, None), + (removed, no_stack_check, "1.0.0", None, None, 40110), /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible (object safe). /// Renamed to `dyn_compatible_for_dispatch`. (removed, object_safe_for_dispatch, "1.83.0", Some(43561), - Some("renamed to `dyn_compatible_for_dispatch`")), + Some("renamed to `dyn_compatible_for_dispatch`"), 131511), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) - (removed, on_unimplemented, "1.40.0", None, None), + (removed, on_unimplemented, "1.40.0", None, None, 65794), /// A way to temporarily opt out of opt-in copy. This will *never* be accepted. - (removed, opt_out_copy, "1.0.0", None, None), + (removed, opt_out_copy, "1.0.0", None, None, 20740), /// Allows features specific to OIBIT (now called auto traits). /// Renamed to `auto_traits`. - (removed, optin_builtin_traits, "1.0.0", Some(13231), - Some("renamed to `auto_traits`")), + (removed, optin_builtin_traits, "1.50.0", Some(13231), + Some("renamed to `auto_traits`"), 79336), /// Allows overlapping impls of marker traits. (removed, overlapping_marker_traits, "1.42.0", Some(29864), - Some("removed in favor of `#![feature(marker_trait_attr)]`")), + Some("removed in favor of `#![feature(marker_trait_attr)]`"), 68544), (removed, panic_implementation, "1.28.0", Some(44489), - Some("subsumed by `#[panic_handler]`")), + Some("subsumed by `#[panic_handler]`"), 53619), /// Allows `extern "platform-intrinsic" { ... }`. - (removed, platform_intrinsics, "1.4.0", Some(27731), - Some("SIMD intrinsics use the regular intrinsics ABI now")), + (removed, platform_intrinsics, "1.78.0", Some(27731), + Some("SIMD intrinsics use the regular intrinsics ABI now"), 121516), /// Allows using `#![plugin(myplugin)]`. (removed, plugin, "1.75.0", Some(29597), - Some("plugins are no longer supported")), + Some("plugins are no longer supported"), 116412), /// Allows using `#[plugin_registrar]` on functions. - (removed, plugin_registrar, "1.54.0", Some(29597), - Some("plugins are no longer supported")), + (removed, plugin_registrar, "1.75.0", Some(29597), + Some("plugins are no longer supported"), 116412), /// Allows exhaustive integer pattern matching with `usize::MAX`/`isize::MIN`/`isize::MAX`. - (removed, precise_pointer_size_matching, "1.32.0", Some(56354), - Some("removed in favor of half-open ranges")), + (removed, precise_pointer_size_matching, "1.76.0", Some(56354), + Some("removed in favor of half-open ranges"), 118598), (removed, pref_align_of, "CURRENT_RUSTC_VERSION", Some(91971), Some("removed due to marginal use and inducing compiler complications")), (removed, proc_macro_expr, "1.27.0", Some(54727), - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121), (removed, proc_macro_gen, "1.27.0", Some(54727), - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121), (removed, proc_macro_mod, "1.27.0", Some(54727), - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121), (removed, proc_macro_non_items, "1.27.0", Some(54727), - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + Some("subsumed by `#![feature(proc_macro_hygiene)]`"), 52121), (removed, pub_macro_rules, "1.53.0", Some(78855), Some("removed due to being incomplete, in particular it does not work across crates")), (removed, pushpop_unsafe, "1.2.0", None, None), (removed, quad_precision_float, "1.0.0", None, None), (removed, quote, "1.33.0", Some(29601), None), - (removed, ref_pat_everywhere, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024")), + (removed, ref_pat_everywhere, "1.80.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024"), 125168), (removed, reflect, "1.0.0", Some(27749), None), /// Allows using the `#[register_attr]` attribute. (removed, register_attr, "1.65.0", Some(66080), - Some("removed in favor of `#![register_tool]`")), + Some("removed in favor of `#![register_tool]`"), 66070), (removed, rust_2018_preview, "1.76.0", None, Some("2018 Edition preview is no longer relevant")), /// Allows using the macros: /// + `__diagnostic_used` /// + `__register_diagnostic` /// +`__build_diagnostic_array` - (removed, rustc_diagnostic_macros, "1.38.0", None, None), + (removed, rustc_diagnostic_macros, "1.38.0", None, None, 64139), /// Allows identifying crates that contain sanitizer runtimes. - (removed, sanitizer_runtime, "1.17.0", None, None), + (removed, sanitizer_runtime, "1.17.0", None, None, 65241), (removed, simd, "1.0.0", Some(27731), Some("removed in favor of `#[repr(simd)]`")), /// Allows using `#[start]` on a function indicating that it is the program entrypoint. - (removed, start, "1.0.0", Some(29633), Some("not portable enough and never RFC'd")), + (removed, start, "1.86.0", Some(29633), Some("not portable enough and never RFC'd"), 134299), /// Allows `#[link(kind = "static-nobundle", ...)]`. - (removed, static_nobundle, "1.16.0", Some(37403), - Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#)), + (removed, static_nobundle, "1.63.0", Some(37403), + Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#), 95818), (removed, struct_inherit, "1.0.0", None, None), (removed, test_removed_feature, "1.0.0", None, None), /// Allows using items which are missing stability attributes (removed, unmarked_api, "1.0.0", None, None), /// Allows unnamed fields of struct and union type - (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign")), + (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign"), 131045), (removed, unsafe_no_drop_flag, "1.0.0", None, None), (removed, unsized_tuple_coercion, "1.87.0", Some(42877), - Some("The feature restricts possible layouts for tuples, and this restriction is not worth it.")), + Some("The feature restricts possible layouts for tuples, and this restriction is not worth it."), 137728), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. - (removed, untagged_unions, "1.13.0", Some(55149), - Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more")), + (removed, untagged_unions, "1.64.0", Some(55149), + Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more"), 97995), /// Allows `#[unwind(..)]`. /// /// Permits specifying whether a function should permit unwinding or abort on unwind. - (removed, unwind_attributes, "1.56.0", Some(58760), Some("use the C-unwind ABI instead")), + (removed, unwind_attributes, "1.56.0", Some(58760), Some("use the C-unwind ABI instead"), 86155), (removed, visible_private_types, "1.0.0", None, None), /// Allows `extern "wasm" fn` (removed, wasm_abi, "1.81.0", Some(83788), - Some("non-standard wasm ABI is no longer supported")), + Some("non-standard wasm ABI is no longer supported"), 127605), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 9447deeecbb..594021d78d2 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -546,8 +546,6 @@ declare_features! ( (incomplete, inherent_associated_types, "1.52.0", Some(8995)), /// Allows using `pointer` and `reference` in intra-doc links (unstable, intra_doc_pointers, "1.51.0", Some(80896)), - // Allows using the `kl` and `widekl` target features and the associated intrinsics - (unstable, keylocker_x86, "1.86.0", Some(134813)), // Allows setting the threshold for the `large_assignments` lint. (unstable, large_assignments, "1.52.0", Some(83518)), /// Allow to have type alias types for inter-crate use. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 064b42413f0..60ca0155bdd 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -37,22 +37,23 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir}; use super::compare_impl_item::check_type_bounds; use super::*; +fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) { + if let ExternAbi::Cdecl { unwind } = abi { + let c_abi = ExternAbi::C { unwind }; + diag.help(format!("use `extern {c_abi}` instead",)); + } else if let ExternAbi::Stdcall { unwind } = abi { + let c_abi = ExternAbi::C { unwind }; + let system_abi = ExternAbi::System { unwind }; + diag.help(format!( + "if you need `extern {abi}` on win32 and `extern {c_abi}` everywhere else, \ + use `extern {system_abi}`" + )); + } +} + pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) { // FIXME: this should be checked earlier, e.g. in `rustc_ast_lowering`, to fix // things like #86232. - fn add_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) { - if let ExternAbi::Cdecl { unwind } = abi { - let c_abi = ExternAbi::C { unwind }; - diag.help(format!("use `extern {c_abi}` instead",)); - } else if let ExternAbi::Stdcall { unwind } = abi { - let c_abi = ExternAbi::C { unwind }; - let system_abi = ExternAbi::System { unwind }; - diag.help(format!( - "if you need `extern {abi}` on win32 and `extern {c_abi}` everywhere else, \ - use `extern {system_abi}`" - )); - } - } match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) { AbiMapping::Direct(..) => (), @@ -63,13 +64,13 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi E0570, "`{abi}` is not a supported ABI for the current target", ); - add_help(abi, &mut err); + add_abi_diag_help(abi, &mut err); err.emit(); } AbiMapping::Deprecated(..) => { tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { lint.primary_message("use of calling convention not supported on this target"); - add_help(abi, lint); + add_abi_diag_help(abi, lint); }); } } @@ -80,7 +81,16 @@ pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ex // in `check_abi` above. match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) { AbiMapping::Direct(..) => (), - AbiMapping::Deprecated(..) | AbiMapping::Invalid => { + // This is not a redundant match arm: these ABIs started linting after introducing + // UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS already existed and we want to + // avoid expanding the scope of that lint so it can move to a hard error sooner. + AbiMapping::Deprecated(..) => { + tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { + lint.primary_message("use of calling convention not supported on this target"); + add_abi_diag_help(abi, lint); + }); + } + AbiMapping::Invalid => { tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { lint.primary_message(format!( "the calling convention {abi} is not supported on this target" diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index bb068f3821d..f2f975a6968 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1531,8 +1531,6 @@ pub enum CastKind { /// /// MIR is well-formed if the input and output types have different sizes, /// but running a transmute between differently-sized types is UB. - /// - /// Allowed only in [`MirPhase::Runtime`]; Earlier it's a [`TerminatorKind::Call`]. Transmute, } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index fd91508cc11..7dcdd7999f2 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1308,37 +1308,27 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } CastKind::Transmute => { - if let MirPhase::Runtime(..) = self.body.phase { - // Unlike `mem::transmute`, a MIR `Transmute` is well-formed - // for any two `Sized` types, just potentially UB to run. - - if !self - .tcx - .normalize_erasing_regions(self.typing_env, op_ty) - .is_sized(self.tcx, self.typing_env) - { - self.fail( - location, - format!("Cannot transmute from non-`Sized` type {op_ty}"), - ); - } - if !self - .tcx - .normalize_erasing_regions(self.typing_env, *target_type) - .is_sized(self.tcx, self.typing_env) - { - self.fail( - location, - format!("Cannot transmute to non-`Sized` type {target_type:?}"), - ); - } - } else { + // Unlike `mem::transmute`, a MIR `Transmute` is well-formed + // for any two `Sized` types, just potentially UB to run. + + if !self + .tcx + .normalize_erasing_regions(self.typing_env, op_ty) + .is_sized(self.tcx, self.typing_env) + { self.fail( location, - format!( - "Transmute is not supported in non-runtime phase {:?}.", - self.body.phase - ), + format!("Cannot transmute from non-`Sized` type {op_ty}"), + ); + } + if !self + .tcx + .normalize_erasing_regions(self.typing_env, *target_type) + .is_sized(self.tcx, self.typing_env) + { + self.fail( + location, + format!("Cannot transmute to non-`Sized` type {target_type:?}"), ); } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dc29b03083f..4e2be8ff0b8 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -132,7 +132,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> { target, attrs, ), - _ => { + Attribute::Parsed(AttributeKind::AllowConstFnUnstable { .. }) => { + self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target) + } + Attribute::Parsed(AttributeKind::Deprecation { .. }) => { + self.check_deprecated(hir_id, attr, span, target) + } + Attribute::Parsed(AttributeKind::DocComment { .. }) => { /* `#[doc]` is actually a lot more than just doc comments, so is checked below*/ + } + Attribute::Parsed(AttributeKind::Repr(_)) => { /* handled below this loop and elsewhere */ + } + Attribute::Parsed( + AttributeKind::BodyStability { .. } + | AttributeKind::ConstStabilityIndirect + | AttributeKind::MacroTransparency(_), + ) => { /* do nothing */ } + Attribute::Unparsed(_) => { match attr.path().as_slice() { [sym::diagnostic, sym::do_not_recommend, ..] => { self.check_do_not_recommend(attr.span(), hir_id, target, attr, item) @@ -169,9 +184,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_rustc_layout_scalar_valid_range(attr, span, target) } [sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target), - [sym::rustc_allow_const_fn_unstable, ..] => { - self.check_rustc_allow_const_fn_unstable(hir_id, attr, span, target) - } [sym::rustc_std_internal_symbol, ..] => { self.check_rustc_std_internal_symbol(attr, span, target) } @@ -229,7 +241,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::link_name, ..] => self.check_link_name(hir_id, attr, span, target), [sym::link_section, ..] => self.check_link_section(hir_id, attr, span, target), [sym::no_mangle, ..] => self.check_no_mangle(hir_id, attr, span, target), - [sym::deprecated, ..] => self.check_deprecated(hir_id, attr, span, target), [sym::macro_use, ..] | [sym::macro_escape, ..] => { self.check_macro_use(hir_id, attr, target) } @@ -283,7 +294,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::pointee // FIXME(derive_coerce_pointee) | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) | sym::used // handled elsewhere to restrict to static items - | sym::repr // handled elsewhere to restrict to type decls items | sym::instruction_set // broken on stable!!! | sym::windows_subsystem // broken on stable!!! | sym::patchable_function_entry // FIXME(patchable_function_entry) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index d48a599f544..5d1182fce48 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -443,7 +443,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("fma", Stable, &["avx"]), ("fxsr", Stable, &[]), ("gfni", Stable, &["sse2"]), - ("kl", Unstable(sym::keylocker_x86), &["sse2"]), + ("kl", Stable, &["sse2"]), ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), ("lzcnt", Stable, &[]), ("movbe", Stable, &[]), @@ -471,7 +471,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("tbm", Unstable(sym::tbm_target_feature), &[]), ("vaes", Stable, &["avx2", "aes"]), ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]), - ("widekl", Unstable(sym::keylocker_x86), &["kl"]), + ("widekl", Stable, &["kl"]), ("x87", Unstable(sym::x87_target_feature), &[]), ("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]), ("xsave", Stable, &[]), | 
