Removed dead structures after changes to PartialOrd/Ord derivings.
Remove the `NonMatchesExplode` variant now that no deriving impl uses it. Removed `EnumNonMatching` entirely. Remove now irrelevant `on_matching` field and `HandleNonMatchingEnums` type. Removed unused `EnumNonMatchFunc` type def. Drive-by: revise `EnumNonMatchCollapsedFunc` doc. Made all calls to `expand_enum_method_body` go directly to `build_enum_match_tuple`. Alpha-rename `enum_nonmatch_g` back to `enum_nonmatch_f` to reduce overall diff noise. Inline sole call of `some_ordering_const`. Inline sole call of `ordering_const`. Removed a bunch of code that became dead after the above changes.
This commit is contained in:
parent
c8ae44682d
commit
5cee57869c
14 changed files with 29 additions and 352 deletions
|
|
@ -39,7 +39,6 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
|
|||
args: Vec::new(),
|
||||
ret_ty: Self,
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|c, s, sub| {
|
||||
cs_clone("Clone", c, s, sub)
|
||||
}),
|
||||
|
|
@ -69,7 +68,7 @@ fn cs_clone(
|
|||
ctor_ident = variant.node.name;
|
||||
all_fields = af;
|
||||
},
|
||||
EnumNonMatching(..) | EnumNonMatchingCollapsed (..) => {
|
||||
EnumNonMatchingCollapsed (..) => {
|
||||
cx.span_bug(trait_span,
|
||||
format!("non-matching enum variants in \
|
||||
`deriving({})`",
|
||||
|
|
|
|||
|
|
@ -27,12 +27,10 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
|||
// any fields are not equal or if the enum variants are different
|
||||
fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> Gc<Expr> {
|
||||
cs_and(|cx, span, _, _| cx.expr_bool(span, false),
|
||||
|cx, span, _, _| cx.expr_bool(span, false),
|
||||
cx, span, substr)
|
||||
cx, span, substr)
|
||||
}
|
||||
fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> Gc<Expr> {
|
||||
cs_or(|cx, span, _, _| cx.expr_bool(span, true),
|
||||
|cx, span, _, _| cx.expr_bool(span, true),
|
||||
cx, span, substr)
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +45,6 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
|
|||
args: vec!(borrowed_self()),
|
||||
ret_ty: Literal(Path::new(vec!("bool"))),
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchesCollapse,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
$f(a, b, c)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
|||
args: vec!(borrowed_self()),
|
||||
ret_ty: Literal(Path::new(vec!("bool"))),
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchesCollapseWithTags,
|
||||
combine_substructure: combine_substructure(|cx, span, substr| {
|
||||
cs_op($op, $equal, cx, span, substr)
|
||||
})
|
||||
|
|
@ -59,7 +58,6 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
|||
args: vec![borrowed_self()],
|
||||
ret_ty: ret_ty,
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchesCollapseWithTags,
|
||||
combine_substructure: combine_substructure(|cx, span, substr| {
|
||||
cs_partial_cmp(cx, span, substr)
|
||||
})
|
||||
|
|
@ -82,20 +80,6 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
|
|||
trait_def.expand(cx, mitem, item, push)
|
||||
}
|
||||
|
||||
pub fn some_ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> Gc<ast::Expr> {
|
||||
let cnst = match cnst {
|
||||
Less => "Less",
|
||||
Equal => "Equal",
|
||||
Greater => "Greater"
|
||||
};
|
||||
let ordering = cx.path_global(span,
|
||||
vec!(cx.ident_of("std"),
|
||||
cx.ident_of("cmp"),
|
||||
cx.ident_of(cnst)));
|
||||
let ordering = cx.expr_path(ordering);
|
||||
cx.expr_some(span, ordering)
|
||||
}
|
||||
|
||||
pub enum OrderingOp {
|
||||
PartialCmpOp, LtOp, LeOp, GtOp, GeOp,
|
||||
}
|
||||
|
|
@ -117,7 +101,12 @@ pub fn some_ordering_collapsed(cx: &mut ExtCtxt,
|
|||
pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
|
||||
substr: &Substructure) -> Gc<Expr> {
|
||||
let test_id = cx.ident_of("__test");
|
||||
let equals_expr = some_ordering_const(cx, span, Equal);
|
||||
let ordering = cx.path_global(span,
|
||||
vec!(cx.ident_of("std"),
|
||||
cx.ident_of("cmp"),
|
||||
cx.ident_of("Equal")));
|
||||
let ordering = cx.expr_path(ordering);
|
||||
let equals_expr = cx.expr_some(span, ordering);
|
||||
|
||||
/*
|
||||
Builds:
|
||||
|
|
@ -159,15 +148,6 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
|
|||
cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
|
||||
},
|
||||
equals_expr.clone(),
|
||||
|cx, span, list, _| {
|
||||
match list {
|
||||
// an earlier nonmatching variant is Less than a
|
||||
// later one.
|
||||
[(self_var, _, _), (other_var, _, _)] =>
|
||||
some_ordering_const(cx, span, self_var.cmp(&other_var)),
|
||||
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`"),
|
||||
}
|
||||
},
|
||||
|cx, span, (self_args, tag_tuple), _non_self_args| {
|
||||
if self_args.len() != 2 {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
|
||||
|
|
@ -216,21 +196,6 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span,
|
|||
cx.expr_binary(span, ast::BiOr, cmp, and)
|
||||
},
|
||||
cx.expr_bool(span, equal),
|
||||
|cx, span, args, _| {
|
||||
// nonmatching enums, order by the order the variants are
|
||||
// written
|
||||
match args {
|
||||
[(self_var, _, _),
|
||||
(other_var, _, _)] =>
|
||||
cx.expr_bool(span,
|
||||
if less {
|
||||
self_var < other_var
|
||||
} else {
|
||||
self_var > other_var
|
||||
}),
|
||||
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
|
||||
}
|
||||
},
|
||||
|cx, span, (self_args, tag_tuple), _non_self_args| {
|
||||
if self_args.len() != 2 {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
|
|||
let block = cx.block(span, stmts, None);
|
||||
cx.expr_block(block)
|
||||
},
|
||||
|cx, sp, _, _| cx.span_bug(sp, "non matching enums in deriving(Eq)?"),
|
||||
|cx, sp, _, _| cx.span_bug(sp, "non matching enums in deriving(Eq)?"),
|
||||
cx,
|
||||
span,
|
||||
|
|
@ -58,7 +57,6 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
|
|||
args: vec!(),
|
||||
ret_ty: nil_ty(),
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchesCollapse,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
cs_total_eq_assert(a, b, c)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ use ext::deriving::generic::*;
|
|||
use ext::deriving::generic::ty::*;
|
||||
use parse::token::InternedString;
|
||||
|
||||
use std::cmp::{Ordering, Equal, Less, Greater};
|
||||
use std::gc::Gc;
|
||||
|
||||
pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
|
||||
|
|
@ -41,7 +40,6 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
|
|||
args: vec!(borrowed_self()),
|
||||
ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchesCollapseWithTags,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
cs_cmp(a, b, c)
|
||||
}),
|
||||
|
|
@ -53,18 +51,6 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
|
|||
}
|
||||
|
||||
|
||||
pub fn ordering_const(cx: &mut ExtCtxt, span: Span, cnst: Ordering) -> ast::Path {
|
||||
let cnst = match cnst {
|
||||
Less => "Less",
|
||||
Equal => "Equal",
|
||||
Greater => "Greater"
|
||||
};
|
||||
cx.path_global(span,
|
||||
vec!(cx.ident_of("std"),
|
||||
cx.ident_of("cmp"),
|
||||
cx.ident_of(cnst)))
|
||||
}
|
||||
|
||||
pub fn ordering_collapsed(cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
self_arg_tags: &[ast::Ident]) -> Gc<ast::Expr> {
|
||||
|
|
@ -76,7 +62,10 @@ pub fn ordering_collapsed(cx: &mut ExtCtxt,
|
|||
pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
|
||||
substr: &Substructure) -> Gc<Expr> {
|
||||
let test_id = cx.ident_of("__test");
|
||||
let equals_path = ordering_const(cx, span, Equal);
|
||||
let equals_path = cx.path_global(span,
|
||||
vec!(cx.ident_of("std"),
|
||||
cx.ident_of("cmp"),
|
||||
cx.ident_of("Equal")));
|
||||
|
||||
/*
|
||||
Builds:
|
||||
|
|
@ -118,18 +107,6 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
|
|||
cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
|
||||
},
|
||||
cx.expr_path(equals_path.clone()),
|
||||
|cx, span, list, _| {
|
||||
match list {
|
||||
// an earlier nonmatching variant is Less than a
|
||||
// later one.
|
||||
[(self_var, _, _),
|
||||
(other_var, _, _)] => {
|
||||
let order = ordering_const(cx, span, self_var.cmp(&other_var));
|
||||
cx.expr_path(order)
|
||||
}
|
||||
_ => cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
|
||||
}
|
||||
},
|
||||
|cx, span, (self_args, tag_tuple), _non_self_args| {
|
||||
if self_args.len() != 2 {
|
||||
cx.span_bug(span, "not exactly 2 arguments in `deriving(TotalOrd)`")
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
|
|||
vec!(box Self,
|
||||
box Literal(Path::new_local("__E"))), true)),
|
||||
attributes: Vec::new(),
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
decodable_substructure(a, b, c)
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
|
|||
args: Vec::new(),
|
||||
ret_ty: Self,
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
default_substructure(a, b, c)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
|
|||
box Literal(Path::new_local("__E"))),
|
||||
true)),
|
||||
attributes: Vec::new(),
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
encodable_substructure(a, b, c)
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -37,18 +37,19 @@
|
|||
//! `struct T(int, char)`).
|
||||
//! - `EnumMatching`, when `Self` is an enum and all the arguments are the
|
||||
//! same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`)
|
||||
//! - `EnumNonMatching` when `Self` is an enum and the arguments are not
|
||||
//! the same variant (e.g. `None`, `Some(1)` and `None`). If
|
||||
//! `on_nonmatching == NonMatchesCollapse`, this will contain an empty list.
|
||||
//! - `EnumNonMatchingCollapsed` when `Self` is an enum and the arguments
|
||||
//! are not the same variant (e.g. `None`, `Some(1)` and `None`).
|
||||
//! - `StaticEnum` and `StaticStruct` for static methods, where the type
|
||||
//! being derived upon is either an enum or struct respectively. (Any
|
||||
//! argument with type Self is just grouped among the non-self
|
||||
//! arguments.)
|
||||
//!
|
||||
//! In the first two cases, the values from the corresponding fields in
|
||||
//! all the arguments are grouped together. In the `EnumNonMatching` case
|
||||
//! all the arguments are grouped together. For `EnumNonMatchingCollapsed`
|
||||
//! this isn't possible (different variants have different fields), so the
|
||||
//! fields are grouped by which argument they come from. There are no
|
||||
//! fields are inaccessible. (Previous versions of the deriving infrastructure
|
||||
//! had a way to expand into code that could access them, at the cost of
|
||||
//! generating exponential amounts of code; see issue #15375). There are no
|
||||
//! fields with values in the static cases, so these are treated entirely
|
||||
//! differently.
|
||||
//!
|
||||
|
|
@ -218,21 +219,6 @@ pub struct TraitDef<'a> {
|
|||
pub methods: Vec<MethodDef<'a>>,
|
||||
}
|
||||
|
||||
#[deriving(PartialEq, Eq)]
|
||||
pub enum HandleNonMatchingEnums {
|
||||
/// handle all non-matches via one `_ => ..` clause
|
||||
NonMatchesCollapse,
|
||||
|
||||
/// handle all non-matches via one `_ => ..` clause that has
|
||||
/// access to a tuple of tags indicating each variant index.
|
||||
NonMatchesCollapseWithTags,
|
||||
|
||||
/// handle via n^k cases for n variants and k self-args
|
||||
NonMatchesExplode,
|
||||
|
||||
/// cannot encounter two enums of Self type
|
||||
NonMatchHandlingIrrelevant,
|
||||
}
|
||||
|
||||
pub struct MethodDef<'a> {
|
||||
/// name of the method
|
||||
|
|
@ -253,18 +239,6 @@ pub struct MethodDef<'a> {
|
|||
|
||||
pub attributes: Vec<ast::Attribute>,
|
||||
|
||||
/// How to handle nonmatching enums; `NonMatchesCollapse`
|
||||
/// indicates value is independent of the actual enum variants,
|
||||
/// i.e. can use _ => .. match.
|
||||
///
|
||||
/// Note that if this is `NonMatchesExplode`, then deriving will
|
||||
/// generate `Omega(n^k)` code, where `n` is the number of
|
||||
/// variants and `k` is the number of arguments of `Self` type for
|
||||
/// the method (including the `self` argument, if any). Strive to
|
||||
/// avoid use of `NonMatchesExplode`, to avoid generating
|
||||
/// quadratic amounts of code (#15375) or worse.
|
||||
pub on_nonmatching: HandleNonMatchingEnums,
|
||||
|
||||
pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
|
||||
}
|
||||
|
||||
|
|
@ -314,14 +288,6 @@ pub enum SubstructureFields<'a> {
|
|||
*/
|
||||
EnumMatching(uint, &'a ast::Variant, Vec<FieldInfo>),
|
||||
|
||||
/**
|
||||
non-matching variants of the enum, [(variant index, ast::Variant,
|
||||
[field span, field ident, fields])] \(i.e. all fields for self are in the
|
||||
first tuple, for other1 are in the second tuple, etc.)
|
||||
*/
|
||||
EnumNonMatching(&'a [(uint, P<ast::Variant>,
|
||||
Vec<(Span, Option<Ident>, Gc<Expr>)>)]),
|
||||
|
||||
/**
|
||||
non-matching variants of the enum, but with all state hidden from
|
||||
the consequent code. The first component holds Idents for all of
|
||||
|
|
@ -839,204 +805,11 @@ impl<'a> MethodDef<'a> {
|
|||
self_args: &[Gc<Expr>],
|
||||
nonself_args: &[Gc<Expr>])
|
||||
-> Gc<Expr> {
|
||||
let mut matches = Vec::new();
|
||||
match self.on_nonmatching {
|
||||
NonMatchesCollapseWithTags =>
|
||||
self.build_enum_match_tuple(
|
||||
cx, trait_, enum_def, type_ident, self_args, nonself_args),
|
||||
NonMatchesCollapse | NonMatchesExplode | NonMatchHandlingIrrelevant =>
|
||||
self.build_enum_match(
|
||||
cx, trait_, enum_def, type_ident, self_args, nonself_args,
|
||||
None, &mut matches, 0),
|
||||
}
|
||||
self.build_enum_match_tuple(
|
||||
cx, trait_, enum_def, type_ident, self_args, nonself_args)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates the nested matches for an enum definition recursively, i.e.
|
||||
|
||||
~~~text
|
||||
match self {
|
||||
Variant1 => match other { Variant1 => matching, Variant2 => nonmatching, ... },
|
||||
Variant2 => match other { Variant1 => nonmatching, Variant2 => matching, ... },
|
||||
...
|
||||
}
|
||||
~~~
|
||||
|
||||
It acts in the most naive way, so every branch (and subbranch,
|
||||
subsubbranch, etc) exists, not just the ones where all the variants in
|
||||
the tree are the same. Hopefully the optimisers get rid of any
|
||||
repetition, otherwise derived methods with many Self arguments will be
|
||||
exponentially large.
|
||||
|
||||
`matching` is Some(n) if all branches in the tree above the
|
||||
current position are variant `n`, `None` otherwise (including on
|
||||
the first call).
|
||||
*/
|
||||
fn build_enum_match(&self,
|
||||
cx: &mut ExtCtxt,
|
||||
trait_: &TraitDef,
|
||||
enum_def: &EnumDef,
|
||||
type_ident: Ident,
|
||||
self_args: &[Gc<Expr>],
|
||||
nonself_args: &[Gc<Expr>],
|
||||
matching: Option<uint>,
|
||||
matches_so_far: &mut Vec<(uint, P<ast::Variant>,
|
||||
Vec<(Span, Option<Ident>, Gc<Expr>)>)> ,
|
||||
match_count: uint) -> Gc<Expr> {
|
||||
if match_count == self_args.len() {
|
||||
// we've matched against all arguments, so make the final
|
||||
// expression at the bottom of the match tree
|
||||
if matches_so_far.len() == 0 {
|
||||
cx.span_bug(trait_.span,
|
||||
"no self match on an enum in \
|
||||
generic `deriving`");
|
||||
}
|
||||
|
||||
// `ref` inside let matches is buggy. Causes havoc with rusc.
|
||||
// let (variant_index, ref self_vec) = matches_so_far[0];
|
||||
let (variant, self_vec) = match matches_so_far.get(0) {
|
||||
&(_, v, ref s) => (v, s)
|
||||
};
|
||||
|
||||
// we currently have a vec of vecs, where each
|
||||
// subvec is the fields of one of the arguments,
|
||||
// but if the variants all match, we want this as
|
||||
// vec of tuples, where each tuple represents a
|
||||
// field.
|
||||
|
||||
// most arms don't have matching variants, so do a
|
||||
// quick check to see if they match (even though
|
||||
// this means iterating twice) instead of being
|
||||
// optimistic and doing a pile of allocations etc.
|
||||
let substructure = match matching {
|
||||
Some(variant_index) => {
|
||||
let mut enum_matching_fields = Vec::from_elem(self_vec.len(), Vec::new());
|
||||
|
||||
for triple in matches_so_far.tail().iter() {
|
||||
match triple {
|
||||
&(_, _, ref other_fields) => {
|
||||
for (i, &(_, _, e)) in other_fields.iter().enumerate() {
|
||||
enum_matching_fields.get_mut(i).push(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let field_tuples =
|
||||
self_vec.iter()
|
||||
.zip(enum_matching_fields.iter())
|
||||
.map(|(&(span, id, self_f), other)| {
|
||||
FieldInfo {
|
||||
span: span,
|
||||
name: id,
|
||||
self_: self_f,
|
||||
other: (*other).clone()
|
||||
}
|
||||
}).collect();
|
||||
EnumMatching(variant_index, &*variant, field_tuples)
|
||||
}
|
||||
None => {
|
||||
EnumNonMatching(matches_so_far.as_slice())
|
||||
}
|
||||
};
|
||||
self.call_substructure_method(cx, trait_, type_ident,
|
||||
self_args, nonself_args,
|
||||
&substructure)
|
||||
|
||||
} else { // there are still matches to create
|
||||
let current_match_str = if match_count == 0 {
|
||||
"__self".to_string()
|
||||
} else {
|
||||
format!("__arg_{}", match_count)
|
||||
};
|
||||
|
||||
let mut arms = Vec::new();
|
||||
|
||||
assert!(self.on_nonmatching == NonMatchesCollapse ||
|
||||
self.on_nonmatching == NonMatchesExplode ||
|
||||
self.on_nonmatching == NonMatchHandlingIrrelevant);
|
||||
|
||||
// the code for nonmatching variants only matters when
|
||||
// we've seen at least one other variant already
|
||||
assert!(match_count == 0 ||
|
||||
self.on_nonmatching != NonMatchHandlingIrrelevant);
|
||||
if self.on_nonmatching == NonMatchesCollapse && match_count > 0 {
|
||||
// make a matching-variant match, and a _ match.
|
||||
let index = match matching {
|
||||
Some(i) => i,
|
||||
None => cx.span_bug(trait_.span,
|
||||
"non-matching variants when required to \
|
||||
be matching in generic `deriving`")
|
||||
};
|
||||
|
||||
// matching-variant match
|
||||
let variant = *enum_def.variants.get(index);
|
||||
let (pattern, idents) = trait_.create_enum_variant_pattern(
|
||||
cx,
|
||||
&*variant,
|
||||
current_match_str.as_slice(),
|
||||
ast::MutImmutable);
|
||||
|
||||
matches_so_far.push((index, variant, idents));
|
||||
let arm_expr = self.build_enum_match(cx,
|
||||
trait_,
|
||||
enum_def,
|
||||
type_ident,
|
||||
self_args, nonself_args,
|
||||
matching,
|
||||
matches_so_far,
|
||||
match_count + 1);
|
||||
matches_so_far.pop().unwrap();
|
||||
arms.push(cx.arm(trait_.span, vec!( pattern ), arm_expr));
|
||||
|
||||
if enum_def.variants.len() > 1 {
|
||||
let e = &EnumNonMatching(&[]);
|
||||
let wild_expr = self.call_substructure_method(cx, trait_, type_ident,
|
||||
self_args, nonself_args,
|
||||
e);
|
||||
let wild_arm = cx.arm(
|
||||
trait_.span,
|
||||
vec!( cx.pat_wild(trait_.span) ),
|
||||
wild_expr);
|
||||
arms.push(wild_arm);
|
||||
}
|
||||
} else {
|
||||
// create an arm matching on each variant
|
||||
for (index, &variant) in enum_def.variants.iter().enumerate() {
|
||||
let (pattern, idents) =
|
||||
trait_.create_enum_variant_pattern(
|
||||
cx,
|
||||
&*variant,
|
||||
current_match_str.as_slice(),
|
||||
ast::MutImmutable);
|
||||
|
||||
matches_so_far.push((index, variant, idents));
|
||||
let new_matching =
|
||||
match matching {
|
||||
_ if match_count == 0 => Some(index),
|
||||
Some(i) if index == i => Some(i),
|
||||
_ => None
|
||||
};
|
||||
let arm_expr = self.build_enum_match(cx,
|
||||
trait_,
|
||||
enum_def,
|
||||
type_ident,
|
||||
self_args, nonself_args,
|
||||
new_matching,
|
||||
matches_so_far,
|
||||
match_count + 1);
|
||||
matches_so_far.pop().unwrap();
|
||||
|
||||
let arm = cx.arm(trait_.span, vec!( pattern ), arm_expr);
|
||||
arms.push(arm);
|
||||
}
|
||||
}
|
||||
|
||||
// match foo { arm, arm, arm, ... }
|
||||
cx.expr_match(trait_.span, self_args[match_count], arms)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a match for a tuple of all `self_args`, where either all
|
||||
variants match, or it falls into a catch-all for when one variant
|
||||
|
|
@ -1522,8 +1295,7 @@ left-to-right (`true`) or right-to-left (`false`).
|
|||
pub fn cs_fold(use_foldl: bool,
|
||||
f: |&mut ExtCtxt, Span, Gc<Expr>, Gc<Expr>, &[Gc<Expr>]| -> Gc<Expr>,
|
||||
base: Gc<Expr>,
|
||||
enum_nonmatch_f: EnumNonMatchFunc,
|
||||
enum_nonmatch_g: EnumNonMatchCollapsedFunc,
|
||||
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||
cx: &mut ExtCtxt,
|
||||
trait_span: Span,
|
||||
substructure: &Substructure)
|
||||
|
|
@ -1548,11 +1320,8 @@ pub fn cs_fold(use_foldl: bool,
|
|||
})
|
||||
}
|
||||
},
|
||||
EnumNonMatching(ref all_enums) =>
|
||||
enum_nonmatch_f(cx, trait_span, *all_enums,
|
||||
substructure.nonself_args),
|
||||
EnumNonMatchingCollapsed(ref all_args, _, tuple) =>
|
||||
enum_nonmatch_g(cx, trait_span, (all_args.as_slice(), tuple),
|
||||
enum_nonmatch_f(cx, trait_span, (all_args.as_slice(), tuple),
|
||||
substructure.nonself_args),
|
||||
StaticEnum(..) | StaticStruct(..) => {
|
||||
cx.span_bug(trait_span, "static function in `deriving`")
|
||||
|
|
@ -1572,8 +1341,7 @@ f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1),
|
|||
*/
|
||||
#[inline]
|
||||
pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<Gc<Expr>>| -> Gc<Expr>,
|
||||
enum_nonmatch_f: EnumNonMatchFunc,
|
||||
enum_nonmatch_g: EnumNonMatchCollapsedFunc,
|
||||
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||
cx: &mut ExtCtxt,
|
||||
trait_span: Span,
|
||||
substructure: &Substructure)
|
||||
|
|
@ -1592,11 +1360,8 @@ pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<Gc<Expr>>| -> Gc<Expr>,
|
|||
|
||||
f(cx, trait_span, called)
|
||||
},
|
||||
EnumNonMatching(ref all_enums) =>
|
||||
enum_nonmatch_f(cx, trait_span, *all_enums,
|
||||
substructure.nonself_args),
|
||||
EnumNonMatchingCollapsed(ref all_self_args, _, tuple) =>
|
||||
enum_nonmatch_g(cx, trait_span, (all_self_args.as_slice(), tuple),
|
||||
enum_nonmatch_f(cx, trait_span, (all_self_args.as_slice(), tuple),
|
||||
substructure.nonself_args),
|
||||
StaticEnum(..) | StaticStruct(..) => {
|
||||
cx.span_bug(trait_span, "static function in `deriving`")
|
||||
|
|
@ -1613,8 +1378,7 @@ fields. `use_foldl` controls whether this is done left-to-right
|
|||
pub fn cs_same_method_fold(use_foldl: bool,
|
||||
f: |&mut ExtCtxt, Span, Gc<Expr>, Gc<Expr>| -> Gc<Expr>,
|
||||
base: Gc<Expr>,
|
||||
enum_nonmatch_f: EnumNonMatchFunc,
|
||||
enum_nonmatch_g: EnumNonMatchCollapsedFunc,
|
||||
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||
cx: &mut ExtCtxt,
|
||||
trait_span: Span,
|
||||
substructure: &Substructure)
|
||||
|
|
@ -1632,7 +1396,6 @@ pub fn cs_same_method_fold(use_foldl: bool,
|
|||
}
|
||||
},
|
||||
enum_nonmatch_f,
|
||||
enum_nonmatch_g,
|
||||
cx, trait_span, substructure)
|
||||
}
|
||||
|
||||
|
|
@ -1642,8 +1405,7 @@ on all the fields.
|
|||
*/
|
||||
#[inline]
|
||||
pub fn cs_binop(binop: ast::BinOp, base: Gc<Expr>,
|
||||
enum_nonmatch_f: EnumNonMatchFunc,
|
||||
enum_nonmatch_g: EnumNonMatchCollapsedFunc,
|
||||
enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||
cx: &mut ExtCtxt, trait_span: Span,
|
||||
substructure: &Substructure) -> Gc<Expr> {
|
||||
cs_same_method_fold(
|
||||
|
|
@ -1656,30 +1418,25 @@ pub fn cs_binop(binop: ast::BinOp, base: Gc<Expr>,
|
|||
},
|
||||
base,
|
||||
enum_nonmatch_f,
|
||||
enum_nonmatch_g,
|
||||
cx, trait_span, substructure)
|
||||
}
|
||||
|
||||
/// cs_binop with binop == or
|
||||
#[inline]
|
||||
pub fn cs_or(enum_nonmatch_f: EnumNonMatchFunc,
|
||||
enum_nonmatch_g: EnumNonMatchCollapsedFunc,
|
||||
pub fn cs_or(enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||
cx: &mut ExtCtxt, span: Span,
|
||||
substructure: &Substructure) -> Gc<Expr> {
|
||||
cs_binop(ast::BiOr, cx.expr_bool(span, false),
|
||||
enum_nonmatch_f,
|
||||
enum_nonmatch_g,
|
||||
cx, span, substructure)
|
||||
}
|
||||
|
||||
/// cs_binop with binop == and
|
||||
#[inline]
|
||||
pub fn cs_and(enum_nonmatch_f: EnumNonMatchFunc,
|
||||
enum_nonmatch_g: EnumNonMatchCollapsedFunc,
|
||||
pub fn cs_and(enum_nonmatch_f: EnumNonMatchCollapsedFunc,
|
||||
cx: &mut ExtCtxt, span: Span,
|
||||
substructure: &Substructure) -> Gc<Expr> {
|
||||
cs_binop(ast::BiAnd, cx.expr_bool(span, true),
|
||||
enum_nonmatch_f,
|
||||
enum_nonmatch_g,
|
||||
cx, span, substructure)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
|
|||
args: vec!(Ptr(box Literal(args), Borrowed(None, MutMutable))),
|
||||
ret_ty: nil_ty(),
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
hash_substructure(a, b, c)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
|
|||
true)),
|
||||
// #[inline] liable to cause code-bloat
|
||||
attributes: attrs.clone(),
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|c, s, sub| {
|
||||
cs_from("i64", c, s, sub)
|
||||
}),
|
||||
|
|
@ -62,7 +61,6 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
|
|||
true)),
|
||||
// #[inline] liable to cause code-bloat
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|c, s, sub| {
|
||||
cs_from("u64", c, s, sub)
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
|
|||
),
|
||||
ret_ty: Self,
|
||||
attributes: Vec::new(),
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
rand_substructure(a, b, c)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
|
|||
args: vec!(fmtr),
|
||||
ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
|
||||
attributes: Vec::new(),
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
show_substructure(a, b, c)
|
||||
})
|
||||
|
|
@ -66,9 +65,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
|
|||
let name = match *substr.fields {
|
||||
Struct(_) => substr.type_ident,
|
||||
EnumMatching(_, v, _) => v.node.name,
|
||||
|
||||
EnumNonMatching(..) | EnumNonMatchingCollapsed(..) |
|
||||
StaticStruct(..) | StaticEnum(..) => {
|
||||
EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
|
||||
cx.span_bug(span, "nonsensical .fields in `#[deriving(Show)]`")
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
|
|||
args: Vec::new(),
|
||||
ret_ty: Self,
|
||||
attributes: attrs.clone(),
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|a, b, c| {
|
||||
zero_substructure(a, b, c)
|
||||
})
|
||||
|
|
@ -51,16 +50,11 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
|
|||
args: Vec::new(),
|
||||
ret_ty: Literal(Path::new(vec!("bool"))),
|
||||
attributes: attrs,
|
||||
on_nonmatching: NonMatchHandlingIrrelevant,
|
||||
combine_substructure: combine_substructure(|cx, span, substr| {
|
||||
cs_and(|cx, span, _, _| cx.span_bug(span,
|
||||
"Non-matching enum \
|
||||
variant in \
|
||||
deriving(Zero)"),
|
||||
|cx, span, _, _| cx.span_bug(span,
|
||||
"Non-matching enum \
|
||||
variant in \
|
||||
deriving(Zero)"),
|
||||
cx, span, substr)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue