Skip to content

Commit 27adf3d

Browse files
Rollup merge of rust-lang#156583 - AsakuraMizu:eii-static-default, r=JonathanBrouwer,mu001999
Support defaults for static EIIs Tracking issue: rust-lang#125418 rust-lang#154193 added EII support for statics, but left default implementations for "a followup PR". This PR implements it. Maybe I should remove `no-prefer-dynamic` if rust-lang#156577 is accepted.
2 parents 129ae43 + d7f16d7 commit 27adf3d

12 files changed

Lines changed: 127 additions & 43 deletions

compiler/rustc_builtin_macros/src/eii.rs

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use thin_vec::{ThinVec, thin_vec};
1212
use crate::errors::{
1313
EiiExternTargetExpectedList, EiiExternTargetExpectedMacro, EiiExternTargetExpectedUnsafe,
1414
EiiMacroExpectedMaxOneArgument, EiiOnlyOnce, EiiSharedMacroInStatementPosition,
15-
EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticDefault,
16-
EiiStaticMultipleImplementations, EiiStaticMutable,
15+
EiiSharedMacroTarget, EiiStaticArgumentRequired, EiiStaticMultipleImplementations,
16+
EiiStaticMutable,
1717
};
1818

1919
/// ```rust
@@ -86,14 +86,6 @@ fn eii_(
8686
let (item_span, foreign_item_name) = match kind {
8787
ItemKind::Fn(func) => (func.sig.span, func.ident),
8888
ItemKind::Static(stat) => {
89-
// Statics with a default are not supported yet
90-
if let Some(stat_body) = &stat.expr {
91-
ecx.dcx().emit_err(EiiStaticDefault {
92-
span: stat_body.span,
93-
name: path_to_string(&meta_item.path),
94-
});
95-
return vec![];
96-
}
9789
// Statics must have an explicit name for the eii
9890
if meta_item.is_word() {
9991
ecx.dcx().emit_err(EiiStaticArgumentRequired {
@@ -137,18 +129,16 @@ fn eii_(
137129

138130
let mut module_items = Vec::new();
139131

140-
if let ItemKind::Fn(func) = kind
141-
&& func.body.is_some()
142-
{
143-
module_items.push(generate_default_func_impl(
144-
ecx,
145-
&func,
146-
impl_unsafe,
147-
macro_name,
148-
eii_attr_span,
149-
item_span,
150-
foreign_item_name,
151-
))
132+
if let Some(default_impl) = generate_default_impl(
133+
ecx,
134+
kind,
135+
impl_unsafe,
136+
macro_name,
137+
eii_attr_span,
138+
item_span,
139+
foreign_item_name,
140+
) {
141+
module_items.push(default_impl);
152142
}
153143

154144
module_items.push(generate_foreign_item(
@@ -220,20 +210,33 @@ fn filter_attrs_for_multiple_eii_attr(
220210
.collect()
221211
}
222212

223-
fn generate_default_func_impl(
213+
fn generate_default_impl(
224214
ecx: &mut ExtCtxt<'_>,
225-
func: &ast::Fn,
215+
item_kind: &ItemKind,
226216
impl_unsafe: bool,
227217
macro_name: Ident,
228218
eii_attr_span: Span,
229219
item_span: Span,
230220
foreign_item_name: Ident,
231-
) -> Box<ast::Item> {
221+
) -> Option<Box<ast::Item>> {
222+
match item_kind {
223+
ItemKind::Fn(func) => {
224+
if func.body.is_none() {
225+
return None;
226+
}
227+
}
228+
ItemKind::Static(stat) => {
229+
if stat.expr.is_none() {
230+
return None;
231+
}
232+
}
233+
_ => unreachable!("Target was checked earlier"),
234+
};
235+
232236
// FIXME: re-add some original attrs
233237
let attrs = ThinVec::new();
234238

235-
let mut default_func = func.clone();
236-
default_func.eii_impls.push(EiiImpl {
239+
let eii_impl = EiiImpl {
237240
node_id: DUMMY_NODE_ID,
238241
inner_span: macro_name.span,
239242
eii_macro_path: ast::Path::from_ident(macro_name),
@@ -253,7 +256,18 @@ fn generate_default_func_impl(
253256
),
254257
impl_unsafe,
255258
}),
256-
});
259+
};
260+
261+
let mut item_kind = item_kind.clone();
262+
match &mut item_kind {
263+
ItemKind::Fn(func) => {
264+
func.eii_impls.push(eii_impl);
265+
}
266+
ItemKind::Static(stat) => {
267+
stat.eii_impls.push(eii_impl);
268+
}
269+
_ => unreachable!("Target was checked earlier"),
270+
};
257271

258272
let anon_mod = |span: Span, stmts: ThinVec<ast::Stmt>| {
259273
let unit = ecx.ty(item_span, ast::TyKind::Tup(ThinVec::new()));
@@ -267,15 +281,12 @@ fn generate_default_func_impl(
267281
};
268282

269283
// const _: () = {
270-
// <orig fn>
284+
// <orig item>
271285
// }
272-
anon_mod(
286+
Some(anon_mod(
273287
item_span,
274-
thin_vec![ecx.stmt_item(
275-
item_span,
276-
ecx.item(item_span, attrs, ItemKind::Fn(Box::new(default_func)))
277-
),],
278-
)
288+
thin_vec![ecx.stmt_item(item_span, ecx.item(item_span, attrs, item_kind))],
289+
))
279290
}
280291

281292
/// Generates a foreign item, like
@@ -362,6 +373,8 @@ fn generate_foreign_static(mut stat: Box<ast::StaticItem>) -> ast::ForeignItemKi
362373
stat.safety = ast::Safety::Safe(stat.ident.span);
363374
}
364375

376+
stat.expr = None;
377+
365378
ast::ForeignItemKind::Static(stat)
366379
}
367380

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,14 +1134,6 @@ pub(crate) struct EiiStaticMultipleImplementations {
11341134
pub span: Span,
11351135
}
11361136

1137-
#[derive(Diagnostic)]
1138-
#[diag("`#[{$name}]` cannot be used on statics with a value")]
1139-
pub(crate) struct EiiStaticDefault {
1140-
#[primary_span]
1141-
pub span: Span,
1142-
pub name: String,
1143-
}
1144-
11451137
#[derive(Diagnostic)]
11461138
#[diag("`#[{$name}]` requires the name as an explicit argument when used on a static")]
11471139
pub(crate) struct EiiStaticArgumentRequired {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#![crate_type = "rlib"]
2+
#![feature(extern_item_impls)]
3+
4+
#[eii(eii1)]
5+
pub static DECL1: u64 = 5;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//@ aux-build: decl_with_default.rs
2+
#![crate_type = "rlib"]
3+
#![feature(extern_item_impls)]
4+
5+
extern crate decl_with_default as decl;
6+
7+
#[decl::eii1]
8+
pub static EII1_IMPL: u64 = 10;

tests/ui/eii/static/default.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ run-pass
2+
//@ check-run-results
3+
//@ ignore-backends: gcc
4+
// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
5+
//@ ignore-windows
6+
// Tests static EIIs with default implementations.
7+
8+
#![feature(extern_item_impls)]
9+
10+
#[eii(eii1)]
11+
pub static DECL1: u64 = 5;
12+
13+
fn main() {
14+
println!("{DECL1}");
15+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//@ aux-build: decl_with_default.rs
2+
//@ run-pass
3+
//@ check-run-results
4+
//@ ignore-backends: gcc
5+
// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
6+
//@ ignore-windows
7+
// Tests that a static EII default can be used from another crate.
8+
9+
extern crate decl_with_default;
10+
11+
fn main() {
12+
println!("{}", decl_with_default::DECL1);
13+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
5
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ aux-build: decl_with_default.rs
2+
//@ aux-build: impl_default_override.rs
3+
//@ run-pass
4+
//@ check-run-results
5+
//@ ignore-backends: gcc
6+
// FIXME: linking on windows (specifically mingw) not yet supported, see tracking issue #125418
7+
//@ ignore-windows
8+
// Tests that an explicit static EII implementation overrides a cross-crate default.
9+
10+
extern crate decl_with_default;
11+
extern crate impl_default_override;
12+
13+
fn main() {
14+
println!("{}", decl_with_default::DECL1);
15+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10

0 commit comments

Comments
 (0)