Rollup merge of #102049 - fee1-dead-contrib:derive_const, r=oli-obk

Add the `#[derive_const]` attribute

Closes #102371. This is a minimal patchset for the attribute to work. There are no restrictions on what traits this attribute applies to.

r? `````@oli-obk`````
This commit is contained in:
Dylan DPC 2022-11-12 12:02:50 +05:30 committed by GitHub
commit 4b0b89827d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 163 additions and 30 deletions

View File

@ -34,6 +34,7 @@ impl MultiItemModifier for Expander {
span: Span, span: Span,
meta_item: &ast::MetaItem, meta_item: &ast::MetaItem,
item: Annotatable, item: Annotatable,
_is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> { ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
let template = AttributeTemplate { list: Some("path"), ..Default::default() }; let template = AttributeTemplate { list: Some("path"), ..Default::default() };
let attr = &ecx.attribute(meta_item.clone()); let attr = &ecx.attribute(meta_item.clone());

View File

@ -10,7 +10,7 @@ use rustc_session::Session;
use rustc_span::symbol::{sym, Ident}; use rustc_span::symbol::{sym, Ident};
use rustc_span::Span; use rustc_span::Span;
pub(crate) struct Expander; pub(crate) struct Expander(pub bool);
impl MultiItemModifier for Expander { impl MultiItemModifier for Expander {
fn expand( fn expand(
@ -19,6 +19,7 @@ impl MultiItemModifier for Expander {
span: Span, span: Span,
meta_item: &ast::MetaItem, meta_item: &ast::MetaItem,
item: Annotatable, item: Annotatable,
_: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> { ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
let sess = ecx.sess; let sess = ecx.sess;
if report_bad_target(sess, &item, span) { if report_bad_target(sess, &item, span) {
@ -58,20 +59,20 @@ impl MultiItemModifier for Expander {
report_path_args(sess, &meta); report_path_args(sess, &meta);
meta.path meta.path
}) })
.map(|path| (path, dummy_annotatable(), None)) .map(|path| (path, dummy_annotatable(), None, self.0))
.collect(); .collect();
// Do not configure or clone items unless necessary. // Do not configure or clone items unless necessary.
match &mut resolutions[..] { match &mut resolutions[..] {
[] => {} [] => {}
[(_, first_item, _), others @ ..] => { [(_, first_item, ..), others @ ..] => {
*first_item = cfg_eval( *first_item = cfg_eval(
sess, sess,
features, features,
item.clone(), item.clone(),
ecx.current_expansion.lint_node_id, ecx.current_expansion.lint_node_id,
); );
for (_, item, _) in others { for (_, item, _, _) in others {
*item = first_item.clone(); *item = first_item.clone();
} }
} }

View File

@ -12,6 +12,7 @@ pub fn expand_deriving_copy(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
let trait_def = TraitDef { let trait_def = TraitDef {
span, span,
@ -22,6 +23,7 @@ pub fn expand_deriving_copy(
supports_unions: true, supports_unions: true,
methods: Vec::new(), methods: Vec::new(),
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push); trait_def.expand(cx, mitem, item, push);

View File

@ -14,6 +14,7 @@ pub fn expand_deriving_clone(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
// The simple form is `fn clone(&self) -> Self { *self }`, possibly with // The simple form is `fn clone(&self) -> Self { *self }`, possibly with
// some additional `AssertParamIsClone` assertions. // some additional `AssertParamIsClone` assertions.
@ -87,6 +88,7 @@ pub fn expand_deriving_clone(
combine_substructure: substructure, combine_substructure: substructure,
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand_ext(cx, mitem, item, push, is_simple) trait_def.expand_ext(cx, mitem, item, push, is_simple)

View File

@ -15,6 +15,7 @@ pub fn expand_deriving_eq(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
let span = cx.with_def_site_ctxt(span); let span = cx.with_def_site_ctxt(span);
let inline = cx.meta_word(span, sym::inline); let inline = cx.meta_word(span, sym::inline);
@ -42,6 +43,7 @@ pub fn expand_deriving_eq(
})), })),
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push); super::inject_impl_of_structural_trait(cx, span, item, path_std!(marker::StructuralEq), push);

View File

@ -13,6 +13,7 @@ pub fn expand_deriving_ord(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
let inline = cx.meta_word(span, sym::inline); let inline = cx.meta_word(span, sym::inline);
let attrs = thin_vec![cx.attribute(inline)]; let attrs = thin_vec![cx.attribute(inline)];
@ -34,6 +35,7 @@ pub fn expand_deriving_ord(
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))), combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)

View File

@ -14,6 +14,7 @@ pub fn expand_deriving_partial_eq(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
let base = true; let base = true;
@ -89,6 +90,7 @@ pub fn expand_deriving_partial_eq(
supports_unions: false, supports_unions: false,
methods, methods,
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)
} }

View File

@ -13,6 +13,7 @@ pub fn expand_deriving_partial_ord(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
let ordering_ty = Path(path_std!(cmp::Ordering)); let ordering_ty = Path(path_std!(cmp::Ordering));
let ret_ty = let ret_ty =
@ -43,6 +44,7 @@ pub fn expand_deriving_partial_ord(
supports_unions: false, supports_unions: false,
methods: vec![partial_cmp_def], methods: vec![partial_cmp_def],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)
} }

View File

@ -13,6 +13,7 @@ pub fn expand_deriving_debug(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
// &mut ::std::fmt::Formatter // &mut ::std::fmt::Formatter
let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut); let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut);
@ -37,6 +38,7 @@ pub fn expand_deriving_debug(
})), })),
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)
} }

