diff --git a/compiler/rustc_builtin_macros/src/diagnostics.rs b/compiler/rustc_builtin_macros/src/diagnostics.rs index 929c88402b1aa..6ae0f908a88a0 100644 --- a/compiler/rustc_builtin_macros/src/diagnostics.rs +++ b/compiler/rustc_builtin_macros/src/diagnostics.rs @@ -1135,8 +1135,9 @@ pub(crate) struct EiiStaticMultipleImplementations { } #[derive(Diagnostic)] -#[diag("`#[{$name}]` cannot be used on statics with a value")] -pub(crate) struct EiiStaticDefault { +#[diag("`#[{$name}]` cannot be used on statics with a value on Apple targets")] +#[note("see issue #157649 for more information")] +pub(crate) struct EiiStaticDefaultApple { #[primary_span] pub span: Span, pub name: String, diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index 9bb34cdd642a0..68d5278c85ef1 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -13,7 +13,7 @@ use crate::diagnostics::{ EiiAttributeNotSupported, EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition, EiiSharedMacroTarget, EiiStaticArgumentRequired, - EiiStaticDefault, EiiStaticMultipleImplementations, EiiStaticMutable, + EiiStaticDefaultApple, EiiStaticMultipleImplementations, EiiStaticMutable, }; /// ```rust @@ -86,14 +86,17 @@ 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, + // See https://github.com/rust-lang/rust/issues/157649 + if let Some(expr) = &stat.expr + && ecx.sess.target.is_like_darwin + { + ecx.dcx().emit_err(EiiStaticDefaultApple { + span: expr.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 { @@ -139,19 +142,17 @@ 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, - default_func_attrs, - )) + if let Some(default_impl) = generate_default_impl( + ecx, + kind, + impl_unsafe, + macro_name, + eii_attr_span, + item_span, + foreign_item_name, + default_func_attrs, + ) { + module_items.push(default_impl); } module_items.push(generate_foreign_item( @@ -266,18 +267,31 @@ 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, attrs: ThinVec, -) -> Box { - let mut default_func = func.clone(); - default_func.eii_impls.push(EiiImpl { +) -> 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"), + }; + + let eii_impl = EiiImpl { node_id: DUMMY_NODE_ID, inner_span: macro_name.span, eii_macro_path: ast::Path::from_ident(macro_name), @@ -297,7 +311,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())); @@ -311,15 +336,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 @@ -405,6 +427,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/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..53cdc8d62bb7e --- /dev/null +++ b/tests/ui/eii/static/auxiliary/decl_with_default.rs @@ -0,0 +1,6 @@ +//@ no-prefer-dynamic +#![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..03cb061135e70 --- /dev/null +++ b/tests/ui/eii/static/auxiliary/impl_default_override.rs @@ -0,0 +1,9 @@ +//@ no-prefer-dynamic +//@ 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..6234ee2f0c15e --- /dev/null +++ b/tests/ui/eii/static/default.rs @@ -0,0 +1,17 @@ +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple +// 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..f9de906ac267e --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate.rs @@ -0,0 +1,15 @@ +//@ 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 +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple +// 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..1f534e300e0c3 --- /dev/null +++ b/tests/ui/eii/static/default_cross_crate_explicit.rs @@ -0,0 +1,17 @@ +//@ 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 +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple +// 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..6cf36d8da50a5 --- /dev/null +++ b/tests/ui/eii/static/default_explicit.rs @@ -0,0 +1,21 @@ +//@ run-pass +//@ check-run-results +//@ ignore-backends: gcc +// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418 +//@ ignore-windows +// FIXME(#157649): static EII defaults currently fail to link on Apple targets. +//@ ignore-apple +// 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