mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 18:53:39 +00:00
Rollup merge of #98741 - nnethercote:deriving-cleanups, r=Mark-Simulacrum
Many small deriving cleanups These commits remove lots of little unnecessary things, and clarifies other things. r? `@Mark-Simulacrum`
This commit is contained in:
commit
c0cf363ca1
@ -19,7 +19,6 @@ pub fn expand_deriving_copy(
|
||||
path: path_std!(marker::Copy),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: true,
|
||||
methods: Vec::new(),
|
||||
associated_types: Vec::new(),
|
||||
|
@ -15,23 +15,22 @@ pub fn expand_deriving_clone(
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
) {
|
||||
// check if we can use a short form
|
||||
// The simple form is `fn clone(&self) -> Self { *self }`, possibly with
|
||||
// some additional `AssertParamIsClone` assertions.
|
||||
//
|
||||
// the short form is `fn clone(&self) -> Self { *self }`
|
||||
//
|
||||
// we can use the short form if:
|
||||
// - the item is Copy (unfortunately, all we can check is whether it's also deriving Copy)
|
||||
// - there are no generic parameters (after specialization this limitation can be removed)
|
||||
// if we used the short form with generics, we'd have to bound the generics with
|
||||
// Clone + Copy, and then there'd be no Clone impl at all if the user fills in something
|
||||
// that is Clone but not Copy. and until specialization we can't write both impls.
|
||||
// - the item is a union with Copy fields
|
||||
// Unions with generic parameters still can derive Clone because they require Copy
|
||||
// for deriving, Clone alone is not enough.
|
||||
// Wherever Clone is implemented for fields is irrelevant so we don't assert it.
|
||||
// We can use the simple form if either of the following are true.
|
||||
// - The type derives Copy and there are no generic parameters. (If we
|
||||
// used the simple form with generics, we'd have to bound the generics
|
||||
// with Clone + Copy, and then there'd be no Clone impl at all if the
|
||||
// user fills in something that is Clone but not Copy. After
|
||||
// specialization we can remove this no-generics limitation.)
|
||||
// - The item is a union. (Unions with generic parameters still can derive
|
||||
// Clone because they require Copy for deriving, Clone alone is not
|
||||
// enough. Whether Clone is implemented for fields is irrelevant so we
|
||||
// don't assert it.)
|
||||
let bounds;
|
||||
let substructure;
|
||||
let is_shallow;
|
||||
let is_simple;
|
||||
match *item {
|
||||
Annotatable::Item(ref annitem) => match annitem.kind {
|
||||
ItemKind::Struct(_, Generics { ref params, .. })
|
||||
@ -44,30 +43,25 @@ pub fn expand_deriving_clone(
|
||||
.any(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }))
|
||||
{
|
||||
bounds = vec![];
|
||||
is_shallow = true;
|
||||
is_simple = true;
|
||||
substructure = combine_substructure(Box::new(|c, s, sub| {
|
||||
cs_clone_shallow("Clone", c, s, sub, false)
|
||||
cs_clone_simple("Clone", c, s, sub, false)
|
||||
}));
|
||||
} else {
|
||||
bounds = vec![];
|
||||
is_shallow = false;
|
||||
is_simple = false;
|
||||
substructure =
|
||||
combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub)));
|
||||
}
|
||||
}
|
||||
ItemKind::Union(..) => {
|
||||
bounds = vec![Literal(path_std!(marker::Copy))];
|
||||
is_shallow = true;
|
||||
bounds = vec![Path(path_std!(marker::Copy))];
|
||||
is_simple = true;
|
||||
substructure = combine_substructure(Box::new(|c, s, sub| {
|
||||
cs_clone_shallow("Clone", c, s, sub, true)
|
||||
cs_clone_simple("Clone", c, s, sub, true)
|
||||
}));
|
||||
}
|
||||
_ => {
|
||||
bounds = vec![];
|
||||
is_shallow = false;
|
||||
substructure =
|
||||
combine_substructure(Box::new(|c, s, sub| cs_clone("Clone", c, s, sub)));
|
||||
}
|
||||
_ => cx.span_bug(span, "`#[derive(Clone)]` on wrong item kind"),
|
||||
},
|
||||
|
||||
_ => cx.span_bug(span, "`#[derive(Clone)]` on trait item or impl item"),
|
||||
@ -81,26 +75,24 @@ pub fn expand_deriving_clone(
|
||||
path: path_std!(clone::Clone),
|
||||
additional_bounds: bounds,
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: true,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::clone,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
explicit_self: true,
|
||||
args: Vec::new(),
|
||||
ret_ty: Self_,
|
||||
attributes: attrs,
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: false,
|
||||
combine_substructure: substructure,
|
||||
}],
|
||||
associated_types: Vec::new(),
|
||||
};
|
||||
|
||||
trait_def.expand_ext(cx, mitem, item, push, is_shallow)
|
||||
trait_def.expand_ext(cx, mitem, item, push, is_simple)
|
||||
}
|
||||
|
||||
fn cs_clone_shallow(
|
||||
fn cs_clone_simple(
|
||||
name: &str,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
@ -143,7 +135,7 @@ fn cs_clone_shallow(
|
||||
}
|
||||
_ => cx.span_bug(
|
||||
trait_span,
|
||||
&format!("unexpected substructure in shallow `derive({})`", name),
|
||||
&format!("unexpected substructure in simple `derive({})`", name),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -27,16 +27,14 @@ pub fn expand_deriving_eq(
|
||||
path: path_std!(cmp::Eq),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: true,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::assert_receiver_is_total_eq,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
explicit_self: true,
|
||||
args: vec![],
|
||||
ret_ty: nil_ty(),
|
||||
ret_ty: Unit,
|
||||
attributes: attrs,
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: true,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
cs_total_eq_assert(a, b, c)
|
||||
|
@ -23,16 +23,14 @@ pub fn expand_deriving_ord(
|
||||
path: path_std!(cmp::Ord),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::cmp,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![(borrowed_self(), sym::other)],
|
||||
ret_ty: Literal(path_std!(cmp::Ordering)),
|
||||
explicit_self: true,
|
||||
args: vec![(self_ref(), sym::other)],
|
||||
ret_ty: Path(path_std!(cmp::Ordering)),
|
||||
attributes: attrs,
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: true,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
|
||||
}],
|
||||
@ -99,8 +97,8 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P<
|
||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
||||
},
|
||||
cx.expr_path(equals_path.clone()),
|
||||
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
|
||||
if self_args.len() != 2 {
|
||||
Box::new(|cx, span, tag_tuple| {
|
||||
if tag_tuple.len() != 2 {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
|
||||
} else {
|
||||
ordering_collapsed(cx, span, tag_tuple)
|
||||
|
@ -48,7 +48,7 @@ pub fn expand_deriving_partial_eq(
|
||||
None => cx.expr_bool(span, base),
|
||||
}
|
||||
},
|
||||
Box::new(|cx, span, _, _| cx.expr_bool(span, !base)),
|
||||
Box::new(|cx, span, _| cx.expr_bool(span, !base)),
|
||||
cx,
|
||||
span,
|
||||
substr,
|
||||
@ -69,11 +69,10 @@ pub fn expand_deriving_partial_eq(
|
||||
MethodDef {
|
||||
name: $name,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![(borrowed_self(), sym::other)],
|
||||
ret_ty: Literal(path_local!(bool)),
|
||||
explicit_self: true,
|
||||
args: vec![(self_ref(), sym::other)],
|
||||
ret_ty: Path(path_local!(bool)),
|
||||
attributes: attrs,
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: true,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| $f(a, b, c))),
|
||||
}
|
||||
@ -102,7 +101,6 @@ pub fn expand_deriving_partial_eq(
|
||||
path: path_std!(cmp::PartialEq),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods,
|
||||
associated_types: Vec::new(),
|
||||
|
@ -15,13 +15,9 @@ pub fn expand_deriving_partial_ord(
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
) {
|
||||
let ordering_ty = Literal(path_std!(cmp::Ordering));
|
||||
let ret_ty = Literal(Path::new_(
|
||||
pathvec_std!(option::Option),
|
||||
None,
|
||||
vec![Box::new(ordering_ty)],
|
||||
PathKind::Std,
|
||||
));
|
||||
let ordering_ty = Path(path_std!(cmp::Ordering));
|
||||
let ret_ty =
|
||||
Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
|
||||
|
||||
let inline = cx.meta_word(span, sym::inline);
|
||||
let attrs = vec![cx.attribute(inline)];
|
||||
@ -29,11 +25,10 @@ pub fn expand_deriving_partial_ord(
|
||||
let partial_cmp_def = MethodDef {
|
||||
name: sym::partial_cmp,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![(borrowed_self(), sym::other)],
|
||||
explicit_self: true,
|
||||
args: vec![(self_ref(), sym::other)],
|
||||
ret_ty,
|
||||
attributes: attrs,
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: true,
|
||||
combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
|
||||
cs_partial_cmp(cx, span, substr)
|
||||
@ -46,7 +41,6 @@ pub fn expand_deriving_partial_ord(
|
||||
path: path_std!(cmp::PartialOrd),
|
||||
additional_bounds: vec![],
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![partial_cmp_def],
|
||||
associated_types: Vec::new(),
|
||||
@ -102,8 +96,8 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_
|
||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
||||
},
|
||||
equals_expr,
|
||||
Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
|
||||
if self_args.len() != 2 {
|
||||
Box::new(|cx, span, tag_tuple| {
|
||||
if tag_tuple.len() != 2 {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
|
||||
} else {
|
||||
let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0]));
|
||||
|
@ -16,8 +16,7 @@ pub fn expand_deriving_debug(
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
) {
|
||||
// &mut ::std::fmt::Formatter
|
||||
let fmtr =
|
||||
Ptr(Box::new(Literal(path_std!(fmt::Formatter))), Borrowed(None, ast::Mutability::Mut));
|
||||
let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut);
|
||||
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
@ -25,16 +24,14 @@ pub fn expand_deriving_debug(
|
||||
path: path_std!(fmt::Debug),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::fmt,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
explicit_self: true,
|
||||
args: vec![(fmtr, sym::f)],
|
||||
ret_ty: Literal(path_std!(fmt::Result)),
|
||||
ret_ty: Path(path_std!(fmt::Result)),
|
||||
attributes: Vec::new(),
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: false,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
show_substructure(a, b, c)
|
||||
@ -64,8 +61,6 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
||||
let (is_struct, args_per_field) = match vdata {
|
||||
ast::VariantData::Unit(..) => {
|
||||
// Special fast path for unit variants.
|
||||
//let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
|
||||
//return cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]);
|
||||
assert!(fields.is_empty());
|
||||
(false, 0)
|
||||
}
|
||||
|
@ -23,40 +23,29 @@ pub fn expand_deriving_rustc_decodable(
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: Path::new_(vec![krate, sym::Decodable], None, vec![], PathKind::Global),
|
||||
path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::decode,
|
||||
generics: Bounds {
|
||||
bounds: vec![(
|
||||
typaram,
|
||||
vec![Path::new_(vec![krate, sym::Decoder], None, vec![], PathKind::Global)],
|
||||
vec![Path::new_(vec![krate, sym::Decoder], vec![], PathKind::Global)],
|
||||
)],
|
||||
},
|
||||
explicit_self: None,
|
||||
args: vec![(
|
||||
Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
|
||||
sym::d,
|
||||
)],
|
||||
ret_ty: Literal(Path::new_(
|
||||
explicit_self: false,
|
||||
args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::d)],
|
||||
ret_ty: Path(Path::new_(
|
||||
pathvec_std!(result::Result),
|
||||
None,
|
||||
vec![
|
||||
Box::new(Self_),
|
||||
Box::new(Literal(Path::new_(
|
||||
vec![typaram, sym::Error],
|
||||
None,
|
||||
vec![],
|
||||
PathKind::Local,
|
||||
))),
|
||||
Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))),
|
||||
],
|
||||
PathKind::Std,
|
||||
)),
|
||||
attributes: Vec::new(),
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: false,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
decodable_substructure(a, b, c, krate)
|
||||
|
@ -30,16 +30,14 @@ pub fn expand_deriving_default(
|
||||
path: Path::new(vec![kw::Default, sym::Default]),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: kw::Default,
|
||||
generics: Bounds::empty(),
|
||||
explicit_self: None,
|
||||
explicit_self: false,
|
||||
args: Vec::new(),
|
||||
ret_ty: Self_,
|
||||
attributes: attrs,
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: false,
|
||||
combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| {
|
||||
match substr.fields {
|
||||
|
@ -108,40 +108,29 @@ pub fn expand_deriving_rustc_encodable(
|
||||
let trait_def = TraitDef {
|
||||
span,
|
||||
attributes: Vec::new(),
|
||||
path: Path::new_(vec![krate, sym::Encodable], None, vec![], PathKind::Global),
|
||||
path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global),
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::encode,
|
||||
generics: Bounds {
|
||||
bounds: vec![(
|
||||
typaram,
|
||||
vec![Path::new_(vec![krate, sym::Encoder], None, vec![], PathKind::Global)],
|
||||
vec![Path::new_(vec![krate, sym::Encoder], vec![], PathKind::Global)],
|
||||
)],
|
||||
},
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![(
|
||||
Ptr(Box::new(Literal(Path::new_local(typaram))), Borrowed(None, Mutability::Mut)),
|
||||
sym::s,
|
||||
)],
|
||||
ret_ty: Literal(Path::new_(
|
||||
explicit_self: true,
|
||||
args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::s)],
|
||||
ret_ty: Path(Path::new_(
|
||||
pathvec_std!(result::Result),
|
||||
None,
|
||||
vec![
|
||||
Box::new(Tuple(Vec::new())),
|
||||
Box::new(Literal(Path::new_(
|
||||
vec![typaram, sym::Error],
|
||||
None,
|
||||
vec![],
|
||||
PathKind::Local,
|
||||
))),
|
||||
Box::new(Unit),
|
||||
Box::new(Path(Path::new_(vec![typaram, sym::Error], vec![], PathKind::Local))),
|
||||
],
|
||||
PathKind::Std,
|
||||
)),
|
||||
attributes: Vec::new(),
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: false,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
encodable_substructure(a, b, c, krate)
|
||||
|
@ -146,8 +146,6 @@
|
||||
//!
|
||||
//! ```{.text}
|
||||
//! EnumNonMatchingCollapsed(
|
||||
//! vec![<ident of self>, <ident of __arg_1>],
|
||||
//! &[<ast::Variant for C0>, <ast::Variant for C1>],
|
||||
//! &[<ident for self index value>, <ident of __arg_1 index value>])
|
||||
//! ```
|
||||
//!
|
||||
@ -190,7 +188,7 @@ use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
use ty::{Bounds, Path, Ptr, PtrTy, Self_, Ty};
|
||||
use ty::{Bounds, Path, Ref, Self_, Ty};
|
||||
|
||||
use crate::deriving;
|
||||
|
||||
@ -212,9 +210,6 @@ pub struct TraitDef<'a> {
|
||||
/// Any extra lifetimes and/or bounds, e.g., `D: serialize::Decoder`
|
||||
pub generics: Bounds,
|
||||
|
||||
/// Is it an `unsafe` trait?
|
||||
pub is_unsafe: bool,
|
||||
|
||||
/// Can this trait be derived for unions?
|
||||
pub supports_unions: bool,
|
||||
|
||||
@ -229,10 +224,8 @@ pub struct MethodDef<'a> {
|
||||
/// List of generics, e.g., `R: rand::Rng`
|
||||
pub generics: Bounds,
|
||||
|
||||
/// Whether there is a self argument (outer Option) i.e., whether
|
||||
/// this is a static function, and whether it is a pointer (inner
|
||||
/// Option)
|
||||
pub explicit_self: Option<Option<PtrTy>>,
|
||||
/// Is there is a `&self` argument? If not, it is a static function.
|
||||
pub explicit_self: bool,
|
||||
|
||||
/// Arguments other than the self argument
|
||||
pub args: Vec<(Ty, Symbol)>,
|
||||
@ -242,9 +235,6 @@ pub struct MethodDef<'a> {
|
||||
|
||||
pub attributes: Vec<ast::Attribute>,
|
||||
|
||||
// Is it an `unsafe fn`?
|
||||
pub is_unsafe: bool,
|
||||
|
||||
/// Can we combine fieldless variants for enums into a single match arm?
|
||||
pub unify_fieldless_variants: bool,
|
||||
|
||||
@ -255,14 +245,7 @@ pub struct MethodDef<'a> {
|
||||
pub struct Substructure<'a> {
|
||||
/// ident of self
|
||||
pub type_ident: Ident,
|
||||
/// ident of the method
|
||||
pub method_ident: Ident,
|
||||
/// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)`][ptr] arguments
|
||||
///
|
||||
/// [`Self_`]: ty::Ty::Self_
|
||||
/// [ptr]: ty::Ty::Ptr
|
||||
pub self_args: &'a [P<Expr>],
|
||||
/// verbatim access to any other arguments
|
||||
/// verbatim access to any non-self arguments
|
||||
pub nonself_args: &'a [P<Expr>],
|
||||
pub fields: &'a SubstructureFields<'a>,
|
||||
}
|
||||
@ -299,13 +282,10 @@ pub enum SubstructureFields<'a> {
|
||||
/// variant.
|
||||
EnumMatching(usize, usize, &'a ast::Variant, Vec<FieldInfo<'a>>),
|
||||
|
||||
/// Non-matching variants of the enum, but with all state hidden from
|
||||
/// the consequent code. The first component holds `Ident`s for all of
|
||||
/// the `Self` arguments; the second component is a slice of all of the
|
||||
/// variants for the enum itself, and the third component is a list of
|
||||
/// `Ident`s bound to the variant index values for each of the actual
|
||||
/// input `Self` arguments.
|
||||
EnumNonMatchingCollapsed(Vec<Ident>, &'a [ast::Variant], &'a [Ident]),
|
||||
/// Non-matching variants of the enum, but with all state hidden from the
|
||||
/// consequent code. The field is a list of `Ident`s bound to the variant
|
||||
/// index values for each of the actual input `Self` arguments.
|
||||
EnumNonMatchingCollapsed(&'a [Ident]),
|
||||
|
||||
/// A static method where `Self` is a struct.
|
||||
StaticStruct(&'a ast::VariantData, StaticFields),
|
||||
@ -318,13 +298,10 @@ pub enum SubstructureFields<'a> {
|
||||
pub type CombineSubstructureFunc<'a> =
|
||||
Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &Substructure<'_>) -> P<Expr> + 'a>;
|
||||
|
||||
/// Deal with non-matching enum variants. The tuple is a list of
|
||||
/// identifiers (one for each `Self` argument, which could be any of the
|
||||
/// variants since they have been collapsed together) and the identifiers
|
||||
/// holding the variant index value for each of the `Self` arguments. The
|
||||
/// last argument is all the non-`Self` args of the method being derived.
|
||||
/// Deal with non-matching enum variants. The slice is the identifiers holding
|
||||
/// the variant index value for each of the `Self` arguments.
|
||||
pub type EnumNonMatchCollapsedFunc<'a> =
|
||||
Box<dyn FnMut(&mut ExtCtxt<'_>, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
|
||||
Box<dyn FnMut(&mut ExtCtxt<'_>, Span, &[Ident]) -> P<Expr> + 'a>;
|
||||
|
||||
pub fn combine_substructure(
|
||||
f: CombineSubstructureFunc<'_>,
|
||||
@ -727,14 +704,12 @@ impl<'a> TraitDef<'a> {
|
||||
let mut a = vec![attr, unused_qual];
|
||||
a.extend(self.attributes.iter().cloned());
|
||||
|
||||
let unsafety = if self.is_unsafe { ast::Unsafe::Yes(self.span) } else { ast::Unsafe::No };
|
||||
|
||||
cx.item(
|
||||
self.span,
|
||||
Ident::empty(),
|
||||
a,
|
||||
ast::ItemKind::Impl(Box::new(ast::Impl {
|
||||
unsafety,
|
||||
unsafety: ast::Unsafe::No,
|
||||
polarity: ast::ImplPolarity::Positive,
|
||||
defaultness: ast::Defaultness::Final,
|
||||
constness: ast::Const::No,
|
||||
@ -771,7 +746,6 @@ impl<'a> TraitDef<'a> {
|
||||
self,
|
||||
struct_def,
|
||||
type_ident,
|
||||
&self_args,
|
||||
&nonself_args,
|
||||
)
|
||||
} else {
|
||||
@ -820,7 +794,6 @@ impl<'a> TraitDef<'a> {
|
||||
self,
|
||||
enum_def,
|
||||
type_ident,
|
||||
&self_args,
|
||||
&nonself_args,
|
||||
)
|
||||
} else {
|
||||
@ -848,18 +821,11 @@ impl<'a> MethodDef<'a> {
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
trait_: &TraitDef<'_>,
|
||||
type_ident: Ident,
|
||||
self_args: &[P<Expr>],
|
||||
nonself_args: &[P<Expr>],
|
||||
fields: &SubstructureFields<'_>,
|
||||
) -> P<Expr> {
|
||||
let span = trait_.span;
|
||||
let substructure = Substructure {
|
||||
type_ident,
|
||||
method_ident: Ident::new(self.name, span),
|
||||
self_args,
|
||||
nonself_args,
|
||||
fields,
|
||||
};
|
||||
let substructure = Substructure { type_ident, nonself_args, fields };
|
||||
let mut f = self.combine_substructure.borrow_mut();
|
||||
let f: &mut CombineSubstructureFunc<'_> = &mut *f;
|
||||
f(cx, span, &substructure)
|
||||
@ -876,7 +842,7 @@ impl<'a> MethodDef<'a> {
|
||||
}
|
||||
|
||||
fn is_static(&self) -> bool {
|
||||
self.explicit_self.is_none()
|
||||
!self.explicit_self
|
||||
}
|
||||
|
||||
fn split_self_nonself_args(
|
||||
@ -889,17 +855,15 @@ impl<'a> MethodDef<'a> {
|
||||
let mut self_args = Vec::new();
|
||||
let mut nonself_args = Vec::new();
|
||||
let mut arg_tys = Vec::new();
|
||||
let mut nonstatic = false;
|
||||
let span = trait_.span;
|
||||
|
||||
let ast_explicit_self = self.explicit_self.as_ref().map(|self_ptr| {
|
||||
let (self_expr, explicit_self) = ty::get_explicit_self(cx, span, self_ptr);
|
||||
|
||||
let ast_explicit_self = if self.explicit_self {
|
||||
let (self_expr, explicit_self) = ty::get_explicit_self(cx, span);
|
||||
self_args.push(self_expr);
|
||||
nonstatic = true;
|
||||
|
||||
explicit_self
|
||||
});
|
||||
Some(explicit_self)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
for (ty, name) in self.args.iter() {
|
||||
let ast_ty = ty.to_ty(cx, span, type_ident, generics);
|
||||
@ -911,10 +875,10 @@ impl<'a> MethodDef<'a> {
|
||||
match *ty {
|
||||
// for static methods, just treat any Self
|
||||
// arguments as a normal arg
|
||||
Self_ if nonstatic => {
|
||||
Self_ if !self.is_static() => {
|
||||
self_args.push(arg_expr);
|
||||
}
|
||||
Ptr(ref ty, _) if matches!(**ty, Self_) && nonstatic => {
|
||||
Ref(ref ty, _) if matches!(**ty, Self_) && !self.is_static() => {
|
||||
self_args.push(cx.expr_deref(span, arg_expr))
|
||||
}
|
||||
_ => {
|
||||
@ -955,15 +919,9 @@ impl<'a> MethodDef<'a> {
|
||||
let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type));
|
||||
let body_block = cx.block_expr(body);
|
||||
|
||||
let unsafety = if self.is_unsafe { ast::Unsafe::Yes(span) } else { ast::Unsafe::No };
|
||||
|
||||
let trait_lo_sp = span.shrink_to_lo();
|
||||
|
||||
let sig = ast::FnSig {
|
||||
header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() },
|
||||
decl: fn_decl,
|
||||
span,
|
||||
};
|
||||
let sig = ast::FnSig { header: ast::FnHeader::default(), decl: fn_decl, span };
|
||||
let defaultness = ast::Defaultness::Final;
|
||||
|
||||
// Create the method.
|
||||
@ -1083,7 +1041,6 @@ impl<'a> MethodDef<'a> {
|
||||
cx,
|
||||
trait_,
|
||||
type_ident,
|
||||
self_args,
|
||||
nonself_args,
|
||||
&Struct(struct_def, fields),
|
||||
);
|
||||
@ -1104,7 +1061,6 @@ impl<'a> MethodDef<'a> {
|
||||
trait_: &TraitDef<'_>,
|
||||
struct_def: &VariantData,
|
||||
type_ident: Ident,
|
||||
self_args: &[P<Expr>],
|
||||
nonself_args: &[P<Expr>],
|
||||
) -> P<Expr> {
|
||||
let summary = trait_.summarise_struct(cx, struct_def);
|
||||
@ -1113,7 +1069,6 @@ impl<'a> MethodDef<'a> {
|
||||
cx,
|
||||
trait_,
|
||||
type_ident,
|
||||
self_args,
|
||||
nonself_args,
|
||||
&StaticStruct(struct_def, summary),
|
||||
)
|
||||
@ -1184,11 +1139,6 @@ impl<'a> MethodDef<'a> {
|
||||
)
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
let self_arg_idents = self_arg_names
|
||||
.iter()
|
||||
.map(|name| Ident::from_str_and_span(name, span))
|
||||
.collect::<Vec<Ident>>();
|
||||
|
||||
// The `vi_idents` will be bound, solely in the catch-all, to
|
||||
// a series of let statements mapping each self_arg to an int
|
||||
// value corresponding to its discriminant.
|
||||
@ -1203,8 +1153,7 @@ impl<'a> MethodDef<'a> {
|
||||
// Builds, via callback to call_substructure_method, the
|
||||
// delegated expression that handles the catch-all case,
|
||||
// using `__variants_tuple` to drive logic if necessary.
|
||||
let catch_all_substructure =
|
||||
EnumNonMatchingCollapsed(self_arg_idents, &variants, &vi_idents);
|
||||
let catch_all_substructure = EnumNonMatchingCollapsed(&vi_idents);
|
||||
|
||||
let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty());
|
||||
|
||||
@ -1303,7 +1252,6 @@ impl<'a> MethodDef<'a> {
|
||||
cx,
|
||||
trait_,
|
||||
type_ident,
|
||||
&self_args[..],
|
||||
nonself_args,
|
||||
&substructure,
|
||||
);
|
||||
@ -1322,7 +1270,6 @@ impl<'a> MethodDef<'a> {
|
||||
cx,
|
||||
trait_,
|
||||
type_ident,
|
||||
&self_args[..],
|
||||
nonself_args,
|
||||
&substructure,
|
||||
))
|
||||
@ -1393,7 +1340,6 @@ impl<'a> MethodDef<'a> {
|
||||
cx,
|
||||
trait_,
|
||||
type_ident,
|
||||
&self_args[..],
|
||||
nonself_args,
|
||||
&catch_all_substructure,
|
||||
);
|
||||
@ -1491,7 +1437,6 @@ impl<'a> MethodDef<'a> {
|
||||
trait_: &TraitDef<'_>,
|
||||
enum_def: &EnumDef,
|
||||
type_ident: Ident,
|
||||
self_args: &[P<Expr>],
|
||||
nonself_args: &[P<Expr>],
|
||||
) -> P<Expr> {
|
||||
let summary = enum_def
|
||||
@ -1507,7 +1452,6 @@ impl<'a> MethodDef<'a> {
|
||||
cx,
|
||||
trait_,
|
||||
type_ident,
|
||||
self_args,
|
||||
nonself_args,
|
||||
&StaticEnum(enum_def, summary),
|
||||
)
|
||||
@ -1628,7 +1572,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
// helpful premade recipes
|
||||
|
||||
pub fn cs_fold_fields<'a, F>(
|
||||
fn cs_fold_fields<'a, F>(
|
||||
use_foldl: bool,
|
||||
mut f: F,
|
||||
base: P<Expr>,
|
||||
@ -1650,21 +1594,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cs_fold_enumnonmatch(
|
||||
fn cs_fold_enumnonmatch(
|
||||
mut enum_nonmatch_f: EnumNonMatchCollapsedFunc<'_>,
|
||||
cx: &mut ExtCtxt<'_>,
|
||||
trait_span: Span,
|
||||
substructure: &Substructure<'_>,
|
||||
) -> P<Expr> {
|
||||
match *substructure.fields {
|
||||
EnumNonMatchingCollapsed(ref all_args, _, tuple) => {
|
||||
enum_nonmatch_f(cx, trait_span, (&all_args[..], tuple), substructure.nonself_args)
|
||||
}
|
||||
EnumNonMatchingCollapsed(tuple) => enum_nonmatch_f(cx, trait_span, tuple),
|
||||
_ => cx.span_bug(trait_span, "cs_fold_enumnonmatch expected an EnumNonMatchingCollapsed"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cs_fold_static(cx: &mut ExtCtxt<'_>, trait_span: Span) -> P<Expr> {
|
||||
fn cs_fold_static(cx: &mut ExtCtxt<'_>, trait_span: Span) -> P<Expr> {
|
||||
cx.span_bug(trait_span, "static function in `derive`")
|
||||
}
|
||||
|
||||
@ -1717,22 +1659,21 @@ where
|
||||
{
|
||||
match *substructure.fields {
|
||||
EnumMatching(.., ref all_fields) | Struct(_, ref all_fields) => {
|
||||
let (base, all_fields) = match (all_fields.is_empty(), use_foldl) {
|
||||
let (base, rest) = match (all_fields.is_empty(), use_foldl) {
|
||||
(false, true) => {
|
||||
let field = &all_fields[0];
|
||||
let args = (field.span, field.self_.clone(), &field.other[..]);
|
||||
(b(cx, Some(args)), &all_fields[1..])
|
||||
let (first, rest) = all_fields.split_first().unwrap();
|
||||
let args = (first.span, first.self_.clone(), &first.other[..]);
|
||||
(b(cx, Some(args)), rest)
|
||||
}
|
||||
(false, false) => {
|
||||
let idx = all_fields.len() - 1;
|
||||
let field = &all_fields[idx];
|
||||
let args = (field.span, field.self_.clone(), &field.other[..]);
|
||||
(b(cx, Some(args)), &all_fields[..idx])
|
||||
let (last, rest) = all_fields.split_last().unwrap();
|
||||
let args = (last.span, last.self_.clone(), &last.other[..]);
|
||||
(b(cx, Some(args)), rest)
|
||||
}
|
||||
(true, _) => (b(cx, None), &all_fields[..]),
|
||||
};
|
||||
|
||||
cs_fold_fields(use_foldl, f, base, cx, all_fields)
|
||||
cs_fold_fields(use_foldl, f, base, cx, rest)
|
||||
}
|
||||
EnumNonMatchingCollapsed(..) => {
|
||||
cs_fold_enumnonmatch(enum_nonmatch_f, cx, trait_span, substructure)
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use
|
||||
//! when specifying impls to be derived.
|
||||
|
||||
pub use PtrTy::*;
|
||||
pub use Ty::*;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
@ -11,22 +10,11 @@ use rustc_span::source_map::{respan, DUMMY_SP};
|
||||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
/// The types of pointers
|
||||
#[derive(Clone)]
|
||||
pub enum PtrTy {
|
||||
/// &'lifetime mut
|
||||
Borrowed(Option<Ident>, ast::Mutability),
|
||||
/// *mut
|
||||
#[allow(dead_code)]
|
||||
Raw(ast::Mutability),
|
||||
}
|
||||
|
||||
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support
|
||||
/// for type parameters and a lifetime.
|
||||
/// for type parameters.
|
||||
#[derive(Clone)]
|
||||
pub struct Path {
|
||||
path: Vec<Symbol>,
|
||||
lifetime: Option<Ident>,
|
||||
params: Vec<Box<Ty>>,
|
||||
kind: PathKind,
|
||||
}
|
||||
@ -40,18 +28,13 @@ pub enum PathKind {
|
||||
|
||||
impl Path {
|
||||
pub fn new(path: Vec<Symbol>) -> Path {
|
||||
Path::new_(path, None, Vec::new(), PathKind::Std)
|
||||
Path::new_(path, Vec::new(), PathKind::Std)
|
||||
}
|
||||
pub fn new_local(path: Symbol) -> Path {
|
||||
Path::new_(vec![path], None, Vec::new(), PathKind::Local)
|
||||
Path::new_(vec![path], Vec::new(), PathKind::Local)
|
||||
}
|
||||
pub fn new_(
|
||||
path: Vec<Symbol>,
|
||||
lifetime: Option<Ident>,
|
||||
params: Vec<Box<Ty>>,
|
||||
kind: PathKind,
|
||||
) -> Path {
|
||||
Path { path, lifetime, params, kind }
|
||||
pub fn new_(path: Vec<Symbol>, params: Vec<Box<Ty>>, kind: PathKind) -> Path {
|
||||
Path { path, params, kind }
|
||||
}
|
||||
|
||||
pub fn to_ty(
|
||||
@ -71,10 +54,8 @@ impl Path {
|
||||
self_generics: &Generics,
|
||||
) -> ast::Path {
|
||||
let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect();
|
||||
let lt = mk_lifetimes(cx, span, &self.lifetime);
|
||||
let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics));
|
||||
let params =
|
||||
lt.into_iter().map(GenericArg::Lifetime).chain(tys.map(GenericArg::Type)).collect();
|
||||
let params = tys.map(GenericArg::Type).collect();
|
||||
|
||||
match self.kind {
|
||||
PathKind::Global => cx.path_all(span, true, idents, params),
|
||||
@ -92,40 +73,17 @@ impl Path {
|
||||
#[derive(Clone)]
|
||||
pub enum Ty {
|
||||
Self_,
|
||||
/// &/Box/ Ty
|
||||
Ptr(Box<Ty>, PtrTy),
|
||||
/// A reference.
|
||||
Ref(Box<Ty>, ast::Mutability),
|
||||
/// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type
|
||||
/// parameter, and things like `i32`
|
||||
Literal(Path),
|
||||
/// includes unit
|
||||
Tuple(Vec<Ty>),
|
||||
Path(Path),
|
||||
/// For () return types.
|
||||
Unit,
|
||||
}
|
||||
|
||||
pub fn borrowed_ptrty() -> PtrTy {
|
||||
Borrowed(None, ast::Mutability::Not)
|
||||
}
|
||||
pub fn borrowed(ty: Box<Ty>) -> Ty {
|
||||
Ptr(ty, borrowed_ptrty())
|
||||
}
|
||||
|
||||
pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
|
||||
Some(Some(borrowed_ptrty()))
|
||||
}
|
||||
|
||||
pub fn borrowed_self() -> Ty {
|
||||
borrowed(Box::new(Self_))
|
||||
}
|
||||
|
||||
pub fn nil_ty() -> Ty {
|
||||
Tuple(Vec::new())
|
||||
}
|
||||
|
||||
fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Option<ast::Lifetime> {
|
||||
lt.map(|ident| cx.lifetime(span, ident))
|
||||
}
|
||||
|
||||
fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<Ident>) -> Vec<ast::Lifetime> {
|
||||
mk_lifetime(cx, span, lt).into_iter().collect()
|
||||
pub fn self_ref() -> Ty {
|
||||
Ref(Box::new(Self_), ast::Mutability::Not)
|
||||
}
|
||||
|
||||
impl Ty {
|
||||
@ -136,23 +94,15 @@ impl Ty {
|
||||
self_ty: Ident,
|
||||
self_generics: &Generics,
|
||||
) -> P<ast::Ty> {
|
||||
match *self {
|
||||
Ptr(ref ty, ref ptr) => {
|
||||
match self {
|
||||
Ref(ty, mutbl) => {
|
||||
let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
|
||||
match *ptr {
|
||||
Borrowed(ref lt, mutbl) => {
|
||||
let lt = mk_lifetime(cx, span, lt);
|
||||
cx.ty_rptr(span, raw_ty, lt, mutbl)
|
||||
}
|
||||
Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl),
|
||||
}
|
||||
cx.ty_rptr(span, raw_ty, None, *mutbl)
|
||||
}
|
||||
Literal(ref p) => p.to_ty(cx, span, self_ty, self_generics),
|
||||
Path(p) => p.to_ty(cx, span, self_ty, self_generics),
|
||||
Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)),
|
||||
Tuple(ref fields) => {
|
||||
let ty = ast::TyKind::Tup(
|
||||
fields.iter().map(|f| f.to_ty(cx, span, self_ty, self_generics)).collect(),
|
||||
);
|
||||
Unit => {
|
||||
let ty = ast::TyKind::Tup(vec![]);
|
||||
cx.ty(span, ty)
|
||||
}
|
||||
}
|
||||
@ -185,9 +135,9 @@ impl Ty {
|
||||
|
||||
cx.path_all(span, false, vec![self_ty], params)
|
||||
}
|
||||
Literal(ref p) => p.to_path(cx, span, self_ty, generics),
|
||||
Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"),
|
||||
Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"),
|
||||
Path(ref p) => p.to_path(cx, span, self_ty, generics),
|
||||
Ref(..) => cx.span_bug(span, "ref in a path in generic `derive`"),
|
||||
Unit => cx.span_bug(span, "unit in a path in generic `derive`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -245,28 +195,10 @@ impl Bounds {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_explicit_self(
|
||||
cx: &ExtCtxt<'_>,
|
||||
span: Span,
|
||||
self_ptr: &Option<PtrTy>,
|
||||
) -> (P<Expr>, ast::ExplicitSelf) {
|
||||
pub fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P<Expr>, ast::ExplicitSelf) {
|
||||
// this constructs a fresh `self` path
|
||||
let self_path = cx.expr_self(span);
|
||||
match *self_ptr {
|
||||
None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Not))),
|
||||
Some(ref ptr) => {
|
||||
let self_ty = respan(
|
||||
span,
|
||||
match *ptr {
|
||||
Borrowed(ref lt, mutbl) => {
|
||||
let lt = lt.map(|s| cx.lifetime(span, s));
|
||||
SelfKind::Region(lt, mutbl)
|
||||
}
|
||||
Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition"),
|
||||
},
|
||||
);
|
||||
let self_expr = cx.expr_deref(span, self_path);
|
||||
(self_expr, self_ty)
|
||||
}
|
||||
}
|
||||
let self_ty = respan(span, SelfKind::Region(None, ast::Mutability::Not));
|
||||
let self_expr = cx.expr_deref(span, self_path);
|
||||
(self_expr, self_ty)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ pub fn expand_deriving_hash(
|
||||
item: &Annotatable,
|
||||
push: &mut dyn FnMut(Annotatable),
|
||||
) {
|
||||
let path = Path::new_(pathvec_std!(hash::Hash), None, vec![], PathKind::Std);
|
||||
let path = Path::new_(pathvec_std!(hash::Hash), vec![], PathKind::Std);
|
||||
|
||||
let typaram = sym::__H;
|
||||
|
||||
@ -26,16 +26,14 @@ pub fn expand_deriving_hash(
|
||||
path,
|
||||
additional_bounds: Vec::new(),
|
||||
generics: Bounds::empty(),
|
||||
is_unsafe: false,
|
||||
supports_unions: false,
|
||||
methods: vec![MethodDef {
|
||||
name: sym::hash,
|
||||
generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] },
|
||||
explicit_self: borrowed_explicit_self(),
|
||||
args: vec![(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mut)), sym::state)],
|
||||
ret_ty: nil_ty(),
|
||||
explicit_self: true,
|
||||
args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
|
||||
ret_ty: Unit,
|
||||
attributes: vec![],
|
||||
is_unsafe: false,
|
||||
unify_fieldless_variants: true,
|
||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||
hash_substructure(a, b, c)
|
||||
|
Loading…
Reference in New Issue
Block a user