Skip to content

Commit 1e4af5e

Browse files
committed
Introduce proc_macro::DeriveExpansionOptions
1 parent a191610 commit 1e4af5e

File tree

8 files changed

+117
-8
lines changed

8 files changed

+117
-8
lines changed

Diff for: compiler/rustc_expand/src/proc_macro.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl base::BangProcMacro for BangProcMacro {
5959

6060
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
6161
let strategy = exec_strategy(ecx);
62-
let server = proc_macro_server::Rustc::new(ecx);
62+
let server = proc_macro_server::Rustc::new(ecx, Default::default());
6363
self.client.run(&strategy, server, input, proc_macro_backtrace).map_err(|e| {
6464
ecx.sess.emit_err(errors::ProcMacroPanicked {
6565
span,
@@ -90,7 +90,7 @@ impl base::AttrProcMacro for AttrProcMacro {
9090

9191
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
9292
let strategy = exec_strategy(ecx);
93-
let server = proc_macro_server::Rustc::new(ecx);
93+
let server = proc_macro_server::Rustc::new(ecx, Default::default());
9494
self.client.run(&strategy, server, annotation, annotated, proc_macro_backtrace).map_err(
9595
|e| {
9696
let mut err = ecx.struct_span_err(span, "custom attribute panicked");
@@ -114,7 +114,7 @@ impl MultiItemModifier for DeriveProcMacro {
114114
span: Span,
115115
_meta_item: &ast::MetaItem,
116116
item: Annotatable,
117-
_is_derive_const: bool,
117+
is_derive_const: bool,
118118
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
119119
// We need special handling for statement items
120120
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
@@ -142,7 +142,10 @@ impl MultiItemModifier for DeriveProcMacro {
142142
});
143143
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
144144
let strategy = exec_strategy(ecx);
145-
let server = proc_macro_server::Rustc::new(ecx);
145+
let server = proc_macro_server::Rustc::new(
146+
ecx,
147+
proc_macro_server::ExpansionOptions { is_derive_const },
148+
);
146149
match self.client.run(&strategy, server, input, proc_macro_backtrace) {
147150
Ok(stream) => stream,
148151
Err(e) => {

Diff for: compiler/rustc_expand/src/proc_macro_server.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -370,17 +370,19 @@ pub(crate) struct Rustc<'a, 'b> {
370370
mixed_site: Span,
371371
krate: CrateNum,
372372
rebased_spans: FxHashMap<usize, Span>,
373+
options: ExpansionOptions,
373374
}
374375

375376
impl<'a, 'b> Rustc<'a, 'b> {
376-
pub fn new(ecx: &'a mut ExtCtxt<'b>) -> Self {
377+
pub fn new(ecx: &'a mut ExtCtxt<'b>, options: ExpansionOptions) -> Self {
377378
let expn_data = ecx.current_expansion.id.expn_data();
378379
Rustc {
379380
def_site: ecx.with_def_site_ctxt(expn_data.def_site),
380381
call_site: ecx.with_call_site_ctxt(expn_data.call_site),
381382
mixed_site: ecx.with_mixed_site_ctxt(expn_data.call_site),
382383
krate: expn_data.macro_def_id.unwrap().krate,
383384
rebased_spans: FxHashMap::default(),
385+
options,
384386
ecx,
385387
}
386388
}
@@ -390,6 +392,11 @@ impl<'a, 'b> Rustc<'a, 'b> {
390392
}
391393
}
392394

395+
#[derive(Default)]
396+
pub(crate) struct ExpansionOptions {
397+
pub(crate) is_derive_const: bool,
398+
}
399+
393400
impl server::Types for Rustc<'_, '_> {
394401
type FreeFunctions = FreeFunctions;
395402
type TokenStream = TokenStream;
@@ -477,6 +484,10 @@ impl server::FreeFunctions for Rustc<'_, '_> {
477484
}
478485
self.sess().span_diagnostic.emit_diagnostic(&mut diag);
479486
}
487+
488+
fn is_derive_const(&mut self) -> bool {
489+
self.options.is_derive_const
490+
}
480491
}
481492

482493
impl server::TokenStream for Rustc<'_, '_> {

Diff for: compiler/rustc_passes/src/check_attr.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2280,6 +2280,13 @@ impl CheckAttrVisitor<'_> {
22802280
///
22812281
/// If this best effort goes wrong, it will just emit a worse error later (see #102923)
22822282
fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
2283+
// FIXME(fmease): This is temporary. Update this function to permit the signature of derive
2284+
// macros to be EITHER `fn(TS) -> TS` OR `fn(TS, DEO) -> TS`. Should be straightforward to
2285+
// implement.
2286+
if true {
2287+
return;
2288+
}
2289+
22832290
if target != Target::Fn {
22842291
return;
22852292
}

Diff for: library/proc_macro/src/bridge/client.rs

+30-3
Original file line numberDiff line numberDiff line change
@@ -484,12 +484,16 @@ impl ProcMacro {
484484
}
485485
}
486486

487-
pub const fn custom_derive(
487+
pub const fn custom_derive<Discriminant>(
488488
trait_name: &'static str,
489489
attributes: &'static [&'static str],
490-
expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
490+
expand: impl ~const ExpandCustomDerive<Discriminant>,
491491
) -> Self {
492-
ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
492+
ProcMacro::CustomDerive {
493+
trait_name,
494+
attributes,
495+
client: Client::expand1(expand.into_fn()),
496+
}
493497
}
494498

495499
pub const fn attr(
@@ -506,3 +510,26 @@ impl ProcMacro {
506510
ProcMacro::Bang { name, client: Client::expand1(expand) }
507511
}
508512
}
513+
514+
#[const_trait]
515+
pub trait ExpandCustomDerive<Discriminant> {
516+
fn into_fn(self) -> impl Fn(crate::TokenStream) -> crate::TokenStream + Copy;
517+
}
518+
519+
impl<F> const ExpandCustomDerive<()> for F
520+
where
521+
F: Fn(crate::TokenStream) -> crate::TokenStream + Copy,
522+
{
523+
fn into_fn(self) -> impl Fn(crate::TokenStream) -> crate::TokenStream + Copy {
524+
self
525+
}
526+
}
527+
528+
impl<F> const ExpandCustomDerive<crate::DeriveExpansionOptions> for F
529+
where
530+
F: Fn(crate::TokenStream, crate::DeriveExpansionOptions) -> crate::TokenStream + Copy,
531+
{
532+
fn into_fn(self) -> impl Fn(crate::TokenStream) -> crate::TokenStream + Copy {
533+
move |input| self(input, Default::default())
534+
}
535+
}

Diff for: library/proc_macro/src/bridge/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ macro_rules! with_api {
5959
fn track_path(path: &str);
6060
fn literal_from_str(s: &str) -> Result<Literal<$S::Span, $S::Symbol>, ()>;
6161
fn emit_diagnostic(diagnostic: Diagnostic<$S::Span>);
62+
fn is_derive_const() -> bool;
6263
},
6364
TokenStream {
6465
fn drop($self: $S::TokenStream);

Diff for: library/proc_macro/src/lib.rs

+27
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
#![feature(rustc_allow_const_fn_unstable)]
2626
#![feature(staged_api)]
2727
#![feature(allow_internal_unstable)]
28+
#![feature(const_trait_impl)]
2829
#![feature(decl_macro)]
30+
#![feature(effects)]
2931
#![feature(maybe_uninit_write_slice)]
3032
#![feature(negative_impls)]
3133
#![feature(new_uninit)]
@@ -85,6 +87,31 @@ impl !Send for TokenStream {}
8587
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
8688
impl !Sync for TokenStream {}
8789

90+
/// Derive expansion options.
91+
#[unstable(feature = "derive_const", issue = "none")]
92+
#[derive(Default, Clone)]
93+
#[non_exhaustive]
94+
pub struct DeriveExpansionOptions;
95+
96+
impl DeriveExpansionOptions {
97+
/// Returns the default options.
98+
#[unstable(feature = "derive_const", issue = "none")]
99+
pub fn new() -> Self {
100+
Self::default()
101+
}
102+
103+
/// Whether this is a `#[derive_const]` or a `#[derive]`.
104+
#[unstable(feature = "derive_const", issue = "none")]
105+
pub fn is_const(&self) -> bool {
106+
bridge::client::FreeFunctions::is_derive_const()
107+
}
108+
}
109+
110+
#[unstable(feature = "derive_const", issue = "none")]
111+
impl !Send for DeriveExpansionOptions {}
112+
#[unstable(feature = "derive_const", issue = "none")]
113+
impl !Sync for DeriveExpansionOptions {}
114+
88115
/// Error returned from `TokenStream::from_str`.
89116
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
90117
#[non_exhaustive]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
#![crate_type = "proc-macro"]
4+
#![feature(derive_const)]
5+
6+
extern crate proc_macro;
7+
8+
use proc_macro::{TokenStream, DeriveExpansionOptions};
9+
10+
#[proc_macro_derive(IsDeriveConst)]
11+
pub fn is_derive_const(_: TokenStream, options: DeriveExpansionOptions) -> TokenStream {
12+
format!("const IS_DERIVE_CONST: bool = {};", options.is_const()).parse().unwrap()
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// check-pass
2+
// edition: 2021
3+
// aux-crate:is_derive_const=is-derive-const.rs
4+
#![feature(derive_const)]
5+
6+
const _: () = {
7+
#[derive(is_derive_const::IsDeriveConst)]
8+
struct _Type;
9+
10+
assert!(!IS_DERIVE_CONST);
11+
};
12+
13+
const _: () = {
14+
#[derive_const(is_derive_const::IsDeriveConst)]
15+
struct _Type;
16+
17+
assert!(IS_DERIVE_CONST);
18+
};
19+
20+
fn main() {}

0 commit comments

Comments
 (0)