View File

@ -16,6 +16,7 @@ pub fn expand_deriving_rustc_decodable(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
let krate = sym::rustc_serialize; let krate = sym::rustc_serialize;
let typaram = sym::__D; let typaram = sym::__D;
@ -55,6 +56,7 @@ pub fn expand_deriving_rustc_decodable(
})), })),
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)

View File

@ -16,6 +16,7 @@ pub fn expand_deriving_default(
mitem: &ast::MetaItem, mitem: &ast::MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
item.visit_with(&mut DetectNonVariantDefaultAttr { cx }); item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
@ -47,6 +48,7 @@ pub fn expand_deriving_default(
})), })),
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)
} }

View File

@ -100,6 +100,7 @@ pub fn expand_deriving_rustc_encodable(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
let krate = sym::rustc_serialize; let krate = sym::rustc_serialize;
let typaram = sym::__S; let typaram = sym::__S;
@ -139,6 +140,7 @@ pub fn expand_deriving_rustc_encodable(
})), })),
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
trait_def.expand(cx, mitem, item, push) trait_def.expand(cx, mitem, item, push)

View File

@ -171,7 +171,7 @@ use rustc_ast::{GenericArg, GenericParamKind, VariantData};
use rustc_attr as attr; use rustc_attr as attr;
use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span; use rustc_span::{Span, DUMMY_SP};
use std::cell::RefCell; use std::cell::RefCell;
use std::iter; use std::iter;
use std::ops::Not; use std::ops::Not;
@ -204,6 +204,8 @@ pub struct TraitDef<'a> {
pub methods: Vec<MethodDef<'a>>, pub methods: Vec<MethodDef<'a>>,
pub associated_types: Vec<(Ident, Ty)>, pub associated_types: Vec<(Ident, Ty)>,
pub is_const: bool,
} }
pub struct MethodDef<'a> { pub struct MethodDef<'a> {
@ -730,7 +732,7 @@ impl<'a> TraitDef<'a> {
unsafety: ast::Unsafe::No, unsafety: ast::Unsafe::No,
polarity: ast::ImplPolarity::Positive, polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final, defaultness: ast::Defaultness::Final,
constness: ast::Const::No, constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No },
generics: trait_generics, generics: trait_generics,
of_trait: opt_trait_ref, of_trait: opt_trait_ref,
self_ty: self_type, self_ty: self_type,

View File

@ -13,6 +13,7 @@ pub fn expand_deriving_hash(
mitem: &MetaItem, mitem: &MetaItem,
item: &Annotatable, item: &Annotatable,
push: &mut dyn FnMut(Annotatable), push: &mut dyn FnMut(Annotatable),
is_const: bool,
) { ) {
let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std); let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std);
@ -39,6 +40,7 @@ pub fn expand_deriving_hash(
})), })),
}], }],
associated_types: Vec::new(), associated_types: Vec::new(),
is_const,
}; };
hash_trait_def.expand(cx, mitem, item, push); hash_trait_def.expand(cx, mitem, item, push);

