args: Vec::new(),
ret_ty: Self,
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|c, s, sub| {
cs_clone("Clone", c, s, sub)
}),
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
- const_nonmatching: true,
+ on_nonmatching: NonMatchesCollapse,
combine_substructure: combine_substructure(|a, b, c| {
$f(a, b, c)
})
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchesExplode,
combine_substructure: combine_substructure(|cx, span, substr| {
cs_op($op, $equal, cx, span, substr)
})
args: vec![borrowed_self()],
ret_ty: ret_ty,
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchesExplode,
combine_substructure: combine_substructure(|cx, span, substr| {
cs_partial_cmp(cx, span, substr)
})
args: vec!(),
ret_ty: nil_ty(),
attributes: attrs,
- const_nonmatching: true,
+ on_nonmatching: NonMatchesCollapse,
combine_substructure: combine_substructure(|a, b, c| {
cs_total_eq_assert(a, b, c)
})
args: vec!(borrowed_self()),
ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchesExplode,
combine_substructure: combine_substructure(|a, b, c| {
cs_cmp(a, b, c)
}),
vec!(box Self,
box Literal(Path::new_local("__E"))), true)),
attributes: Vec::new(),
- const_nonmatching: true,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|a, b, c| {
decodable_substructure(a, b, c)
}),
args: Vec::new(),
ret_ty: Self,
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|a, b, c| {
default_substructure(a, b, c)
})
box Literal(Path::new_local("__E"))),
true)),
attributes: Vec::new(),
- const_nonmatching: true,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|a, b, c| {
encodable_substructure(a, b, c)
}),
//! 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
-//! `const_nonmatching` is true, this will contain an empty list.
+//! `on_nonmatching == NonMatchesCollapse`, this will contain an empty list.
//! - `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
//! }])
//! ~~~
//!
-//! For `C1 {x}` and `C1 {x}`,
+//! For `C1 {x}` and `C1 {x}` ,
//!
//! ~~~text
//! EnumMatching(1, <ast::Variant for C1>,
//! (<ident of C1>, <span of C1>,
//! Named(~[(<ident of x>, <span of x>)]))])
//! ~~~
+//!
use std::cell::RefCell;
use std::gc::{Gc, GC};
pub methods: Vec<MethodDef<'a>>,
}
+#[deriving(PartialEq, Eq)]
+pub enum HandleNonMatchingEnums {
+ NonMatchesCollapse, // handle all non-matches via one `_ => ..` clause
+ NonMatchesExplode, // handle via n^k cases for n variants and k self-args
+ NonMatchHandlingIrrelevant, // cannot encounter two enums of Self type
+}
pub struct MethodDef<'a> {
/// name of the method
pub attributes: Vec<ast::Attribute>,
- /// if the value of the nonmatching enums is independent of the
- /// actual enum variants, i.e. can use _ => .. match.
- pub const_nonmatching: bool,
+ /// 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>>,
}
A2(int)
}
- // is equivalent to (with const_nonmatching == false)
+ // is equivalent to (with on_nonmatching == NonMatchesExplode)
impl PartialEq for A {
fn eq(&self, __arg_1: &A) {
// the code for nonmatching variants only matters when
// we've seen at least one other variant already
- if self.const_nonmatching && match_count > 0 {
+ 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,
args: vec!(Ptr(box Literal(args), Borrowed(None, MutMutable))),
ret_ty: nil_ty(),
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|a, b, c| {
hash_substructure(a, b, c)
})
true)),
// #[inline] liable to cause code-bloat
attributes: attrs.clone(),
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|c, s, sub| {
cs_from("i64", c, s, sub)
}),
true)),
// #[inline] liable to cause code-bloat
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|c, s, sub| {
cs_from("u64", c, s, sub)
}),
),
ret_ty: Self,
attributes: Vec::new(),
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|a, b, c| {
rand_substructure(a, b, c)
})
args: vec!(fmtr),
ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
attributes: Vec::new(),
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|a, b, c| {
show_substructure(a, b, c)
})
args: Vec::new(),
ret_ty: Self,
attributes: attrs.clone(),
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|a, b, c| {
zero_substructure(a, b, c)
})
args: Vec::new(),
ret_ty: Literal(Path::new(vec!("bool"))),
attributes: attrs,
- const_nonmatching: false,
+ on_nonmatching: NonMatchHandlingIrrelevant,
combine_substructure: combine_substructure(|cx, span, substr| {
cs_and(|cx, span, _, _| cx.span_bug(span,
"Non-matching enum \