diff options
Diffstat (limited to 'compiler')
29 files changed, 443 insertions, 305 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 1e2576bef2c..610c93a253c 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -416,12 +416,24 @@ pub enum AttributeKind { /// Represents `#[pointee]` Pointee(Span), + /// Represents `#[proc_macro]` + ProcMacro(Span), + + /// Represents `#[proc_macro_attribute]` + ProcMacroAttribute(Span), + + /// Represents `#[proc_macro_derive]` + ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec<Symbol>, span: Span }, + /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint). PubTransparent(Span), /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations). Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span }, + /// Represents `#[rustc_builtin_macro]`. + RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span }, + /// Represents `#[rustc_layout_scalar_valid_range_end]`. RustcLayoutScalarValidRangeEnd(Box<u128>, Span), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 159b807a3b2..af2d46d0bc7 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -61,8 +61,12 @@ impl AttributeKind { PassByValue(..) => Yes, Path(..) => No, Pointee(..) => No, + ProcMacro(..) => No, + ProcMacroAttribute(..) => No, + ProcMacroDerive { .. } => No, PubTransparent(..) => Yes, Repr { .. } => No, + RustcBuiltinMacro { .. } => Yes, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, RustcObjectLifetimeDefault => No, diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 15b90bd2ed7..0c10517d044 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -41,6 +41,7 @@ pub(crate) mod must_use; pub(crate) mod no_implicit_prelude; pub(crate) mod non_exhaustive; pub(crate) mod path; +pub(crate) mod proc_macro_attrs; pub(crate) mod repr; pub(crate) mod rustc_internal; pub(crate) mod semantics; diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs new file mode 100644 index 00000000000..4de77dc268e --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -0,0 +1,139 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Span, Symbol, sym}; +use thin_vec::ThinVec; + +use crate::attributes::{ + AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, +}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; + +pub(crate) struct ProcMacroParser; +impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser { + const PATH: &[Symbol] = &[sym::proc_macro]; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro; +} + +pub(crate) struct ProcMacroAttributeParser; +impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser { + const PATH: &[Symbol] = &[sym::proc_macro_attribute]; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute; +} + +pub(crate) struct ProcMacroDeriveParser; +impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser { + const PATH: &[Symbol] = &[sym::proc_macro_derive]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const TEMPLATE: AttributeTemplate = + template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + let (trait_name, helper_attrs) = parse_derive_like(cx, args, true)?; + Some(AttributeKind::ProcMacroDerive { + trait_name: trait_name.expect("Trait name is mandatory, so it is present"), + helper_attrs, + span: cx.attr_span, + }) + } +} + +pub(crate) struct RustcBuiltinMacroParser; +impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser { + const PATH: &[Symbol] = &[sym::rustc_builtin_macro]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; + const TEMPLATE: AttributeTemplate = + template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + let (builtin_name, helper_attrs) = parse_derive_like(cx, args, false)?; + Some(AttributeKind::RustcBuiltinMacro { builtin_name, helper_attrs, span: cx.attr_span }) + } +} + +fn parse_derive_like<S: Stage>( + cx: &mut AcceptContext<'_, '_, S>, + args: &ArgParser<'_>, + trait_name_mandatory: bool, +) -> Option<(Option<Symbol>, ThinVec<Symbol>)> { + let Some(list) = args.list() else { + // For #[rustc_builtin_macro], it is permitted to leave out the trait name + if args.no_args().is_ok() && !trait_name_mandatory { + return Some((None, ThinVec::new())); + } + cx.expected_list(cx.attr_span); + return None; + }; + let mut items = list.mixed(); + + // Parse the name of the trait that is derived. + let Some(trait_attr) = items.next() else { + cx.expected_at_least_one_argument(list.span); + return None; + }; + let Some(trait_attr) = trait_attr.meta_item() else { + cx.unexpected_literal(trait_attr.span()); + return None; + }; + let Some(trait_ident) = trait_attr.path().word() else { + cx.expected_identifier(trait_attr.path().span()); + return None; + }; + if !trait_ident.name.can_be_raw() { + cx.expected_identifier(trait_ident.span); + return None; + } + if let Err(e) = trait_attr.args().no_args() { + cx.expected_no_args(e); + return None; + }; + + // Parse optional attributes + let mut attributes = ThinVec::new(); + if let Some(attrs) = items.next() { + let Some(attr_list) = attrs.meta_item() else { + cx.expected_list(attrs.span()); + return None; + }; + if !attr_list.path().word_is(sym::attributes) { + cx.expected_specific_argument(attrs.span(), vec!["attributes"]); + return None; + } + let Some(attr_list) = attr_list.args().list() else { + cx.expected_list(attrs.span()); + return None; + }; + + // Parse item in `attributes(...)` argument + for attr in attr_list.mixed() { + let Some(attr) = attr.meta_item() else { + cx.expected_identifier(attr.span()); + return None; + }; + if let Err(e) = attr.args().no_args() { + cx.expected_no_args(e); + return None; + }; + let Some(ident) = attr.path().word() else { + cx.expected_identifier(attr.path().span()); + return None; + }; + if !ident.name.can_be_raw() { + cx.expected_identifier(ident.span); + return None; + } + attributes.push(ident.name); + } + } + + // If anything else is specified, we should reject it + if let Some(next) = items.next() { + cx.expected_no_args(next.span()); + } + + Some((Some(trait_ident.name), attributes)) +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 45bfe345207..9b86d101840 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -38,6 +38,9 @@ use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::non_exhaustive::NonExhaustiveParser; use crate::attributes::path::PathParser as PathAttributeParser; +use crate::attributes::proc_macro_attrs::{ + ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser, +}; use crate::attributes::repr::{AlignParser, ReprParser}; use crate::attributes::rustc_internal::{ RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart, @@ -154,6 +157,8 @@ attribute_parsers!( Single<MustUseParser>, Single<OptimizeParser>, Single<PathAttributeParser>, + Single<ProcMacroDeriveParser>, + Single<RustcBuiltinMacroParser>, Single<RustcForceInlineParser>, Single<RustcLayoutScalarValidRangeEnd>, Single<RustcLayoutScalarValidRangeStart>, @@ -186,6 +191,8 @@ attribute_parsers!( Single<WithoutArgs<ParenSugarParser>>, Single<WithoutArgs<PassByValueParser>>, Single<WithoutArgs<PointeeParser>>, + Single<WithoutArgs<ProcMacroAttributeParser>>, + Single<WithoutArgs<ProcMacroParser>>, Single<WithoutArgs<PubTransparentParser>>, Single<WithoutArgs<SpecializationTraitParser>>, Single<WithoutArgs<StdInternalSymbolParser>>, diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 42b7e0e06d1..09f5e6f6efc 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -1,11 +1,13 @@ -use std::mem; +use std::{mem, slice}; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; -use rustc_ast::{self as ast, NodeId, attr}; +use rustc_ast::{self as ast, HasNodeId, NodeId, attr}; use rustc_ast_pretty::pprust; +use rustc_attr_data_structures::AttributeKind; +use rustc_attr_parsing::AttributeParser; use rustc_errors::DiagCtxtHandle; -use rustc_expand::base::{ExtCtxt, ResolverExpand, parse_macro_name_and_helper_attrs}; +use rustc_expand::base::{ExtCtxt, ResolverExpand}; use rustc_expand::expand::{AstFragment, ExpansionConfig}; use rustc_feature::Features; use rustc_session::Session; @@ -22,7 +24,7 @@ struct ProcMacroDerive { trait_name: Symbol, function_ident: Ident, span: Span, - attrs: Vec<Symbol>, + attrs: ThinVec<Symbol>, } struct ProcMacroDef { @@ -41,6 +43,7 @@ struct CollectProcMacros<'a> { macros: Vec<ProcMacro>, in_root: bool, dcx: DiagCtxtHandle<'a>, + session: &'a Session, source_map: &'a SourceMap, is_proc_macro_crate: bool, is_test_crate: bool, @@ -63,6 +66,7 @@ pub fn inject( macros: Vec::new(), in_root: true, dcx, + session: sess, source_map: sess.source_map(), is_proc_macro_crate, is_test_crate, @@ -98,8 +102,18 @@ impl<'a> CollectProcMacros<'a> { function_ident: Ident, attr: &'a ast::Attribute, ) { - let Some((trait_name, proc_attrs)) = - parse_macro_name_and_helper_attrs(self.dcx, attr, "derive") + let Some(rustc_hir::Attribute::Parsed(AttributeKind::ProcMacroDerive { + trait_name, + helper_attrs, + .. + })) = AttributeParser::parse_limited( + self.session, + slice::from_ref(attr), + sym::proc_macro_derive, + item.span, + item.node_id(), + None, + ) else { return; }; @@ -110,7 +124,7 @@ impl<'a> CollectProcMacros<'a> { span: item.span, trait_name, function_ident, - attrs: proc_attrs, + attrs: helper_attrs, })); } else { let msg = if !self.in_root { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index fcc0d378f06..7b27e496986 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -382,26 +382,16 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let width = size.bits(); let llty = self.type_ix(width); match name { - sym::ctlz | sym::cttz => { - let y = self.const_bool(false); - let ret = self.call_intrinsic( - format!("llvm.{name}"), - &[llty], - &[args[0].immediate(), y], - ); - - self.intcast(ret, result.layout.llvm_type(self), false) - } - sym::ctlz_nonzero => { - let y = self.const_bool(true); - let ret = - self.call_intrinsic("llvm.ctlz", &[llty], &[args[0].immediate(), y]); - self.intcast(ret, result.layout.llvm_type(self), false) - } - sym::cttz_nonzero => { - let y = self.const_bool(true); + sym::ctlz | sym::ctlz_nonzero | sym::cttz | sym::cttz_nonzero => { + let y = + self.const_bool(name == sym::ctlz_nonzero || name == sym::cttz_nonzero); + let llvm_name = if name == sym::ctlz || name == sym::ctlz_nonzero { + "llvm.ctlz" + } else { + "llvm.cttz" + }; let ret = - self.call_intrinsic("llvm.cttz", &[llty], &[args[0].immediate(), y]); + self.call_intrinsic(llvm_name, &[llty], &[args[0].immediate(), y]); self.intcast(ret, result.layout.llvm_type(self), false) } sym::ctpop => { diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 89d6e62834d..5a53670c865 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -1,26 +1,8 @@ -expand_arg_not_attributes = - second argument must be `attributes` - -expand_attr_no_arguments = - attribute must have either one or two arguments - -expand_attribute_meta_item = - attribute must be a meta item, not a literal - -expand_attribute_single_word = - attribute must only be a single word - expand_attributes_on_expressions_experimental = attributes on expressions are experimental .help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//` .help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !` -expand_attributes_wrong_form = - attribute must be of form: `attributes(foo, bar)` - -expand_cannot_be_name_of_macro = - `{$trait_ident}` cannot be a name of {$macro_type} macro - expand_collapse_debuginfo_illegal = illegal value for attribute #[collapse_debuginfo(no|external|yes)] @@ -71,9 +53,6 @@ expand_glob_delegation_outside_impls = expand_glob_delegation_traitless_qpath = qualified path without a trait in glob delegation -expand_helper_attribute_name_invalid = - `{$name}` cannot be a name of derive helper attribute - expand_incomplete_parse = macro expansion ignores {$descr} and any tokens following .label = caused by the macro expansion here @@ -165,12 +144,6 @@ expand_mve_unrecognized_var = expand_non_inline_modules_in_proc_macro_input_are_unstable = non-inline modules in proc macro input are unstable -expand_not_a_meta_item = - not a meta item - -expand_only_one_word = - must only be one word - expand_proc_macro_back_compat = using an old version of `{$crate_name}` .note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 44a99aa6ea0..c01320fc644 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -861,7 +861,7 @@ impl SyntaxExtension { /// | (unspecified) | no | if-ext | if-ext | yes | /// | external | no | if-ext | if-ext | yes | /// | yes | yes | yes | yes | yes | - fn get_collapse_debuginfo(sess: &Session, attrs: &[impl AttributeExt], ext: bool) -> bool { + fn get_collapse_debuginfo(sess: &Session, attrs: &[hir::Attribute], ext: bool) -> bool { let flag = sess.opts.cg.collapse_macro_debuginfo; let attr = ast::attr::find_by_name(attrs, sym::collapse_debuginfo) .and_then(|attr| { @@ -872,7 +872,7 @@ impl SyntaxExtension { .ok() }) .unwrap_or_else(|| { - if ast::attr::contains_name(attrs, sym::rustc_builtin_macro) { + if find_attr!(attrs, AttributeKind::RustcBuiltinMacro { .. }) { CollapseMacroDebuginfo::Yes } else { CollapseMacroDebuginfo::Unspecified @@ -915,16 +915,18 @@ impl SyntaxExtension { let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local); tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe); - let (builtin_name, helper_attrs) = ast::attr::find_by_name(attrs, sym::rustc_builtin_macro) - .map(|attr| { - // Override `helper_attrs` passed above if it's a built-in macro, - // marking `proc_macro_derive` macros as built-in is not a realistic use case. - parse_macro_name_and_helper_attrs(sess.dcx(), attr, "built-in").map_or_else( - || (Some(name), Vec::new()), - |(name, helper_attrs)| (Some(name), helper_attrs), - ) - }) - .unwrap_or_else(|| (None, helper_attrs)); + let (builtin_name, helper_attrs) = match find_attr!(attrs, AttributeKind::RustcBuiltinMacro { builtin_name, helper_attrs, .. } => (builtin_name, helper_attrs)) + { + // Override `helper_attrs` passed above if it's a built-in macro, + // marking `proc_macro_derive` macros as built-in is not a realistic use case. + Some((Some(name), helper_attrs)) => { + (Some(*name), helper_attrs.iter().copied().collect()) + } + Some((None, _)) => (Some(name), Vec::new()), + + // Not a built-in macro + None => (None, helper_attrs), + }; let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability); @@ -1141,7 +1143,7 @@ pub trait ResolverExpand { /// Names of specific methods to which glob delegation expands. fn glob_delegation_suffixes( - &mut self, + &self, trait_def_id: DefId, impl_def_id: LocalDefId, ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>; @@ -1390,80 +1392,6 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe } } -pub fn parse_macro_name_and_helper_attrs( - dcx: DiagCtxtHandle<'_>, - attr: &impl AttributeExt, - macro_type: &str, -) -> Option<(Symbol, Vec<Symbol>)> { - // Once we've located the `#[proc_macro_derive]` attribute, verify - // that it's of the form `#[proc_macro_derive(Foo)]` or - // `#[proc_macro_derive(Foo, attributes(A, ..))]` - let list = attr.meta_item_list()?; - let ([trait_attr] | [trait_attr, _]) = list.as_slice() else { - dcx.emit_err(errors::AttrNoArguments { span: attr.span() }); - return None; - }; - let Some(trait_attr) = trait_attr.meta_item() else { - dcx.emit_err(errors::NotAMetaItem { span: trait_attr.span() }); - return None; - }; - let trait_ident = match trait_attr.ident() { - Some(trait_ident) if trait_attr.is_word() => trait_ident, - _ => { - dcx.emit_err(errors::OnlyOneWord { span: trait_attr.span }); - return None; - } - }; - - if !trait_ident.name.can_be_raw() { - dcx.emit_err(errors::CannotBeNameOfMacro { - span: trait_attr.span, - trait_ident, - macro_type, - }); - } - - let attributes_attr = list.get(1); - let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr { - if !attr.has_name(sym::attributes) { - dcx.emit_err(errors::ArgumentNotAttributes { span: attr.span() }); - } - attr.meta_item_list() - .unwrap_or_else(|| { - dcx.emit_err(errors::AttributesWrongForm { span: attr.span() }); - &[] - }) - .iter() - .filter_map(|attr| { - let Some(attr) = attr.meta_item() else { - dcx.emit_err(errors::AttributeMetaItem { span: attr.span() }); - return None; - }; - - let ident = match attr.ident() { - Some(ident) if attr.is_word() => ident, - _ => { - dcx.emit_err(errors::AttributeSingleWord { span: attr.span }); - return None; - } - }; - if !ident.name.can_be_raw() { - dcx.emit_err(errors::HelperAttributeNameInvalid { - span: attr.span, - name: ident, - }); - } - - Some(ident.name) - }) - .collect() - } else { - Vec::new() - }; - - Some((trait_ident.name, proc_attrs)) -} - /// If this item looks like a specific enums from `rental`, emit a fatal error. /// See #73345 and #83125 for more details. /// FIXME(#73933): Remove this eventually. diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 3ac5d213053..fd1391a554a 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -79,72 +79,6 @@ pub(crate) struct MacroBodyStability { } #[derive(Diagnostic)] -#[diag(expand_attr_no_arguments)] -pub(crate) struct AttrNoArguments { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_not_a_meta_item)] -pub(crate) struct NotAMetaItem { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_only_one_word)] -pub(crate) struct OnlyOneWord { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_cannot_be_name_of_macro)] -pub(crate) struct CannotBeNameOfMacro<'a> { - #[primary_span] - pub span: Span, - pub trait_ident: Ident, - pub macro_type: &'a str, -} - -#[derive(Diagnostic)] -#[diag(expand_arg_not_attributes)] -pub(crate) struct ArgumentNotAttributes { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_attributes_wrong_form)] -pub(crate) struct AttributesWrongForm { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_attribute_meta_item)] -pub(crate) struct AttributeMetaItem { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_attribute_single_word)] -pub(crate) struct AttributeSingleWord { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_helper_attribute_name_invalid)] -pub(crate) struct HelperAttributeNameInvalid { - #[primary_span] - pub span: Span, - pub name: Ident, -} - -#[derive(Diagnostic)] #[diag(expand_feature_removed, code = E0557)] #[note] pub(crate) struct FeatureRemoved<'a> { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e83f6a1df72..96501844264 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1363,6 +1363,17 @@ impl AttributeExt for Attribute { _ => None, } } + + fn is_proc_macro_attr(&self) -> bool { + matches!( + self, + Attribute::Parsed( + AttributeKind::ProcMacro(..) + | AttributeKind::ProcMacroAttribute(..) + | AttributeKind::ProcMacroDerive { .. } + ) + ) + } } // FIXME(fn_delegation): use function delegation instead of manually forwarding diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index bb1de5bcfc3..6e63ce31024 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -767,7 +767,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), DefKind::Static { .. } => { check_static_inhabited(tcx, def_id); check_static_linkage(tcx, def_id); - res = res.and(wfcheck::check_static_item(tcx, def_id)); + let ty = tcx.type_of(def_id).instantiate_identity(); + res = res.and(wfcheck::check_static_item( + tcx, def_id, ty, /* should_check_for_sync */ true, + )); } DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)), _ => unreachable!(), diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 14ec82ede1c..a62efed13bc 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1180,12 +1180,13 @@ fn check_item_fn( } #[instrument(level = "debug", skip(tcx))] -pub(super) fn check_static_item( - tcx: TyCtxt<'_>, +pub(crate) fn check_static_item<'tcx>( + tcx: TyCtxt<'tcx>, item_id: LocalDefId, + ty: Ty<'tcx>, + should_check_for_sync: bool, ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item_id, |wfcx| { - let ty = tcx.type_of(item_id).instantiate_identity(); let span = tcx.ty_span(item_id); let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); @@ -1212,9 +1213,9 @@ pub(super) fn check_static_item( } // Ensure that the end result is `Sync` in a non-thread local `static`. - let should_check_for_sync = tcx.static_mutability(item_id.to_def_id()) - == Some(hir::Mutability::Not) + let should_check_for_sync = should_check_for_sync && !is_foreign_item + && tcx.static_mutability(item_id.to_def_id()) == Some(hir::Mutability::Not) && !tcx.is_thread_local_static(item_id.to_def_id()); if should_check_for_sync { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 902a2e15dff..22fb02714dd 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -14,6 +14,7 @@ use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; use super::{HirPlaceholderCollector, ItemCtxt, bad_placeholder}; +use crate::check::wfcheck::check_static_item; use crate::errors::TypeofReservedKeywordUsed; use crate::hir_ty_lowering::HirTyLowerer; @@ -217,7 +218,15 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ "static variable", ) } else { - icx.lower_ty(ty) + let ty = icx.lower_ty(ty); + // MIR relies on references to statics being scalars. + // Verify that here to avoid ill-formed MIR. + // We skip the `Sync` check to avoid cycles for type-alias-impl-trait, + // relying on the fact that non-Sync statics don't ICE the rest of the compiler. + match check_static_item(tcx, def_id, ty, /* should_check_for_sync */ false) { + Ok(()) => ty, + Err(guar) => Ty::new_error(tcx, guar), + } } } ItemKind::Const(ident, _, ty, body_id) => { @@ -275,7 +284,17 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_fn_def(tcx, def_id.to_def_id(), args) } - ForeignItemKind::Static(t, _, _) => icx.lower_ty(t), + ForeignItemKind::Static(ty, _, _) => { + let ty = icx.lower_ty(ty); + // MIR relies on references to statics being scalars. + // Verify that here to avoid ill-formed MIR. + // We skip the `Sync` check to avoid cycles for type-alias-impl-trait, + // relying on the fact that non-Sync statics don't ICE the rest of the compiler. + match check_static_item(tcx, def_id, ty, /* should_check_for_sync */ false) { + Ok(()) => ty, + Err(guar) => Ty::new_error(tcx, guar), + } + } ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()), }, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 24a3a6e0c4f..ffb33c67f8a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -5,7 +5,7 @@ use std::io::{Read, Seek, Write}; use std::path::{Path, PathBuf}; use std::sync::Arc; -use rustc_attr_data_structures::EncodeCrossCrate; +use rustc_attr_data_structures::{AttributeKind, EncodeCrossCrate, find_attr}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::{Mmap, MmapMut}; use rustc_data_structures::sync::{join, par_for_each_in}; @@ -1965,18 +1965,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Proc-macros may have attributes like `#[allow_internal_unstable]`, // so downstream crates need access to them. let attrs = tcx.hir_attrs(proc_macro); - let macro_kind = if ast::attr::contains_name(attrs, sym::proc_macro) { + let macro_kind = if find_attr!(attrs, AttributeKind::ProcMacro(..)) { MacroKind::Bang - } else if ast::attr::contains_name(attrs, sym::proc_macro_attribute) { + } else if find_attr!(attrs, AttributeKind::ProcMacroAttribute(..)) { MacroKind::Attr - } else if let Some(attr) = ast::attr::find_by_name(attrs, sym::proc_macro_derive) { - // This unwrap chain should have been checked by the proc-macro harness. - name = attr.meta_item_list().unwrap()[0] - .meta_item() - .unwrap() - .ident() - .unwrap() - .name; + } else if let Some(trait_name) = find_attr!(attrs, AttributeKind::ProcMacroDerive { trait_name, ..} => trait_name) + { + name = *trait_name; MacroKind::Derive } else { bug!("Unknown proc-macro type for item {:?}", id); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 66d1335e763..6f21160d1f6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1041,11 +1041,13 @@ const NUM_PREINTERNED_TY_VARS: u32 = 100; const NUM_PREINTERNED_FRESH_TYS: u32 = 20; const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3; const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3; +const NUM_PREINTERNED_ANON_BOUND_TYS_I: u32 = 3; +const NUM_PREINTERNED_ANON_BOUND_TYS_V: u32 = 20; // This number may seem high, but it is reached in all but the smallest crates. const NUM_PREINTERNED_RE_VARS: u32 = 500; -const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2; -const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20; +const NUM_PREINTERNED_ANON_RE_BOUNDS_I: u32 = 3; +const NUM_PREINTERNED_ANON_RE_BOUNDS_V: u32 = 20; pub struct CommonTypes<'tcx> { pub unit: Ty<'tcx>, @@ -1088,6 +1090,11 @@ pub struct CommonTypes<'tcx> { /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`. pub fresh_float_tys: Vec<Ty<'tcx>>, + + /// Pre-interned values of the form: + /// `Bound(DebruijnIndex(i), BoundTy { var: v, kind: BoundTyKind::Anon})` + /// for small values of `i` and `v`. + pub anon_bound_tys: Vec<Vec<Ty<'tcx>>>, } pub struct CommonLifetimes<'tcx> { @@ -1101,9 +1108,9 @@ pub struct CommonLifetimes<'tcx> { pub re_vars: Vec<Region<'tcx>>, /// Pre-interned values of the form: - /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })` + /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BoundRegionKind::Anon })` /// for small values of `i` and `v`. - pub re_late_bounds: Vec<Vec<Region<'tcx>>>, + pub anon_re_bounds: Vec<Vec<Region<'tcx>>>, } pub struct CommonConsts<'tcx> { @@ -1131,6 +1138,19 @@ impl<'tcx> CommonTypes<'tcx> { let fresh_float_tys: Vec<_> = (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect(); + let anon_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_I) + .map(|i| { + (0..NUM_PREINTERNED_ANON_BOUND_TYS_V) + .map(|v| { + mk(ty::Bound( + ty::DebruijnIndex::from(i), + ty::BoundTy { var: ty::BoundVar::from(v), kind: ty::BoundTyKind::Anon }, + )) + }) + .collect() + }) + .collect(); + CommonTypes { unit: mk(Tuple(List::empty())), bool: mk(Bool), @@ -1161,6 +1181,7 @@ impl<'tcx> CommonTypes<'tcx> { fresh_tys, fresh_int_tys, fresh_float_tys, + anon_bound_tys, } } } @@ -1176,9 +1197,9 @@ impl<'tcx> CommonLifetimes<'tcx> { let re_vars = (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect(); - let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I) + let anon_re_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_I) .map(|i| { - (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V) + (0..NUM_PREINTERNED_ANON_RE_BOUNDS_V) .map(|v| { mk(ty::ReBound( ty::DebruijnIndex::from(i), @@ -1196,7 +1217,7 @@ impl<'tcx> CommonLifetimes<'tcx> { re_static: mk(ty::ReStatic), re_erased: mk(ty::ReErased), re_vars, - re_late_bounds, + anon_re_bounds, } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a7cde2ad485..4c95f0748d3 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2024,7 +2024,10 @@ impl<'tcx> TyCtxt<'tcx> { && let Some(def_id) = def_id.as_local() && let outer = self.def_span(def_id).ctxt().outer_expn_data() && matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _)) - && self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro) + && find_attr!( + self.get_all_attrs(outer.macro_def_id.unwrap()), + AttributeKind::RustcBuiltinMacro { .. } + ) { true } else { diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 51be93d9a72..5cf96072177 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -54,7 +54,7 @@ impl<'tcx> Region<'tcx> { ) -> Region<'tcx> { // Use a pre-interned one when possible. if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region - && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize()) + && let Some(inner) = tcx.lifetimes.anon_re_bounds.get(debruijn.as_usize()) && let Some(re) = inner.get(var.as_usize()).copied() { re diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8bb3b3f1263..4569596cfbe 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -485,7 +485,15 @@ impl<'tcx> Ty<'tcx> { index: ty::DebruijnIndex, bound_ty: ty::BoundTy, ) -> Ty<'tcx> { - Ty::new(tcx, Bound(index, bound_ty)) + // Use a pre-interned one when possible. + if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty + && let Some(inner) = tcx.types.anon_bound_tys.get(index.as_usize()) + && let Some(ty) = inner.get(var.as_usize()).copied() + { + ty + } else { + Ty::new(tcx, Bound(index, bound_ty)) + } } #[inline] diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4b524bb2bd2..0b329cc38b0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -130,6 +130,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> { for attr in attrs { let mut style = None; match attr { + Attribute::Parsed(AttributeKind::ProcMacro(_)) => { + self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike) + } + Attribute::Parsed(AttributeKind::ProcMacroAttribute(_)) => { + self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute); + } + Attribute::Parsed(AttributeKind::ProcMacroDerive { span: attr_span, .. }) => { + self.check_generic_attr( + hir_id, + sym::proc_macro_derive, + *attr_span, + target, + Target::Fn, + ); + self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) + } Attribute::Parsed( AttributeKind::SkipDuringMethodDispatch { span: attr_span, .. } | AttributeKind::Coinductive(attr_span) @@ -275,6 +291,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::MacroTransparency(_) | AttributeKind::Pointee(..) | AttributeKind::Dummy + | AttributeKind::RustcBuiltinMacro { .. } | AttributeKind::OmitGdbPrettyPrinterSection, ) => { /* do nothing */ } Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => { @@ -373,16 +390,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::should_panic, ..] => { self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn) } - [sym::proc_macro, ..] => { - self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike) - } - [sym::proc_macro_attribute, ..] => { - self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute); - } - [sym::proc_macro_derive, ..] => { - self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn); - self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) - } [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index ac64385d664..b15b478a6be 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -23,9 +23,9 @@ use rustc_hir::def::{self, *}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::LoadedMacro; -use rustc_middle::bug; use rustc_middle::metadata::ModChild; use rustc_middle::ty::{Feed, Visibility}; +use rustc_middle::{bug, span_bug}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::{Ident, Span, Symbol, kw, sym}; use thin_vec::ThinVec; @@ -46,30 +46,59 @@ type Res = def::Res<NodeId>; impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - pub(crate) fn define_binding( + pub(crate) fn define_binding_local( &mut self, parent: Module<'ra>, ident: Ident, ns: Namespace, binding: NameBinding<'ra>, ) { - if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) { + if let Err(old_binding) = self.try_define_local(parent, ident, ns, binding, false) { self.report_conflict(parent, ident, ns, old_binding, binding); } } - fn define( + fn define_local( &mut self, parent: Module<'ra>, ident: Ident, ns: Namespace, res: Res, - vis: Visibility<impl Into<DefId>>, + vis: Visibility, span: Span, expn_id: LocalExpnId, ) { let binding = self.arenas.new_res_binding(res, vis.to_def_id(), span, expn_id); - self.define_binding(parent, ident, ns, binding) + self.define_binding_local(parent, ident, ns, binding); + } + + fn define_extern( + &self, + parent: Module<'ra>, + ident: Ident, + ns: Namespace, + res: Res, + vis: Visibility<DefId>, + span: Span, + expn_id: LocalExpnId, + ) { + let binding = self.arenas.new_res_binding(res, vis, span, expn_id); + // Even if underscore names cannot be looked up, we still need to add them to modules, + // because they can be fetched by glob imports from those modules, and bring traits + // into scope both directly and through glob imports. + let key = BindingKey::new_disambiguated(ident, ns, || { + parent.underscore_disambiguator.update(|d| d + 1); + parent.underscore_disambiguator.get() + }); + if self + .resolution_or_default(parent, key) + .borrow_mut() + .non_glob_binding + .replace(binding) + .is_some() + { + span_bug!(span, "an external binding was already defined"); + } } /// Walks up the tree of definitions starting at `def_id`, @@ -192,7 +221,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { visitor.parent_scope.macro_rules } - pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'ra>) { + pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) { for child in self.tcx.module_children(module.def_id()) { let parent_scope = ParentScope::module(module, self); self.build_reduced_graph_for_external_crate_res(child, parent_scope) @@ -201,7 +230,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Builds the reduced graph for a single item in an external crate. fn build_reduced_graph_for_external_crate_res( - &mut self, + &self, child: &ModChild, parent_scope: ParentScope<'ra>, ) { @@ -232,7 +261,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _, ) | Res::PrimTy(..) - | Res::ToolMod => self.define(parent, ident, TypeNS, res, vis, span, expansion), + | Res::ToolMod => self.define_extern(parent, ident, TypeNS, res, vis, span, expansion), Res::Def( DefKind::Fn | DefKind::AssocFn @@ -241,9 +270,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { | DefKind::AssocConst | DefKind::Ctor(..), _, - ) => self.define(parent, ident, ValueNS, res, vis, span, expansion), + ) => self.define_extern(parent, ident, ValueNS, res, vis, span, expansion), Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { - self.define(parent, ident, MacroNS, res, vis, span, expansion) + self.define_extern(parent, ident, MacroNS, res, vis, span, expansion) } Res::Def( DefKind::TyParam @@ -711,7 +740,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let expansion = parent_scope.expansion; // Define a name in the type namespace if it is not anonymous. - self.r.define(parent, ident, TypeNS, adt_res, adt_vis, adt_span, expansion); + self.r.define_local(parent, ident, TypeNS, adt_res, adt_vis, adt_span, expansion); self.r.feed_visibility(feed, adt_vis); let def_id = feed.key(); @@ -763,7 +792,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } ItemKind::Mod(_, ident, ref mod_kind) => { - self.r.define(parent, ident, TypeNS, res, vis, sp, expansion); + self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind { self.r.mods_with_parse_errors.insert(def_id); @@ -782,10 +811,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::Const(box ConstItem { ident, .. }) | ItemKind::Delegation(box Delegation { ident, .. }) | ItemKind::Static(box StaticItem { ident, .. }) => { - self.r.define(parent, ident, ValueNS, res, vis, sp, expansion); + self.r.define_local(parent, ident, ValueNS, res, vis, sp, expansion); } ItemKind::Fn(box Fn { ident, .. }) => { - self.r.define(parent, ident, ValueNS, res, vis, sp, expansion); + self.r.define_local(parent, ident, ValueNS, res, vis, sp, expansion); // Functions introducing procedural macros reserve a slot // in the macro namespace as well (see #52225). @@ -794,11 +823,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // These items live in the type namespace. ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => { - self.r.define(parent, ident, TypeNS, res, vis, sp, expansion); + self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); } ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => { - self.r.define(parent, ident, TypeNS, res, vis, sp, expansion); + self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); self.parent_scope.module = self.r.new_local_module( Some(parent), @@ -850,7 +879,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let feed = self.r.feed(ctor_node_id); let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); - self.r.define(parent, ident, ValueNS, ctor_res, ctor_vis, sp, expansion); + self.r.define_local(parent, ident, ValueNS, ctor_res, ctor_vis, sp, expansion); self.r.feed_visibility(feed, ctor_vis); // We need the field visibility spans also for the constructor for E0603. self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields()); @@ -974,7 +1003,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ); } } - self.r.define_binding(parent, ident, TypeNS, imported_binding); + self.r.define_binding_local(parent, ident, TypeNS, imported_binding); } /// Constructs the reduced graph for one foreign item. @@ -991,7 +1020,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); - self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion); + self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); self.r.feed_visibility(feed, vis); } @@ -1074,7 +1103,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { if let Some(span) = import_all { let import = macro_use_import(self, span, false); self.r.potentially_unused_imports.push(import); - module.for_each_child(self, |this, ident, ns, binding| { + module.for_each_child_mut(self, |this, ident, ns, binding| { if ns == MacroNS { let import = if this.r.is_accessible_from(binding.vis, this.parent_scope.module) { @@ -1239,7 +1268,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { }); self.r.import_use_map.insert(import, Used::Other); let import_binding = self.r.import(binding, import); - self.r.define_binding(self.r.graph_root, ident, MacroNS, import_binding); + self.r.define_binding_local(self.r.graph_root, ident, MacroNS, import_binding); } else { self.r.check_reserved_macro_name(ident, res); self.insert_unused_macro(ident, def_id, item.id); @@ -1267,7 +1296,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { if !vis.is_public() { self.insert_unused_macro(ident, def_id, item.id); } - self.r.define(module, ident, MacroNS, res, vis, span, expansion); + self.r.define_local(module, ident, MacroNS, res, vis, span, expansion); self.r.feed_visibility(feed, vis); self.parent_scope.macro_rules } @@ -1403,7 +1432,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { if ctxt == AssocCtxt::Trait { let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; - self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion); + self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) && ident.name != kw::Underscore { @@ -1491,7 +1520,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let feed = self.r.feed(variant.id); let def_id = feed.key(); let vis = self.resolve_visibility(&variant.vis); - self.r.define(parent, ident, TypeNS, self.res(def_id), vis, variant.span, expn_id); + self.r.define_local(parent, ident, TypeNS, self.res(def_id), vis, variant.span, expn_id); self.r.feed_visibility(feed, vis); // If the variant is marked as non_exhaustive then lower the visibility to within the crate. @@ -1507,7 +1536,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let feed = self.r.feed(ctor_node_id); let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); - self.r.define(parent, ident, ValueNS, ctor_res, ctor_vis, variant.span, expn_id); + self.r.define_local(parent, ident, ValueNS, ctor_res, ctor_vis, variant.span, expn_id); self.r.feed_visibility(feed, ctor_vis); } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 13cf700fbb2..3af69b28780 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -523,7 +523,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } pub(crate) fn add_module_candidates( - &mut self, + &self, module: Module<'ra>, names: &mut Vec<TypoSuggestion>, filter_fn: &impl Fn(Res) -> bool, @@ -1150,7 +1150,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn lookup_import_candidates_from_module<FilterFn>( - &mut self, + &self, lookup_ident: Ident, namespace: Namespace, parent_scope: &ParentScope<'ra>, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index f2de57b4d50..156df45147f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -334,8 +334,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } /// Define the name or return the existing binding if there is a collision. - /// `update` indicates if the definition is a redefinition of an existing binding. - pub(crate) fn try_define( + pub(crate) fn try_define_local( &mut self, module: Module<'ra>, ident: Ident, @@ -353,7 +352,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { module.underscore_disambiguator.update(|d| d + 1); module.underscore_disambiguator.get() }); - self.update_resolution(module, key, warn_ambiguity, |this, resolution| { + self.update_local_resolution(module, key, warn_ambiguity, |this, resolution| { if let Some(old_binding) = resolution.best_binding() { if res == Res::Err && old_binding.res() != Res::Err { // Do not override real bindings with `Res::Err`s from error recovery. @@ -456,7 +455,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. - fn update_resolution<T, F>( + fn update_local_resolution<T, F>( &mut self, module: Module<'ra>, key: BindingKey, @@ -497,7 +496,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, *import); - let _ = self.try_define( + let _ = self.try_define_local( import.parent_scope.module, ident, key.ns, @@ -523,11 +522,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { let module = import.parent_scope.module; - let _ = this.try_define(module, target, ns, dummy_binding, false); + let _ = this.try_define_local(module, target, ns, dummy_binding, false); // Don't remove underscores from `single_imports`, they were never added. if target.name != kw::Underscore { let key = BindingKey::new(target, ns); - this.update_resolution(module, key, false, |_, resolution| { + this.update_local_resolution(module, key, false, |_, resolution| { resolution.single_imports.swap_remove(&import); }) } @@ -902,14 +901,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // We need the `target`, `source` can be extracted. let imported_binding = this.import(binding, import); - this.define_binding(parent, target, ns, imported_binding); + this.define_binding_local(parent, target, ns, imported_binding); PendingBinding::Ready(Some(imported_binding)) } Err(Determinacy::Determined) => { // Don't remove underscores from `single_imports`, they were never added. if target.name != kw::Underscore { let key = BindingKey::new(target, ns); - this.update_resolution(parent, key, false, |_, resolution| { + this.update_local_resolution(parent, key, false, |_, resolution| { resolution.single_imports.swap_remove(&import); }); } @@ -1516,7 +1515,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .resolution(import.parent_scope.module, key) .and_then(|r| r.binding()) .is_some_and(|binding| binding.warn_ambiguity_recursive()); - let _ = self.try_define( + let _ = self.try_define_local( import.parent_scope.module, key.ident, key.ns, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 203827a9e1a..0f0babd4904 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2633,7 +2633,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { false } - fn find_module(&mut self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> { + fn find_module(&self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> { let mut result = None; let mut seen_modules = FxHashSet::default(); let root_did = self.r.graph_root.def_id(); @@ -2690,7 +2690,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { result } - fn collect_enum_ctors(&mut self, def_id: DefId) -> Option<Vec<(Path, DefId, CtorKind)>> { + fn collect_enum_ctors(&self, def_id: DefId) -> Option<Vec<(Path, DefId, CtorKind)>> { self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| { let mut variants = Vec::new(); enum_module.for_each_child(self.r, |_, ident, _, name_binding| { @@ -2707,7 +2707,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { /// Adds a suggestion for using an enum's variant when an enum is used instead. fn suggest_using_enum_variant( - &mut self, + &self, err: &mut Diag<'_>, source: PathSource<'_, '_, '_>, def_id: DefId, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index fe7ed07c46e..8115b87dcae 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -656,11 +656,23 @@ impl<'ra> ModuleData<'ra> { } impl<'ra> Module<'ra> { - fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F) - where - R: AsMut<Resolver<'ra, 'tcx>>, - F: FnMut(&mut R, Ident, Namespace, NameBinding<'ra>), - { + fn for_each_child<'tcx, R: AsRef<Resolver<'ra, 'tcx>>>( + self, + resolver: &R, + mut f: impl FnMut(&R, Ident, Namespace, NameBinding<'ra>), + ) { + for (key, name_resolution) in resolver.as_ref().resolutions(self).borrow().iter() { + if let Some(binding) = name_resolution.borrow().best_binding() { + f(resolver, key.ident, key.ns, binding); + } + } + } + + fn for_each_child_mut<'tcx, R: AsMut<Resolver<'ra, 'tcx>>>( + self, + resolver: &mut R, + mut f: impl FnMut(&mut R, Ident, Namespace, NameBinding<'ra>), + ) { for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { if let Some(binding) = name_resolution.borrow().best_binding() { f(resolver, key.ident, key.ns, binding); @@ -669,10 +681,7 @@ impl<'ra> Module<'ra> { } /// This modifies `self` in place. The traits will be stored in `self.traits`. - fn ensure_traits<'tcx, R>(self, resolver: &mut R) - where - R: AsMut<Resolver<'ra, 'tcx>>, - { + fn ensure_traits<'tcx>(self, resolver: &impl AsRef<Resolver<'ra, 'tcx>>) { let mut traits = self.traits.borrow_mut(); if traits.is_none() { let mut collected_traits = Vec::new(); @@ -681,7 +690,7 @@ impl<'ra> Module<'ra> { return; } if let Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) = binding.res() { - collected_traits.push((name, binding, r.as_mut().get_module(def_id))) + collected_traits.push((name, binding, r.as_ref().get_module(def_id))) } }); *traits = Some(collected_traits.into_boxed_slice()); @@ -1340,6 +1349,12 @@ impl<'ra, 'tcx> AsMut<Resolver<'ra, 'tcx>> for Resolver<'ra, 'tcx> { } } +impl<'ra, 'tcx> AsRef<Resolver<'ra, 'tcx>> for Resolver<'ra, 'tcx> { + fn as_ref(&self) -> &Resolver<'ra, 'tcx> { + self + } +} + impl<'tcx> Resolver<'_, 'tcx> { fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> { self.opt_feed(node).map(|f| f.key()) @@ -1861,7 +1876,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We don't reject trait aliases (`trait_module == None`) because we don't have access to their // associated items. fn trait_may_have_item( - &mut self, + &self, trait_module: Option<Module<'ra>>, assoc_item: Option<(Symbol, Namespace)>, ) -> bool { @@ -1893,7 +1908,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { import_ids } - fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> { + fn resolutions(&self, module: Module<'ra>) -> &'ra Resolutions<'ra> { if module.populate_on_access.get() { module.populate_on_access.set(false); self.build_reduced_graph_external(module); @@ -1902,7 +1917,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn resolution( - &mut self, + &self, module: Module<'ra>, key: BindingKey, ) -> Option<Ref<'ra, NameResolution<'ra>>> { @@ -1910,7 +1925,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn resolution_or_default( - &mut self, + &self, module: Module<'ra>, key: BindingKey, ) -> &'ra RefCell<NameResolution<'ra>> { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index f0225daa09d..b96d9e7dc8e 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -511,7 +511,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn glob_delegation_suffixes( - &mut self, + &self, trait_def_id: DefId, impl_def_id: LocalDefId, ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate> { diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index c3080875da8..97d1d9c2d2a 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -322,6 +322,7 @@ impl ExpnId { /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than /// `expn_id.is_descendant_of(ctxt.outer_expn())`. + #[inline] pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool { HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt))) } @@ -394,6 +395,7 @@ impl HygieneData { } } + #[inline] fn with<R>(f: impl FnOnce(&mut HygieneData) -> R) -> R { with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut())) } @@ -406,6 +408,7 @@ impl HygieneData { } } + #[inline] fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData { self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID") } @@ -437,23 +440,28 @@ impl HygieneData { } } + #[inline] fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque } + #[inline] fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque } + #[inline] fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId { self.syntax_context_data[ctxt.0 as usize].outer_expn } + #[inline] fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) { let data = &self.syntax_context_data[ctxt.0 as usize]; (data.outer_expn, data.outer_transparency) } + #[inline] fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].parent } @@ -718,11 +726,13 @@ impl SyntaxContext { SyntaxContext(raw as u32) } + #[inline] fn from_usize(raw: usize) -> SyntaxContext { SyntaxContext(u32::try_from(raw).unwrap()) } /// Extend a syntax context with a given expansion and transparency. + #[inline] pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext { HygieneData::with(|data| data.apply_mark(self, expn_id, transparency)) } @@ -743,10 +753,12 @@ impl SyntaxContext { /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the /// invocation of f that created g1. /// Returns the mark that was removed. + #[inline] pub fn remove_mark(&mut self) -> ExpnId { HygieneData::with(|data| data.remove_mark(self).0) } + #[inline] pub fn marks(self) -> Vec<(ExpnId, Transparency)> { HygieneData::with(|data| data.marks(self)) } @@ -776,11 +788,13 @@ impl SyntaxContext { /// ``` /// This returns the expansion whose definition scope we use to privacy check the resolution, /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope). + #[inline] pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> { HygieneData::with(|data| data.adjust(self, expn_id)) } /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0. + #[inline] pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> { HygieneData::with(|data| { *self = data.normalize_to_macros_2_0(*self); @@ -901,10 +915,12 @@ impl SyntaxContext { HygieneData::with(|data| data.outer_mark(self)) } + #[inline] pub(crate) fn dollar_crate_name(self) -> Symbol { HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name) } + #[inline] pub fn edition(self) -> Edition { HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition) } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 9b0e009b2cd..dbc67da37b5 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -167,6 +167,7 @@ where } } +#[inline] pub fn with_session_globals<R, F>(f: F) -> R where F: FnOnce(&SessionGlobals) -> R, diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index e3c4a793b37..3a00fe89360 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -400,8 +400,12 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>( (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a), (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def == b_def => { - let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?; - Ok(Ty::new_adt(cx, a_def, args)) + Ok(if a_args.is_empty() { + a + } else { + let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?; + if args == a_args { a } else { Ty::new_adt(cx, a_def, args) } + }) } (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(cx, a_id)), @@ -515,8 +519,12 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>( } (ty::FnDef(a_def_id, a_args), ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => { - let args = relation.relate_item_args(a_def_id, a_args, b_args)?; - Ok(Ty::new_fn_def(cx, a_def_id, args)) + Ok(if a_args.is_empty() { + a + } else { + let args = relation.relate_item_args(a_def_id, a_args, b_args)?; + if args == a_args { a } else { Ty::new_fn_def(cx, a_def_id, args) } + }) } (ty::FnPtr(a_sig_tys, a_hdr), ty::FnPtr(b_sig_tys, b_hdr)) => { |