View File

@ -38,9 +38,10 @@ pub mod partial_ord;
pub mod generic; pub mod generic;
pub(crate) struct BuiltinDerive( pub(crate) type BuiltinDeriveFn =
pub(crate) fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable)), fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool);
);
pub(crate) struct BuiltinDerive(pub(crate) BuiltinDeriveFn);
impl MultiItemModifier for BuiltinDerive { impl MultiItemModifier for BuiltinDerive {
fn expand( fn expand(
@ -49,6 +50,7 @@ impl MultiItemModifier for BuiltinDerive {
span: Span, span: Span,
meta_item: &MetaItem, meta_item: &MetaItem,
item: Annotatable, item: Annotatable,
is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> { ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
// FIXME: Built-in derives often forget to give spans contexts, // FIXME: Built-in derives often forget to give spans contexts,
// so we are doing it here in a centralized way. // so we are doing it here in a centralized way.
@ -57,21 +59,28 @@ impl MultiItemModifier for BuiltinDerive {
match item { match item {
Annotatable::Stmt(stmt) => { Annotatable::Stmt(stmt) => {
if let ast::StmtKind::Item(item) = stmt.into_inner().kind { if let ast::StmtKind::Item(item) = stmt.into_inner().kind {
(self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| { (self.0)(
// Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx' ecx,
// to the function span,
items.push(Annotatable::Stmt(P(ast::Stmt { meta_item,
id: ast::DUMMY_NODE_ID, &Annotatable::Item(item),
kind: ast::StmtKind::Item(a.expect_item()), &mut |a| {
span, // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
}))); // to the function
}); items.push(Annotatable::Stmt(P(ast::Stmt {
id: ast::DUMMY_NODE_ID,
kind: ast::StmtKind::Item(a.expect_item()),
span,
})));
},
is_derive_const,
);
} else { } else {
unreachable!("should have already errored on non-item statement") unreachable!("should have already errored on non-item statement")
} }
} }
_ => { _ => {
(self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a), is_derive_const);
} }
} }
ExpandResult::Ready(items) ExpandResult::Ready(items)

View File

@ -99,7 +99,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
bench: test::expand_bench, bench: test::expand_bench,
cfg_accessible: cfg_accessible::Expander, cfg_accessible: cfg_accessible::Expander,
cfg_eval: cfg_eval::expand, cfg_eval: cfg_eval::expand,
derive: derive::Expander, derive: derive::Expander(false),
derive_const: derive::Expander(true),
global_allocator: global_allocator::expand, global_allocator: global_allocator::expand,
test: test::expand_test, test: test::expand_test,
test_case: test::expand_test_case, test_case: test::expand_test_case,

View File

@ -250,6 +250,7 @@ pub trait MultiItemModifier {
span: Span, span: Span,
meta_item: &ast::MetaItem, meta_item: &ast::MetaItem,
item: Annotatable, item: Annotatable,
is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable>; ) -> ExpandResult<Vec<Annotatable>, Annotatable>;
} }
@ -263,6 +264,7 @@ where
span: Span, span: Span,
meta_item: &ast::MetaItem, meta_item: &ast::MetaItem,
item: Annotatable, item: Annotatable,
_is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> { ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
ExpandResult::Ready(self(ecx, span, meta_item, item)) ExpandResult::Ready(self(ecx, span, meta_item, item))
} }
@ -873,7 +875,7 @@ impl SyntaxExtension {
/// Error type that denotes indeterminacy. /// Error type that denotes indeterminacy.
pub struct Indeterminate; pub struct Indeterminate;
pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>; pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>, bool)>;
pub trait ResolverExpand { pub trait ResolverExpand {
fn next_node_id(&mut self) -> NodeId; fn next_node_id(&mut self) -> NodeId;

View File

@ -337,6 +337,7 @@ pub enum InvocationKind {
}, },
Derive { Derive {
path: ast::Path, path: ast::Path,
is_const: bool,
item: Annotatable, item: Annotatable,
}, },
} }
@ -478,13 +479,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
derive_invocations.reserve(derives.len()); derive_invocations.reserve(derives.len());
derives derives
.into_iter() .into_iter()
.map(|(path, item, _exts)| { .map(|(path, item, _exts, is_const)| {
// FIXME: Consider using the derive resolutions (`_exts`) // FIXME: Consider using the derive resolutions (`_exts`)
// instead of enqueuing the derives to be resolved again later. // instead of enqueuing the derives to be resolved again later.
let expn_id = LocalExpnId::fresh_empty(); let expn_id = LocalExpnId::fresh_empty();
derive_invocations.push(( derive_invocations.push((
Invocation { Invocation {
kind: InvocationKind::Derive { path, item }, kind: InvocationKind::Derive { path, item, is_const },
fragment_kind, fragment_kind,
expansion_data: ExpansionData { expansion_data: ExpansionData {
id: expn_id, id: expn_id,
@ -717,7 +718,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
SyntaxExtensionKind::LegacyAttr(expander) => { SyntaxExtensionKind::LegacyAttr(expander) => {
match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) { match validate_attr::parse_meta(&self.cx.sess.parse_sess, &attr) {
Ok(meta) => { Ok(meta) => {
let items = match expander.expand(self.cx, span, &meta, item) { let items = match expander.expand(self.cx, span, &meta, item, false) {
ExpandResult::Ready(items) => items, ExpandResult::Ready(items) => items,
ExpandResult::Retry(item) => { ExpandResult::Retry(item) => {
// Reassemble the original invocation for retrying. // Reassemble the original invocation for retrying.
@ -749,19 +750,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
} }
_ => unreachable!(), _ => unreachable!(),
}, },
InvocationKind::Derive { path, item } => match ext { InvocationKind::Derive { path, item, is_const } => match ext {
SyntaxExtensionKind::Derive(expander) SyntaxExtensionKind::Derive(expander)
| SyntaxExtensionKind::LegacyDerive(expander) => { | SyntaxExtensionKind::LegacyDerive(expander) => {
if let SyntaxExtensionKind::Derive(..) = ext { if let SyntaxExtensionKind::Derive(..) = ext {
self.gate_proc_macro_input(&item); self.gate_proc_macro_input(&item);
} }
let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path }; let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path };
let items = match expander.expand(self.cx, span, &meta, item) { let items = match expander.expand(self.cx, span, &meta, item, is_const) {
ExpandResult::Ready(items) => items, ExpandResult::Ready(items) => items,
ExpandResult::Retry(item) => { ExpandResult::Retry(item) => {
// Reassemble the original invocation for retrying. // Reassemble the original invocation for retrying.
return ExpandResult::Retry(Invocation { return ExpandResult::Retry(Invocation {
kind: InvocationKind::Derive { path: meta.path, item }, kind: InvocationKind::Derive { path: meta.path, item, is_const },
..invoc ..invoc
}); });
} }

View File

@ -112,6 +112,7 @@ impl MultiItemModifier for DeriveProcMacro {
span: Span, span: Span,
_meta_item: &ast::MetaItem, _meta_item: &ast::MetaItem,
item: Annotatable, item: Annotatable,
_is_derive_const: bool,
) -> ExpandResult<Vec<Annotatable>, Annotatable> { ) -> ExpandResult<Vec<Annotatable>, Annotatable> {
// We need special handling for statement items // We need special handling for statement items
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`) // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)

View File

@ -356,7 +356,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
has_derive_copy: false, has_derive_copy: false,
}); });
let parent_scope = self.invocation_parent_scopes[&expn_id]; let parent_scope = self.invocation_parent_scopes[&expn_id];
for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() { for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() {
if opt_ext.is_none() { if opt_ext.is_none() {
*opt_ext = Some( *opt_ext = Some(
match self.resolve_macro_path( match self.resolve_macro_path(

View File

@ -620,6 +620,7 @@ symbols! {
deref_mut, deref_mut,
deref_target, deref_target,
derive, derive,
derive_const,
derive_default_enum, derive_default_enum,
destruct, destruct,
destructuring_assignment, destructuring_assignment,

View File

@ -1464,6 +1464,19 @@ pub(crate) mod builtin {
/* compiler built-in */ /* compiler built-in */
} }
/// Attribute macro used to apply derive macros for implementing traits
/// in a const context.
///
/// See [the reference] for more info.
///
/// [the reference]: ../../../reference/attributes/derive.html
#[unstable(feature = "derive_const", issue = "none")]
#[rustc_builtin_macro]
#[cfg(not(bootstrap))]
pub macro derive_const($item:item) {
/* compiler built-in */
}
/// Attribute macro applied to a function to turn it into a unit test. /// Attribute macro applied to a function to turn it into a unit test.
/// ///
/// See [the reference] for more info. /// See [the reference] for more info.

View File

@ -81,6 +81,10 @@ pub use crate::macros::builtin::alloc_error_handler;
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case}; pub use crate::macros::builtin::{bench, derive, global_allocator, test, test_case};
#[unstable(feature = "derive_const", issue = "none")]
#[cfg(not(bootstrap))]
pub use crate::macros::builtin::derive_const;
#[unstable( #[unstable(
feature = "cfg_accessible", feature = "cfg_accessible",
issue = "64797", issue = "64797",

View File

@ -65,6 +65,10 @@ pub use core::prelude::v1::alloc_error_handler;
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case}; pub use core::prelude::v1::{bench, derive, global_allocator, test, test_case};
#[unstable(feature = "derive_const", issue = "none")]
#[cfg(not(bootstrap))]
pub use core::prelude::v1::derive_const;
// Do not `doc(no_inline)` either. // Do not `doc(no_inline)` either.
#[unstable( #[unstable(
feature = "cfg_accessible", feature = "cfg_accessible",

View File

@ -2,18 +2,28 @@ error: cannot find attribute `derive_Clone` in this scope
--> $DIR/issue-32655.rs:3:11 --> $DIR/issue-32655.rs:3:11
| |
LL | #[derive_Clone] LL | #[derive_Clone]
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
... ...
LL | foo!(); LL | foo!();
| ------ in this macro invocation | ------ in this macro invocation
| |
::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
LL | pub macro derive_const($item:item) {
| ---------------------- similarly named attribute macro `derive_const` defined here
|
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find attribute `derive_Clone` in this scope error: cannot find attribute `derive_Clone` in this scope
--> $DIR/issue-32655.rs:15:7 --> $DIR/issue-32655.rs:15:7
| |
LL | #[derive_Clone] LL | #[derive_Clone]
| ^^^^^^^^^^^^ | ^^^^^^^^^^^^ help: an attribute macro with a similar name exists: `derive_const`
|
::: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
LL | pub macro derive_const($item:item) {
| ---------------------- similarly named attribute macro `derive_const` defined here
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -0,0 +1,4 @@
#[derive_const(Default)] //~ ERROR use of unstable library feature
pub struct S;
fn main() {}

View File

@ -0,0 +1,11 @@
error[E0658]: use of unstable library feature 'derive_const'
--> $DIR/derive-const-gate.rs:1:3
|
LL | #[derive_const(Default)]
| ^^^^^^^^^^^^
|
= help: add `#![feature(derive_const)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -0,0 +1,13 @@
#![feature(derive_const)]
pub struct A;
impl Default for A {
fn default() -> A { A }
}
#[derive_const(Default)]
pub struct S(A);
//~^ cannot call non-const fn
fn main() {}

View File

@ -0,0 +1,14 @@
error[E0015]: cannot call non-const fn `<A as Default>::default` in constant functions
--> $DIR/derive-const-non-const-type.rs:10:14
|
LL | #[derive_const(Default)]
| ------- in this derive macro expansion
LL | pub struct S(A);
| ^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -0,0 +1,19 @@
// check-pass
#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
pub struct A;
impl const Default for A {
fn default() -> A { A }
}
impl const PartialEq for A {
fn eq(&self, _: &A) -> bool { true }
}
#[derive_const(Default, PartialEq)]
pub struct S((), A);
const _: () = assert!(S((), A) == S::default());
fn main() {}