diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index fd0ef8500c6c3..c58050c5db7aa 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -12,8 +12,8 @@ use thin_vec::{ThinVec, thin_vec}; use crate::errors::{ EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition, - EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticDefault, - EiiStaticMultipleImplementations, EiiStaticMutable, + EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticMultipleImplementations, + EiiStaticMutable, }; /// ```rust @@ -86,14 +86,6 @@ fn eii_( let (item_span, foreign_item_name) = match kind { ItemKind::Fn(func) => (func.sig.span, func.ident), ItemKind::Static(stat) => { - // Statics with a default are not supported yet - if let Some(stat_body) = &stat.expr { - ecx.dcx().emit_err(EiiStaticDefault { - span: stat_body.span, - name: path_to_string(&meta_item.path), - }); - return vec![]; - } // Statics must have an explicit name for the eii if meta_item.is_word() { ecx.dcx().emit_err(EiiStaticArgumentRequired { @@ -137,18 +129,16 @@ fn eii_( let mut module_items = Vec::new(); - if let ItemKind::Fn(func) = kind - && func.body.is_some() - { - module_items.push(generate_default_func_impl( - ecx, - &func, - impl_unsafe, - macro_name, - eii_attr_span, - item_span, - foreign_item_name, - )) + if let Some(default_impl) = generate_default_impl( + ecx, + kind, + impl_unsafe, + macro_name, + eii_attr_span, + item_span, + foreign_item_name, + ) { + module_items.push(default_impl); } module_items.push(generate_foreign_item( @@ -220,20 +210,33 @@ fn filter_attrs_for_multiple_eii_attr( .collect() } -fn generate_default_func_impl( +fn generate_default_impl( ecx: &mut ExtCtxt<'_>, - func: &ast::Fn, + item_kind: &ItemKind, impl_unsafe: bool, macro_name: Ident, eii_attr_span: Span, item_span: Span, foreign_item_name: Ident, -) -> Box { +) -> Option> { + match item_kind { + ItemKind::Fn(func) => { + if func.body.is_none() { + return None; + } + } + ItemKind::Static(stat) => { + if stat.expr.is_none() { + return None; + } + } + _ => unreachable!("Target was checked earlier"), + }; + // FIXME: re-add some original attrs let attrs = ThinVec::new(); - let mut default_func = func.clone(); - default_func.eii_impls.push(EiiImpl { + let eii_impl = EiiImpl { node_id: DUMMY_NODE_ID, inner_span: macro_name.span, eii_macro_path: ast::Path::from_ident(macro_name), @@ -253,7 +256,18 @@ fn generate_default_func_impl( ), impl_unsafe, }), - }); + }; + + let mut item_kind = item_kind.clone(); + match &mut item_kind { + ItemKind::Fn(func) => { + func.eii_impls.push(eii_impl); + } + ItemKind::Static(stat) => { + stat.eii_impls.push(eii_impl); + } + _ => unreachable!("Target was checked earlier"), + }; let anon_mod = |span: Span, stmts: ThinVec| { let unit = ecx.ty(item_span, ast::TyKind::Tup(ThinVec::new())); @@ -267,15 +281,12 @@ fn generate_default_func_impl( }; // const _: () = { - // + // // } - anon_mod( + Some(anon_mod( item_span, - thin_vec![ecx.stmt_item( - item_span, - ecx.item(item_span, attrs, ItemKind::Fn(Box::new(default_func))) - ),], - ) + thin_vec![ecx.stmt_item(item_span, ecx.item(item_span, attrs, item_kind))], + )) } /// Generates a foreign item, like @@ -362,6 +373,8 @@ fn generate_foreign_static(mut stat: Box) -> ast::ForeignItemKi stat.safety = ast::Safety::Safe(stat.ident.span); } + stat.expr = None; + ast::ForeignItemKind::Static(stat) } diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index c64d6871269a6..24ce4bda79c45 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1134,14 +1134,6 @@ pub(crate) struct EiiStaticMultipleImplementations { pub span: Span, } -#[derive(Diagnostic)] -#[diag("`#[{$name}]` cannot be used on statics with a value")] -pub(crate) struct EiiStaticDefault { - #[primary_span] - pub span: Span, - pub name: String, -} - #[derive(Diagnostic)] #[diag("`#[{$name}]` requires the name as an explicit argument when used on a static")] pub(crate) struct EiiStaticArgumentRequired { diff --git a/tests/ui/eii/static/auxiliary/decl_with_default.rs b/tests/ui/eii/static/auxiliary/decl_with_default.rs new file mode 100644 index 0000000000000..ba87b35deb457 --- /dev/null +++ b/tests/ui/eii/static/auxiliary/decl_with_default.rs @@ -0,0 +1,5 @@ +#![crate_type = "rlib"] +#![feature(extern_item_impls)] + +#[eii(eii1)] +pub static DECL1: u64 = 5; diff --git a/tests/ui/eii/static/auxiliary/impl_default_override.rs b/tests/ui/eii/static/auxiliary/impl_default_override.rs new file mode 100644 index 0000000000000..d70a137fbc459 --- /dev/null +++ b/tests/ui/eii/static/auxiliary/impl_default_override.rs @@ -0,0 +1,8 @@ +//@ aux-build: decl_with_default.rs +#![crate_type = "rlib"] +#![feature(extern_item_impls)] + +extern crate decl_with_default as decl; + +#[decl::eii1] +pub static EII1_IMPL: u64 = 10; diff --git a/tests/ui/eii/static/default.rs b/tests/ui/eii/static/default.rs new file mode 100644 index 0000000000000..02307432e2f81 --- /dev/null +++ b/tests/ui/eii/static/default.rs @@ -0,0 +1,15 @@ +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests static EIIs with default implementations. + +#![feature(extern_item_impls)] + +#[eii(eii1)] +pub static DECL1: u64 = 5; + +fn main() { + println!("{DECL1}"); +} diff --git a/tests/ui/eii/static/default.run.stdout b/tests/ui/eii/static/default.run.stdout new file mode 100644 index 0000000000000..7ed6ff82de6bc --- /dev/null +++ b/tests/ui/eii/static/default.run.stdout @@ -0,0 +1 @@ +5 diff --git a/tests/ui/eii/static/default_cross_crate.rs b/tests/ui/eii/static/default_cross_crate.rs new file mode 100644 index 0000000000000..4d6df4b7ee717 --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate.rs @@ -0,0 +1,13 @@ +//@ aux-build: decl_with_default.rs +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests that a static EII default can be used from another crate. + +extern crate decl_with_default; + +fn main() { + println!("{}", decl_with_default::DECL1); +} diff --git a/tests/ui/eii/static/default_cross_crate.run.stdout b/tests/ui/eii/static/default_cross_crate.run.stdout new file mode 100644 index 0000000000000..7ed6ff82de6bc --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate.run.stdout @@ -0,0 +1 @@ +5 diff --git a/tests/ui/eii/static/default_cross_crate_explicit.rs b/tests/ui/eii/static/default_cross_crate_explicit.rs new file mode 100644 index 0000000000000..c3139f45d19c5 --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate_explicit.rs @@ -0,0 +1,15 @@ +//@ aux-build: decl_with_default.rs +//@ aux-build: impl_default_override.rs +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests that an explicit static EII implementation overrides a cross-crate default. + +extern crate decl_with_default; +extern crate impl_default_override; + +fn main() { + println!("{}", decl_with_default::DECL1); +} diff --git a/tests/ui/eii/static/default_cross_crate_explicit.run.stdout b/tests/ui/eii/static/default_cross_crate_explicit.run.stdout new file mode 100644 index 0000000000000..f599e28b8ab0d --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate_explicit.run.stdout @@ -0,0 +1 @@ +10 diff --git a/tests/ui/eii/static/default_explicit.rs b/tests/ui/eii/static/default_explicit.rs new file mode 100644 index 0000000000000..b18da35c3debe --- /dev/null +++ b/tests/ui/eii/static/default_explicit.rs @@ -0,0 +1,19 @@ +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// Tests that an explicit static EII implementation overrides a local default. + +#![feature(extern_item_impls)] +#![allow(dead_code)] + +#[eii(eii1)] +pub static DECL1: u64 = 5; + +#[eii1] +pub static EII1_IMPL: u64 = 10; + +fn main() { + println!("{DECL1}"); +} diff --git a/tests/ui/eii/static/default_explicit.run.stdout b/tests/ui/eii/static/default_explicit.run.stdout new file mode 100644 index 0000000000000..f599e28b8ab0d --- /dev/null +++ b/tests/ui/eii/static/default_explicit.run.stdout @@ -0,0 +1 @@ +10