Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions compiler/rustc_builtin_macros/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/rust-lang/rust/issues/157649> for more information")]
pub(crate) struct EiiStaticDefaultApple {
#[primary_span]
pub span: Span,
pub name: String,
Expand Down
86 changes: 55 additions & 31 deletions compiler/rustc_builtin_macros/src/eii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::diagnostics::{
EiiAttributeNotSupported, EiiExternTargetExpectedList, EiiExternTargetExpectedMacro,
EiiExternTargetExpectedUnsafe, EiiMacroExpectedMaxOneArgument, EiiOnlyOnce,
EiiSharedMacroInStatementPosition, EiiSharedMacroTarget, EiiStaticArgumentRequired,
EiiStaticDefault, EiiStaticMultipleImplementations, EiiStaticMutable,
EiiStaticDefaultApple, EiiStaticMultipleImplementations, EiiStaticMutable,
};

/// ```rust
Expand Down Expand Up @@ -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 {
Comment thread
mu001999 marked this conversation as resolved.
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 {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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<Attribute>,
) -> Box<ast::Item> {
let mut default_func = func.clone();
default_func.eii_impls.push(EiiImpl {
) -> Option<Box<ast::Item>> {
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),
Expand All @@ -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<ast::Stmt>| {
let unit = ecx.ty(item_span, ast::TyKind::Tup(ThinVec::new()));
Expand All @@ -311,15 +336,12 @@ fn generate_default_func_impl(
};

// const _: () = {
// <orig fn>
// <orig item>
// }
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
Expand Down Expand Up @@ -405,6 +427,8 @@ fn generate_foreign_static(mut stat: Box<ast::StaticItem>) -> ast::ForeignItemKi
stat.safety = ast::Safety::Safe(stat.ident.span);
}

stat.expr = None;

ast::ForeignItemKind::Static(stat)
}

Expand Down
6 changes: 6 additions & 0 deletions tests/ui/eii/static/auxiliary/decl_with_default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//@ no-prefer-dynamic
#![crate_type = "rlib"]
#![feature(extern_item_impls)]

#[eii(eii1)]
pub static DECL1: u64 = 5;
9 changes: 9 additions & 0 deletions tests/ui/eii/static/auxiliary/impl_default_override.rs
Original file line number Diff line number Diff line change
@@ -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;
17 changes: 17 additions & 0 deletions tests/ui/eii/static/default.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
1 change: 1 addition & 0 deletions tests/ui/eii/static/default.run.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
5
8 changes: 8 additions & 0 deletions tests/ui/eii/static/default_apple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//@ only-apple
//@ ignore-backends: gcc

#![feature(extern_item_impls)]
#![crate_type = "lib"]
#[eii(eii1)]
pub static DECL1: u64 = 5;
//~^ ERROR `#[eii]` cannot be used on statics with a value on Apple targets
10 changes: 10 additions & 0 deletions tests/ui/eii/static/default_apple.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: `#[eii]` cannot be used on statics with a value on Apple targets
--> $DIR/default_apple.rs:7:25
|
LL | pub static DECL1: u64 = 5;
| ^
|
= note: see issue #157649 <https://github.com/rust-lang/rust/issues/157649> for more information

error: aborting due to 1 previous error

15 changes: 15 additions & 0 deletions tests/ui/eii/static/default_cross_crate.rs
Original file line number Diff line number Diff line change
@@ -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);
}
1 change: 1 addition & 0 deletions tests/ui/eii/static/default_cross_crate.run.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
5
17 changes: 17 additions & 0 deletions tests/ui/eii/static/default_cross_crate_explicit.rs
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10
21 changes: 21 additions & 0 deletions tests/ui/eii/static/default_explicit.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
1 change: 1 addition & 0 deletions tests/ui/eii/static/default_explicit.run.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10
Loading