Skip to content

Commit c449220

Browse files
m-ou-sejdonszelmann
authored andcommitted
Update.
1 parent 2b24fdd commit c449220

File tree

8 files changed

+270
-44
lines changed

8 files changed

+270
-44
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -153,30 +153,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
153153
i: &ItemKind,
154154
) -> Vec<hir::Attribute> {
155155
match i {
156+
ItemKind::Fn(box Fn { eii_impl, .. }) if eii_impl.is_empty() => Vec::new(),
156157
ItemKind::Fn(box Fn { eii_impl, .. }) => {
157-
let mut eii_impls = ThinVec::new();
158-
for EIIImpl {
159-
node_id,
160-
eii_macro_path,
161-
impl_safety,
162-
span,
163-
inner_span,
164-
is_default,
165-
} in eii_impl
166-
{
167-
let did = self.lower_path_simple_eii(*node_id, eii_macro_path);
168-
eii_impls.push(rustc_attr_parsing::EIIImpl {
169-
eii_macro: did,
170-
span: self.lower_span(*span),
171-
inner_span: self.lower_span(*inner_span),
172-
impl_marked_unsafe: self
173-
.lower_safety(*impl_safety, hir::Safety::Safe)
174-
.is_unsafe(),
175-
is_default: *is_default,
176-
})
177-
}
178-
179-
vec![hir::Attribute::Parsed(AttributeKind::EiiImpl(eii_impls))]
158+
vec![hir::Attribute::Parsed(AttributeKind::EiiImpl(
159+
eii_impl
160+
.iter()
161+
.map(
162+
|EIIImpl {
163+
node_id,
164+
eii_macro_path,
165+
impl_safety,
166+
span,
167+
inner_span,
168+
is_default,
169+
}| {
170+
let did = self.lower_path_simple_eii(*node_id, eii_macro_path);
171+
rustc_attr_parsing::EIIImpl {
172+
eii_macro: did,
173+
span: self.lower_span(*span),
174+
inner_span: self.lower_span(*inner_span),
175+
impl_marked_unsafe: self
176+
.lower_safety(*impl_safety, hir::Safety::Safe)
177+
.is_unsafe(),
178+
is_default: *is_default,
179+
}
180+
},
181+
)
182+
.collect(),
183+
))]
180184
}
181185
ItemKind::MacroDef(
182186
_,
@@ -541,14 +545,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
541545
def_kind.descr(def_id.to_def_id())
542546
);
543547
};
544-
545-
let ast_macro_def = self.arena.alloc(ast::MacroDef {
548+
let macro_def = self.arena.alloc(ast::MacroDef {
546549
body,
547550
macro_rules: *macro_rules,
548551
eii_macro_for: None,
549552
});
550553

551-
hir::ItemKind::Macro(ident, ast_macro_def, macro_kind)
554+
hir::ItemKind::Macro(ident, macro_def, macro_kind)
552555
}
553556
ItemKind::Delegation(box delegation) => {
554557
let delegation_results = self.lower_delegation(delegation, id, false);

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,17 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
788788
sp: Span,
789789
print_visibility: impl FnOnce(&mut Self),
790790
) {
791+
if let Some(eii_macro_for) = &macro_def.eii_macro_for {
792+
self.word("#[eii_macro_for(");
793+
self.print_path(&eii_macro_for.extern_item_path, false, 0);
794+
if eii_macro_for.impl_unsafe {
795+
self.word(",");
796+
self.space();
797+
self.word("unsafe");
798+
}
799+
self.word(")]");
800+
self.hardbreak();
801+
}
791802
let (kw, has_bang) = if macro_def.macro_rules {
792803
("macro_rules", true)
793804
} else {

compiler/rustc_builtin_macros/src/eii.rs

Lines changed: 205 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,210 @@
1-
use rustc_ast::{DUMMY_NODE_ID, EIIImpl, EIIMacroFor, ItemKind, ast};
1+
use rustc_ast::ptr::P;
2+
use rustc_ast::token::{Delimiter, TokenKind};
3+
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
4+
use rustc_ast::{DUMMY_NODE_ID, EIIImpl, EIIMacroFor, ItemKind, ast, token, tokenstream};
25
use rustc_ast_pretty::pprust::path_to_string;
36
use rustc_expand::base::{Annotatable, ExtCtxt};
4-
use rustc_span::{Span, kw};
7+
use rustc_span::{Ident, Span, kw, sym};
8+
9+
/* ```rust
10+
11+
#[eii]
12+
fn panic_handler();
13+
14+
#[eii(panic_handler)]
15+
fn panic_handler();
16+
17+
#[eii(panic_handler, unsafe)]
18+
fn panic_handler();
19+
20+
// expansion:
21+
22+
extern "Rust" {
23+
fn panic_handler();
24+
}
25+
26+
#[rustc_builtin_macro(eii_macro)] // eii_macro_for: panic_handler
27+
macro panic_handler() {}
28+
29+
``` */
30+
pub(crate) fn eii(
31+
ecx: &mut ExtCtxt<'_>,
32+
span: Span,
33+
meta_item: &ast::MetaItem,
34+
item: Annotatable,
35+
) -> Vec<Annotatable> {
36+
let span = ecx.with_def_site_ctxt(span);
37+
38+
let Annotatable::Item(item) = item else {
39+
ecx.dcx()
40+
.emit_err(EIIMacroExpectedFunction { span, name: path_to_string(&meta_item.path) });
41+
return vec![item];
42+
};
43+
44+
let orig_item = item.clone();
45+
46+
let item = item.into_inner();
47+
48+
let ast::Item {
49+
attrs,
50+
id: _,
51+
span: item_span,
52+
vis,
53+
kind: ItemKind::Fn(mut func),
54+
tokens: _,
55+
} = item
56+
else {
57+
ecx.dcx()
58+
.emit_err(EIIMacroExpectedFunction { span, name: path_to_string(&meta_item.path) });
59+
return vec![Annotatable::Item(P(item))];
60+
};
61+
62+
let macro_name = if meta_item.is_word() {
63+
func.ident
64+
} else if let Some([first]) = meta_item.meta_item_list()
65+
&& let Some(m) = first.meta_item()
66+
&& m.path.segments.len() == 1
67+
{
68+
m.path.segments[0].ident
69+
} else {
70+
ecx.dcx().emit_err(EIIMacroExpectedMaxOneArgument {
71+
span: meta_item.span,
72+
name: path_to_string(&meta_item.path),
73+
});
74+
return vec![Annotatable::Item(orig_item)];
75+
};
76+
77+
let impl_unsafe = false; // TODO
78+
79+
let abi = match func.sig.header.ext {
80+
// extern "X" fn => extern "X" {}
81+
ast::Extern::Explicit(lit, _) => Some(lit),
82+
// extern fn => extern {}
83+
ast::Extern::Implicit(_) => None,
84+
// fn => extern "Rust" {}
85+
ast::Extern::None => Some(ast::StrLit {
86+
symbol: sym::Rust,
87+
suffix: None,
88+
symbol_unescaped: sym::Rust,
89+
style: ast::StrStyle::Cooked,
90+
span,
91+
}),
92+
};
93+
94+
// ABI has been moved to the extern {} block, so we remove it from the fn item.
95+
func.sig.header.ext = ast::Extern::None;
96+
97+
// And mark safe functions explicitly as `safe fn`.
98+
if func.sig.header.safety == ast::Safety::Default {
99+
func.sig.header.safety = ast::Safety::Safe(func.sig.span);
100+
}
101+
102+
// extern "…" { safe fn item(); }
103+
let extern_block = Annotatable::Item(P(ast::Item {
104+
attrs: ast::AttrVec::default(),
105+
id: ast::DUMMY_NODE_ID,
106+
span,
107+
vis: ast::Visibility { span, kind: ast::VisibilityKind::Inherited, tokens: None },
108+
kind: ast::ItemKind::ForeignMod(ast::ForeignMod {
109+
extern_span: span,
110+
safety: ast::Safety::Unsafe(span),
111+
abi,
112+
items: From::from([P(ast::ForeignItem {
113+
attrs,
114+
id: ast::DUMMY_NODE_ID,
115+
span: item_span,
116+
vis,
117+
kind: ast::ForeignItemKind::Fn(func.clone()),
118+
tokens: None,
119+
})]),
120+
}),
121+
tokens: None,
122+
}));
123+
124+
let macro_def = Annotatable::Item(P(ast::Item {
125+
attrs: ast::AttrVec::from_iter([
126+
// #[eii_macro_for(func.ident)]
127+
ast::Attribute {
128+
kind: ast::AttrKind::Normal(P(ast::NormalAttr {
129+
item: ast::AttrItem {
130+
unsafety: ast::Safety::Default,
131+
path: ast::Path::from_ident(Ident::new(sym::eii_macro_for, span)),
132+
args: ast::AttrArgs::Delimited(ast::DelimArgs {
133+
dspan: DelimSpan::from_single(span),
134+
delim: Delimiter::Parenthesis,
135+
tokens: TokenStream::new(vec![tokenstream::TokenTree::Token(
136+
token::Token::from_ast_ident(func.ident),
137+
Spacing::Alone,
138+
)]),
139+
}),
140+
tokens: None,
141+
},
142+
tokens: None,
143+
})),
144+
id: ecx.sess.psess.attr_id_generator.mk_attr_id(),
145+
style: ast::AttrStyle::Outer,
146+
span,
147+
},
148+
// #[builtin_macro(eii_macro)]
149+
ast::Attribute {
150+
kind: ast::AttrKind::Normal(P(ast::NormalAttr {
151+
item: ast::AttrItem {
152+
unsafety: ast::Safety::Default,
153+
path: ast::Path::from_ident(Ident::new(sym::rustc_builtin_macro, span)),
154+
args: ast::AttrArgs::Delimited(ast::DelimArgs {
155+
dspan: DelimSpan::from_single(span),
156+
delim: Delimiter::Parenthesis,
157+
tokens: TokenStream::new(vec![tokenstream::TokenTree::token_alone(
158+
token::TokenKind::Ident(sym::eii_macro, token::IdentIsRaw::No),
159+
span,
160+
)]),
161+
}),
162+
tokens: None,
163+
},
164+
tokens: None,
165+
})),
166+
id: ecx.sess.psess.attr_id_generator.mk_attr_id(),
167+
style: ast::AttrStyle::Outer,
168+
span,
169+
},
170+
]),
171+
id: ast::DUMMY_NODE_ID,
172+
span,
173+
// pub
174+
vis: ast::Visibility { span, kind: ast::VisibilityKind::Public, tokens: None },
175+
kind: ast::ItemKind::MacroDef(
176+
// macro macro_name
177+
macro_name,
178+
ast::MacroDef {
179+
// { () => {} }
180+
body: P(ast::DelimArgs {
181+
dspan: DelimSpan::from_single(span),
182+
delim: Delimiter::Brace,
183+
tokens: TokenStream::from_iter([
184+
TokenTree::Delimited(
185+
DelimSpan::from_single(span),
186+
DelimSpacing::new(Spacing::Alone, Spacing::Alone),
187+
Delimiter::Parenthesis,
188+
TokenStream::default(),
189+
),
190+
TokenTree::token_alone(TokenKind::FatArrow, span),
191+
TokenTree::Delimited(
192+
DelimSpan::from_single(span),
193+
DelimSpacing::new(Spacing::Alone, Spacing::Alone),
194+
Delimiter::Brace,
195+
TokenStream::default(),
196+
),
197+
]),
198+
}),
199+
macro_rules: false,
200+
eii_macro_for: None,
201+
}
202+
),
203+
tokens: None,
204+
}));
205+
206+
vec![extern_block, macro_def]
207+
}
5208

6209
use crate::errors::{
7210
EIIMacroExpectedFunction, EIIMacroExpectedMaxOneArgument, EIIMacroForExpectedList,

compiler/rustc_builtin_macros/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
123123
global_allocator: global_allocator::expand,
124124
test: test::expand_test,
125125
test_case: test::expand_test_case,
126+
eii: eii::eii,
126127
eii_macro_for: eii::eii_macro_for,
127128
eii_macro: eii::eii_macro,
128129
}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,23 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
111111

112112
if let hir::Attribute::Parsed(p) = attr {
113113
match p {
114+
/*
115+
AttributeKind::EiiImpl(eii_macro) => {
116+
let Some(eii_extern_item) = find_attr!(
117+
tcx.get_all_attrs(eii_macro),
118+
AttributeKind::EiiMacroFor { eii_extern_item, .. } => *eii_extern_item
119+
) else {
120+
tcx.dcx().span_delayed_bug(attr.span(), "missing attr on EII macro");
121+
continue;
122+
};
123+
let _ = eii_extern_item; // XXX mangle as this item or something.
124+
}*/
114125
AttributeKind::Repr(reprs) => {
115126
codegen_fn_attrs.alignment = reprs
116127
.iter()
117128
.filter_map(|(r, _)| if let ReprAlign(x) = r { Some(*x) } else { None })
118129
.max();
119130
}
120-
121131
_ => {}
122132
}
123133
}

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,21 +1056,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
10561056
"#[rustc_force_inline] forces a free function to be inlined"
10571057
),
10581058

1059-
gated!(
1060-
eii, Normal, template!(Word),
1061-
ErrorPreceding, EncodeCrossCrate::No,
1062-
eii_internals, "internally used to implement EII"
1063-
),
1064-
gated!(
1065-
eii_impl, Normal, template!(List: "/*opt*/ default"),
1066-
ErrorPreceding, EncodeCrossCrate::No,
1067-
eii_internals, "internally used to implement EII"
1068-
),
1069-
gated!(
1070-
eii_macro_for, Normal, template!(List: "path"),
1071-
ErrorPreceding, EncodeCrossCrate::No,
1072-
eii_internals, "internally used to implement EII"
1073-
),
10741059
// ==========================================================================
10751060
// Internal attributes, Testing:
10761061
// ==========================================================================

library/core/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ pub mod autodiff {
233233
pub use crate::macros::builtin::autodiff;
234234
}
235235

236+
#[cfg(not(bootstrap))]
237+
#[unstable(feature = "eii", issue = "none")]
238+
pub use crate::macros::builtin::eii;
236239
#[cfg(not(bootstrap))]
237240
#[unstable(feature = "eii_internals", issue = "none")]
238241
pub use crate::macros::builtin::eii_macro_for;

library/core/src/macros/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,16 @@ pub(crate) mod builtin {
17811781
builtin # deref($pat)
17821782
}
17831783

1784+
/// Externally Implementable Item: Defines an attribute macro that can override the item
1785+
/// this is applied to.
1786+
#[cfg(not(bootstrap))]
1787+
#[unstable(feature = "eii", issue = "none")]
1788+
#[rustc_builtin_macro]
1789+
#[allow_internal_unstable(eii_internals, decl_macro, rustc_attrs)]
1790+
pub macro eii($item:item) {
1791+
/* compiler built-in */
1792+
}
1793+
17841794
/// Impl detail of EII
17851795
#[cfg(not(bootstrap))]
17861796
#[unstable(feature = "eii_internals", issue = "none")]

0 commit comments

Comments
 (0)