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:
commit
4b0b89827d
@ -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());
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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; }`)
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
#[derive_const(Default)] //~ ERROR use of unstable library feature
|
||||||
|
pub struct S;
|
||||||
|
|
||||||
|
fn main() {}
|
@ -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`.
|
@ -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() {}
|
@ -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`.
|
@ -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() {}
|
Loading…
x
Reference in New Issue
Block a user