Rollup merge of #98915 - nnethercote:clarify-deriving-code, r=Mark-Simulacrum
Clarify deriving code A number of clarifications to the deriving code. r? ``@Mark-Simulacrum``
This commit is contained in:
commit
5e6812b597
11 changed files with 457 additions and 570 deletions
|
@ -80,7 +80,7 @@ pub fn expand_deriving_clone(
|
||||||
name: sym::clone,
|
name: sym::clone,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: Vec::new(),
|
nonself_args: Vec::new(),
|
||||||
ret_ty: Self_,
|
ret_ty: Self_,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: false,
|
unify_fieldless_variants: false,
|
||||||
|
@ -160,8 +160,8 @@ fn cs_clone(
|
||||||
let ctor_path;
|
let ctor_path;
|
||||||
let all_fields;
|
let all_fields;
|
||||||
let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
|
let fn_path = cx.std_path(&[sym::clone, sym::Clone, sym::clone]);
|
||||||
let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo<'_>| {
|
let subcall = |cx: &mut ExtCtxt<'_>, field: &FieldInfo| {
|
||||||
let args = vec![cx.expr_addr_of(field.span, field.self_.clone())];
|
let args = vec![cx.expr_addr_of(field.span, field.self_expr.clone())];
|
||||||
cx.expr_call_global(field.span, fn_path.clone(), args)
|
cx.expr_call_global(field.span, fn_path.clone(), args)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub fn expand_deriving_eq(
|
||||||
name: sym::assert_receiver_is_total_eq,
|
name: sym::assert_receiver_is_total_eq,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: vec![],
|
nonself_args: vec![],
|
||||||
ret_ty: Unit,
|
ret_ty: Unit,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
unify_fieldless_variants: true,
|
||||||
|
|
|
@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
|
||||||
use crate::deriving::generic::*;
|
use crate::deriving::generic::*;
|
||||||
use crate::deriving::path_std;
|
use crate::deriving::path_std;
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::MetaItem;
|
||||||
use rustc_ast::{self as ast, MetaItem};
|
|
||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -28,7 +27,7 @@ pub fn expand_deriving_ord(
|
||||||
name: sym::cmp,
|
name: sym::cmp,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: vec![(self_ref(), sym::other)],
|
nonself_args: vec![(self_ref(), sym::other)],
|
||||||
ret_ty: Path(path_std!(cmp::Ordering)),
|
ret_ty: Path(path_std!(cmp::Ordering)),
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
unify_fieldless_variants: true,
|
||||||
|
@ -40,84 +39,54 @@ pub fn expand_deriving_ord(
|
||||||
trait_def.expand(cx, mitem, item, push)
|
trait_def.expand(cx, mitem, item, push)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ordering_collapsed(
|
|
||||||
cx: &mut ExtCtxt<'_>,
|
|
||||||
span: Span,
|
|
||||||
self_arg_tags: &[Ident],
|
|
||||||
) -> P<ast::Expr> {
|
|
||||||
let lft = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[0]));
|
|
||||||
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
|
|
||||||
let fn_cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
|
|
||||||
cx.expr_call_global(span, fn_cmp_path, vec![lft, rgt])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||||
let test_id = Ident::new(sym::cmp, span);
|
let test_id = Ident::new(sym::cmp, span);
|
||||||
let equals_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
|
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
|
||||||
|
|
||||||
let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
|
let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
|
||||||
|
|
||||||
// Builds:
|
// Builds:
|
||||||
//
|
//
|
||||||
// match ::std::cmp::Ord::cmp(&self_field1, &other_field1) {
|
// match ::core::cmp::Ord::cmp(&self.x, &other.x) {
|
||||||
// ::std::cmp::Ordering::Equal =>
|
// ::std::cmp::Ordering::Equal =>
|
||||||
// match ::std::cmp::Ord::cmp(&self_field2, &other_field2) {
|
// ::core::cmp::Ord::cmp(&self.y, &other.y),
|
||||||
// ::std::cmp::Ordering::Equal => {
|
// cmp => cmp,
|
||||||
// ...
|
|
||||||
// }
|
// }
|
||||||
// cmp => cmp
|
|
||||||
// },
|
|
||||||
// cmp => cmp
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
let expr = cs_fold(
|
let expr = cs_fold(
|
||||||
// foldr nests the if-elses correctly, leaving the first field
|
// foldr nests the if-elses correctly, leaving the first field
|
||||||
// as the outermost one, and the last as the innermost.
|
// as the outermost one, and the last as the innermost.
|
||||||
false,
|
false,
|
||||||
|cx, span, old, self_f, other_fs| {
|
|
||||||
// match new {
|
|
||||||
// ::std::cmp::Ordering::Equal => old,
|
|
||||||
// cmp => cmp
|
|
||||||
// }
|
|
||||||
let new = {
|
|
||||||
let [other_f] = other_fs else {
|
|
||||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
|
|
||||||
};
|
|
||||||
let args =
|
|
||||||
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
|
|
||||||
cx.expr_call_global(span, cmp_path.clone(), args)
|
|
||||||
};
|
|
||||||
|
|
||||||
let eq_arm = cx.arm(span, cx.pat_path(span, equals_path.clone()), old);
|
|
||||||
let neq_arm = cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
|
|
||||||
|
|
||||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
|
||||||
},
|
|
||||||
|cx, args| match args {
|
|
||||||
Some((span, self_f, other_fs)) => {
|
|
||||||
let new = {
|
|
||||||
let [other_f] = other_fs else {
|
|
||||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
|
|
||||||
};
|
|
||||||
let args =
|
|
||||||
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
|
|
||||||
cx.expr_call_global(span, cmp_path.clone(), args)
|
|
||||||
};
|
|
||||||
|
|
||||||
new
|
|
||||||
}
|
|
||||||
None => cx.expr_path(equals_path.clone()),
|
|
||||||
},
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
cx,
|
cx,
|
||||||
span,
|
span,
|
||||||
substr,
|
substr,
|
||||||
|
|cx, fold| match fold {
|
||||||
|
CsFold::Single(field) => {
|
||||||
|
let [other_expr] = &field.other_selflike_exprs[..] else {
|
||||||
|
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
|
||||||
|
};
|
||||||
|
let args = vec![
|
||||||
|
cx.expr_addr_of(field.span, field.self_expr.clone()),
|
||||||
|
cx.expr_addr_of(field.span, other_expr.clone()),
|
||||||
|
];
|
||||||
|
cx.expr_call_global(field.span, cmp_path.clone(), args)
|
||||||
|
}
|
||||||
|
CsFold::Combine(span, expr1, expr2) => {
|
||||||
|
let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1);
|
||||||
|
let neq_arm =
|
||||||
|
cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
|
||||||
|
cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
|
||||||
|
}
|
||||||
|
CsFold::Fieldless => cx.expr_path(equal_path.clone()),
|
||||||
|
CsFold::EnumNonMatching(span, tag_tuple) => {
|
||||||
|
if tag_tuple.len() != 2 {
|
||||||
|
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
|
||||||
|
} else {
|
||||||
|
let lft = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[0]));
|
||||||
|
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
|
||||||
|
let fn_cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]);
|
||||||
|
cx.expr_call_global(span, fn_cmp_path, vec![lft, rgt])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
BlockOrExpr::new_expr(expr)
|
BlockOrExpr::new_expr(expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
|
||||||
use crate::deriving::generic::*;
|
use crate::deriving::generic::*;
|
||||||
use crate::deriving::{path_local, path_std};
|
use crate::deriving::{path_local, path_std};
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::{BinOpKind, MetaItem};
|
||||||
use rustc_ast::{BinOpKind, Expr, MetaItem};
|
|
||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -23,33 +22,22 @@ pub fn expand_deriving_partial_eq(
|
||||||
combiner: BinOpKind,
|
combiner: BinOpKind,
|
||||||
base: bool,
|
base: bool,
|
||||||
) -> BlockOrExpr {
|
) -> BlockOrExpr {
|
||||||
let op = |cx: &mut ExtCtxt<'_>, span: Span, self_f: P<Expr>, other_fs: &[P<Expr>]| {
|
|
||||||
let [other_f] = other_fs else {
|
|
||||||
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`");
|
|
||||||
};
|
|
||||||
|
|
||||||
cx.expr_binary(span, op, self_f, other_f.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
let expr = cs_fold(
|
let expr = cs_fold(
|
||||||
true, // use foldl
|
true, // use foldl
|
||||||
|cx, span, subexpr, self_f, other_fs| {
|
|
||||||
let eq = op(cx, span, self_f, other_fs);
|
|
||||||
cx.expr_binary(span, combiner, subexpr, eq)
|
|
||||||
},
|
|
||||||
|cx, args| {
|
|
||||||
match args {
|
|
||||||
Some((span, self_f, other_fs)) => {
|
|
||||||
// Special-case the base case to generate cleaner code.
|
|
||||||
op(cx, span, self_f, other_fs)
|
|
||||||
}
|
|
||||||
None => cx.expr_bool(span, base),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Box::new(|cx, span, _| cx.expr_bool(span, !base)),
|
|
||||||
cx,
|
cx,
|
||||||
span,
|
span,
|
||||||
substr,
|
substr,
|
||||||
|
|cx, fold| match fold {
|
||||||
|
CsFold::Single(field) => {
|
||||||
|
let [other_expr] = &field.other_selflike_exprs[..] else {
|
||||||
|
cx.span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
|
||||||
|
};
|
||||||
|
cx.expr_binary(field.span, op, field.self_expr.clone(), other_expr.clone())
|
||||||
|
}
|
||||||
|
CsFold::Combine(span, expr1, expr2) => cx.expr_binary(span, combiner, expr1, expr2),
|
||||||
|
CsFold::Fieldless => cx.expr_bool(span, base),
|
||||||
|
CsFold::EnumNonMatching(span, _tag_tuple) => cx.expr_bool(span, !base),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
BlockOrExpr::new_expr(expr)
|
BlockOrExpr::new_expr(expr)
|
||||||
}
|
}
|
||||||
|
@ -69,7 +57,7 @@ pub fn expand_deriving_partial_eq(
|
||||||
name: $name,
|
name: $name,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: vec![(self_ref(), sym::other)],
|
nonself_args: vec![(self_ref(), sym::other)],
|
||||||
ret_ty: Path(path_local!(bool)),
|
ret_ty: Path(path_local!(bool)),
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
unify_fieldless_variants: true,
|
||||||
|
|
|
@ -2,8 +2,7 @@ use crate::deriving::generic::ty::*;
|
||||||
use crate::deriving::generic::*;
|
use crate::deriving::generic::*;
|
||||||
use crate::deriving::{path_std, pathvec_std};
|
use crate::deriving::{path_std, pathvec_std};
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::MetaItem;
|
||||||
use rustc_ast::{Expr, MetaItem};
|
|
||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -26,7 +25,7 @@ pub fn expand_deriving_partial_ord(
|
||||||
name: sym::partial_cmp,
|
name: sym::partial_cmp,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: vec![(self_ref(), sym::other)],
|
nonself_args: vec![(self_ref(), sym::other)],
|
||||||
ret_ty,
|
ret_ty,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
unify_fieldless_variants: true,
|
||||||
|
@ -50,79 +49,54 @@ pub fn expand_deriving_partial_ord(
|
||||||
|
|
||||||
pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||||
let test_id = Ident::new(sym::cmp, span);
|
let test_id = Ident::new(sym::cmp, span);
|
||||||
let ordering = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
|
let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal]));
|
||||||
let ordering_expr = cx.expr_path(ordering.clone());
|
|
||||||
|
|
||||||
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
|
let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
|
||||||
|
|
||||||
// Builds:
|
// Builds:
|
||||||
//
|
//
|
||||||
// match ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1) {
|
// match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) {
|
||||||
// ::std::option::Option::Some(::std::cmp::Ordering::Equal) =>
|
// ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
|
||||||
// match ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2) {
|
// ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y),
|
||||||
// ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {
|
// cmp => cmp,
|
||||||
// ...
|
|
||||||
// }
|
// }
|
||||||
// cmp => cmp
|
|
||||||
// },
|
|
||||||
// cmp => cmp
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
let expr = cs_fold(
|
let expr = cs_fold(
|
||||||
// foldr nests the if-elses correctly, leaving the first field
|
// foldr nests the if-elses correctly, leaving the first field
|
||||||
// as the outermost one, and the last as the innermost.
|
// as the outermost one, and the last as the innermost.
|
||||||
false,
|
false,
|
||||||
|cx, span, old, self_f, other_fs| {
|
|
||||||
// match new {
|
|
||||||
// Some(::std::cmp::Ordering::Equal) => old,
|
|
||||||
// cmp => cmp
|
|
||||||
// }
|
|
||||||
|
|
||||||
let new = {
|
|
||||||
let [other_f] = other_fs else {
|
|
||||||
cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`");
|
|
||||||
};
|
|
||||||
|
|
||||||
let args =
|
|
||||||
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
|
|
||||||
|
|
||||||
cx.expr_call_global(span, partial_cmp_path.clone(), args)
|
|
||||||
};
|
|
||||||
|
|
||||||
let eq_arm = cx.arm(span, cx.pat_some(span, cx.pat_path(span, ordering.clone())), old);
|
|
||||||
let neq_arm = cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
|
|
||||||
|
|
||||||
cx.expr_match(span, new, vec![eq_arm, neq_arm])
|
|
||||||
},
|
|
||||||
|cx: &mut ExtCtxt<'_>, args: Option<(Span, P<Expr>, &[P<Expr>])>| match args {
|
|
||||||
Some((span, self_f, other_fs)) => {
|
|
||||||
let new = {
|
|
||||||
let [other_f] = other_fs else {
|
|
||||||
cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`");
|
|
||||||
};
|
|
||||||
let args =
|
|
||||||
vec![cx.expr_addr_of(span, self_f), cx.expr_addr_of(span, other_f.clone())];
|
|
||||||
cx.expr_call_global(span, partial_cmp_path.clone(), args)
|
|
||||||
};
|
|
||||||
|
|
||||||
new
|
|
||||||
}
|
|
||||||
None => cx.expr_some(span, ordering_expr.clone()),
|
|
||||||
},
|
|
||||||
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]));
|
|
||||||
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
|
|
||||||
let fn_partial_cmp_path =
|
|
||||||
cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
|
|
||||||
cx.expr_call_global(span, fn_partial_cmp_path, vec![lft, rgt])
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
cx,
|
cx,
|
||||||
span,
|
span,
|
||||||
substr,
|
substr,
|
||||||
|
|cx, fold| match fold {
|
||||||
|
CsFold::Single(field) => {
|
||||||
|
let [other_expr] = &field.other_selflike_exprs[..] else {
|
||||||
|
cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
|
||||||
|
};
|
||||||
|
let args = vec![
|
||||||
|
cx.expr_addr_of(field.span, field.self_expr.clone()),
|
||||||
|
cx.expr_addr_of(field.span, other_expr.clone()),
|
||||||
|
];
|
||||||
|
cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
|
||||||
|
}
|
||||||
|
CsFold::Combine(span, expr1, expr2) => {
|
||||||
|
let eq_arm =
|
||||||
|
cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1);
|
||||||
|
let neq_arm =
|
||||||
|
cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id));
|
||||||
|
cx.expr_match(span, expr2, vec![eq_arm, neq_arm])
|
||||||
|
}
|
||||||
|
CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())),
|
||||||
|
CsFold::EnumNonMatching(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]));
|
||||||
|
let rgt = cx.expr_addr_of(span, cx.expr_ident(span, tag_tuple[1]));
|
||||||
|
let fn_partial_cmp_path =
|
||||||
|
cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]);
|
||||||
|
cx.expr_call_global(span, fn_partial_cmp_path, vec![lft, rgt])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
BlockOrExpr::new_expr(expr)
|
BlockOrExpr::new_expr(expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub fn expand_deriving_debug(
|
||||||
name: sym::fmt,
|
name: sym::fmt,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: vec![(fmtr, sym::f)],
|
nonself_args: vec![(fmtr, sym::f)],
|
||||||
ret_ty: Path(path_std!(fmt::Result)),
|
ret_ty: Path(path_std!(fmt::Result)),
|
||||||
attributes: Vec::new(),
|
attributes: Vec::new(),
|
||||||
unify_fieldless_variants: false,
|
unify_fieldless_variants: false,
|
||||||
|
@ -53,7 +53,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
||||||
// We want to make sure we have the ctxt set so that we can use unstable methods
|
// We want to make sure we have the ctxt set so that we can use unstable methods
|
||||||
let span = cx.with_def_site_ctxt(span);
|
let span = cx.with_def_site_ctxt(span);
|
||||||
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
|
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
|
||||||
let fmt = substr.nonself_args[0].clone();
|
let fmt = substr.nonselflike_args[0].clone();
|
||||||
|
|
||||||
// Struct and tuples are similar enough that we use the same code for both,
|
// Struct and tuples are similar enough that we use the same code for both,
|
||||||
// with some extra pieces for structs due to the field names.
|
// with some extra pieces for structs due to the field names.
|
||||||
|
@ -96,7 +96,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
||||||
args.push(name);
|
args.push(name);
|
||||||
}
|
}
|
||||||
// Use double indirection to make sure this works for unsized types
|
// Use double indirection to make sure this works for unsized types
|
||||||
let field = cx.expr_addr_of(field.span, field.self_.clone());
|
let field = cx.expr_addr_of(field.span, field.self_expr.clone());
|
||||||
let field = cx.expr_addr_of(field.span, field);
|
let field = cx.expr_addr_of(field.span, field);
|
||||||
args.push(field);
|
args.push(field);
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use double indirection to make sure this works for unsized types
|
// Use double indirection to make sure this works for unsized types
|
||||||
let value_ref = cx.expr_addr_of(field.span, field.self_.clone());
|
let value_ref = cx.expr_addr_of(field.span, field.self_expr.clone());
|
||||||
value_exprs.push(cx.expr_addr_of(field.span, value_ref));
|
value_exprs.push(cx.expr_addr_of(field.span, value_ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,10 @@ pub fn expand_deriving_rustc_decodable(
|
||||||
)],
|
)],
|
||||||
},
|
},
|
||||||
explicit_self: false,
|
explicit_self: false,
|
||||||
args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::d)],
|
nonself_args: vec![(
|
||||||
|
Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut),
|
||||||
|
sym::d,
|
||||||
|
)],
|
||||||
ret_ty: Path(Path::new_(
|
ret_ty: Path(Path::new_(
|
||||||
pathvec_std!(result::Result),
|
pathvec_std!(result::Result),
|
||||||
vec![
|
vec![
|
||||||
|
@ -63,7 +66,7 @@ fn decodable_substructure(
|
||||||
substr: &Substructure<'_>,
|
substr: &Substructure<'_>,
|
||||||
krate: Symbol,
|
krate: Symbol,
|
||||||
) -> BlockOrExpr {
|
) -> BlockOrExpr {
|
||||||
let decoder = substr.nonself_args[0].clone();
|
let decoder = substr.nonselflike_args[0].clone();
|
||||||
let recurse = vec![
|
let recurse = vec![
|
||||||
Ident::new(krate, trait_span),
|
Ident::new(krate, trait_span),
|
||||||
Ident::new(sym::Decodable, trait_span),
|
Ident::new(sym::Decodable, trait_span),
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub fn expand_deriving_default(
|
||||||
name: kw::Default,
|
name: kw::Default,
|
||||||
generics: Bounds::empty(),
|
generics: Bounds::empty(),
|
||||||
explicit_self: false,
|
explicit_self: false,
|
||||||
args: Vec::new(),
|
nonself_args: Vec::new(),
|
||||||
ret_ty: Self_,
|
ret_ty: Self_,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: false,
|
unify_fieldless_variants: false,
|
||||||
|
|
|
@ -120,7 +120,10 @@ pub fn expand_deriving_rustc_encodable(
|
||||||
)],
|
)],
|
||||||
},
|
},
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: vec![(Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut), sym::s)],
|
nonself_args: vec![(
|
||||||
|
Ref(Box::new(Path(Path::new_local(typaram))), Mutability::Mut),
|
||||||
|
sym::s,
|
||||||
|
)],
|
||||||
ret_ty: Path(Path::new_(
|
ret_ty: Path(Path::new_(
|
||||||
pathvec_std!(result::Result),
|
pathvec_std!(result::Result),
|
||||||
vec![
|
vec![
|
||||||
|
@ -147,7 +150,7 @@ fn encodable_substructure(
|
||||||
substr: &Substructure<'_>,
|
substr: &Substructure<'_>,
|
||||||
krate: Symbol,
|
krate: Symbol,
|
||||||
) -> BlockOrExpr {
|
) -> BlockOrExpr {
|
||||||
let encoder = substr.nonself_args[0].clone();
|
let encoder = substr.nonselflike_args[0].clone();
|
||||||
// throw an underscore in front to suppress unused variable warnings
|
// throw an underscore in front to suppress unused variable warnings
|
||||||
let blkarg = Ident::new(sym::_e, trait_span);
|
let blkarg = Ident::new(sym::_e, trait_span);
|
||||||
let blkencoder = cx.expr_ident(trait_span, blkarg);
|
let blkencoder = cx.expr_ident(trait_span, blkarg);
|
||||||
|
@ -165,12 +168,12 @@ fn encodable_substructure(
|
||||||
let fn_emit_struct_field_path =
|
let fn_emit_struct_field_path =
|
||||||
cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
|
cx.def_site_path(&[sym::rustc_serialize, sym::Encoder, sym::emit_struct_field]);
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
|
for (i, &FieldInfo { name, ref self_expr, span, .. }) in fields.iter().enumerate() {
|
||||||
let name = match name {
|
let name = match name {
|
||||||
Some(id) => id.name,
|
Some(id) => id.name,
|
||||||
None => Symbol::intern(&format!("_field{}", i)),
|
None => Symbol::intern(&format!("_field{}", i)),
|
||||||
};
|
};
|
||||||
let self_ref = cx.expr_addr_of(span, self_.clone());
|
let self_ref = cx.expr_addr_of(span, self_expr.clone());
|
||||||
let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
|
let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
|
||||||
let lambda = cx.lambda1(span, enc, blkarg);
|
let lambda = cx.lambda1(span, enc, blkarg);
|
||||||
let call = cx.expr_call_global(
|
let call = cx.expr_call_global(
|
||||||
|
@ -234,8 +237,8 @@ fn encodable_substructure(
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
if !fields.is_empty() {
|
if !fields.is_empty() {
|
||||||
let last = fields.len() - 1;
|
let last = fields.len() - 1;
|
||||||
for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
|
for (i, &FieldInfo { ref self_expr, span, .. }) in fields.iter().enumerate() {
|
||||||
let self_ref = cx.expr_addr_of(span, self_.clone());
|
let self_ref = cx.expr_addr_of(span, self_expr.clone());
|
||||||
let enc =
|
let enc =
|
||||||
cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
|
cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
|
||||||
let lambda = cx.lambda1(span, enc, blkarg);
|
let lambda = cx.lambda1(span, enc, blkarg);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,7 @@ pub fn expand_deriving_hash(
|
||||||
name: sym::hash,
|
name: sym::hash,
|
||||||
generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] },
|
generics: Bounds { bounds: vec![(typaram, vec![path_std!(hash::Hasher)])] },
|
||||||
explicit_self: true,
|
explicit_self: true,
|
||||||
args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
|
nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
|
||||||
ret_ty: Unit,
|
ret_ty: Unit,
|
||||||
attributes: vec![],
|
attributes: vec![],
|
||||||
unify_fieldless_variants: true,
|
unify_fieldless_variants: true,
|
||||||
|
@ -49,7 +49,7 @@ fn hash_substructure(
|
||||||
trait_span: Span,
|
trait_span: Span,
|
||||||
substr: &Substructure<'_>,
|
substr: &Substructure<'_>,
|
||||||
) -> BlockOrExpr {
|
) -> BlockOrExpr {
|
||||||
let [state_expr] = substr.nonself_args else {
|
let [state_expr] = substr.nonselflike_args else {
|
||||||
cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`");
|
cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`");
|
||||||
};
|
};
|
||||||
let call_hash = |span, thing_expr| {
|
let call_hash = |span, thing_expr| {
|
||||||
|
@ -82,7 +82,9 @@ fn hash_substructure(
|
||||||
};
|
};
|
||||||
|
|
||||||
stmts.extend(
|
stmts.extend(
|
||||||
fields.iter().map(|FieldInfo { ref self_, span, .. }| call_hash(*span, self_.clone())),
|
fields
|
||||||
|
.iter()
|
||||||
|
.map(|FieldInfo { ref self_expr, span, .. }| call_hash(*span, self_expr.clone())),
|
||||||
);
|
);
|
||||||
BlockOrExpr::new_stmts(stmts)
|
BlockOrExpr::new_stmts(stmts)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue