Skip to content
Open
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
83 changes: 48 additions & 35 deletions compiler/rustc_builtin_macros/src/eii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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<ast::Item> {
) -> 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"),
};

// 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),
Expand All @@ -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<ast::Stmt>| {
let unit = ecx.ty(item_span, ast::TyKind::Tup(ThinVec::new()));
Expand All @@ -267,15 +281,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 @@ -362,6 +373,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
8 changes: 0 additions & 8 deletions compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
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;
15 changes: 15 additions & 0 deletions tests/ui/eii/static/default.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
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
13 changes: 13 additions & 0 deletions tests/ui/eii/static/default_cross_crate.rs
Original file line number Diff line number Diff line change
@@ -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);
}
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
15 changes: 15 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,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);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
10
19 changes: 19 additions & 0 deletions tests/ui/eii/static/default_explicit.rs
Original file line number Diff line number Diff line change
@@ -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}");
}
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