diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index d2d1285b0756f..969bce7ae20a6 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -191,6 +191,7 @@ pub enum AttributeKind { }, MacroTransparency(Transparency), Repr(ThinVec<(ReprAttr, Span)>), + RustcMacroEdition2021, Stability { stability: Stability, /// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs index bbd3308809c33..c61b44b273de5 100644 --- a/compiler/rustc_attr_data_structures/src/lib.rs +++ b/compiler/rustc_attr_data_structures/src/lib.rs @@ -182,21 +182,18 @@ macro_rules! find_attr { }}; ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{ - fn check_attribute_iterator<'a>(_: &'_ impl IntoIterator) {} - check_attribute_iterator(&$attributes_list); - - let find_attribute = |iter| { + 'done: { for i in $attributes_list { + let i: &rustc_hir::Attribute = i; match i { rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => { - return Some($e); + break 'done Some($e); } _ => {} } } None - }; - find_attribute($attributes_list) + } }}; } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 6ecd6b4d7dbb7..bac111159db53 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -28,6 +28,7 @@ pub(crate) mod cfg; pub(crate) mod confusables; pub(crate) mod deprecation; pub(crate) mod repr; +pub(crate) mod rustc; pub(crate) mod stability; pub(crate) mod transparency; pub(crate) mod util; diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc.rs b/compiler/rustc_attr_parsing/src/attributes/rustc.rs new file mode 100644 index 0000000000000..bdd3bef2834bb --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/rustc.rs @@ -0,0 +1,19 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_span::sym; + +use super::{AcceptContext, SingleAttributeParser}; +use crate::parser::ArgParser; + +pub(crate) struct RustcMacroEdition2021Parser; + +// FIXME(jdonszelmann): make these proper diagnostics +impl SingleAttributeParser for RustcMacroEdition2021Parser { + const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_macro_edition_2021]; + + fn on_duplicate(_cx: &crate::context::AcceptContext<'_>, _first_span: rustc_span::Span) {} + + fn convert(_cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option { + assert!(args.no_args()); + Some(AttributeKind::RustcMacroEdition2021) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 35541bb04bd7b..a68d4578b40f7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -15,6 +15,7 @@ use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInterna use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::repr::ReprParser; +use crate::attributes::rustc::RustcMacroEdition2021Parser; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; @@ -76,6 +77,7 @@ attribute_groups!( // tidy-alphabetical-start Single, Single, + Single, Single, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 40857e0066ee5..2511ae610f8d3 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -661,6 +661,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "`rustc_never_type_options` is used to experiment with never type fallback and work on \ never type stabilization, and will never be stable" ), + rustc_attr!( + rustc_macro_edition_2021, + Normal, + template!(Word), + ErrorFollowing, + EncodeCrossCrate::No, + "makes spans in this macro edition 2021" + ), // ========================================================================== // Internal attributes: Runtime related: diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7100d89ad61a8..a7cbc816b8361 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::{self as ast, Crate, NodeId, attr}; use rustc_ast_pretty::pprust; -use rustc_attr_parsing::StabilityLevel; +use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, StashKey}; use rustc_expand::base::{ @@ -1125,6 +1125,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { edition, ); + // The #[rustc_macro_edition_2021] attribute is used by the pin!() macro + // as a temporary workaround for a regression in expressiveness in Rust 2024. + // See https://github.com/rust-lang/rust/issues/138718. + if find_attr!(attrs.iter(), AttributeKind::RustcMacroEdition2021) { + ext.edition = Edition::Edition2021; + } + if let Some(builtin_name) = ext.builtin_name { // The macro was marked with `#[rustc_builtin_macro]`. if let Some(builtin_macro) = self.builtin_macros.get_mut(&builtin_name) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d8194..31d9ad104386f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1793,6 +1793,7 @@ symbols! { rustc_lint_opt_ty, rustc_lint_query_instability, rustc_lint_untracked_query_information, + rustc_macro_edition_2021, rustc_macro_transparency, rustc_main, rustc_mir, diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 7fcd19f67ee2d..bc097bf198d03 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1943,6 +1943,7 @@ unsafe impl PinCoerceUnsized for *mut T {} #[stable(feature = "pin_macro", since = "1.68.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(unsafe_pin_internals)] +#[cfg_attr(not(bootstrap), rustc_macro_edition_2021)] pub macro pin($value:expr $(,)?) { // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's // review such a hypothetical macro (that any user-code could define): diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs index b3fb06e710d44..a866cf12a3bbf 100644 --- a/library/coretests/tests/pin.rs +++ b/library/coretests/tests/pin.rs @@ -34,6 +34,9 @@ fn pin_const() { } pin_mut_const(); + + // Check that we accept a Rust 2024 $expr. + std::pin::pin!(const { 1 }); } #[allow(unused)] @@ -81,3 +84,14 @@ mod pin_coerce_unsized { arg } } + +#[test] +#[cfg(not(bootstrap))] +fn temp_lifetime() { + // Check that temporary lifetimes work as in Rust 2021. + // Regression test for https://github.com/rust-lang/rust/issues/138596 + match std::pin::pin!(foo(&mut 0)) { + _ => {} + } + async fn foo(_: &mut usize) {} +}