3939//! same variant of the enum (e.g. `Some(1)`, `Some(3)` and `Some(4)`)
4040//! - `EnumNonMatching` when `Self` is an enum and the arguments are not
4141//! the same variant (e.g. `None`, `Some(1)` and `None`). If
42- //! `const_nonmatching` is true , this will contain an empty list.
42+ //! `on_nonmatching == NonMatchesCollapse` , this will contain an empty list.
4343//! - `StaticEnum` and `StaticStruct` for static methods, where the type
4444//! being derived upon is either an enum or struct respectively. (Any
4545//! argument with type Self is just grouped among the non-self
135135//! }])
136136//! ~~~
137137//!
138- //! For `C1 {x}` and `C1 {x}`,
138+ //! For `C1 {x}` and `C1 {x}` ,
139139//!
140140//! ~~~text
141141//! EnumMatching(1, <ast::Variant for C1>,
172172//! (<ident of C1>, <span of C1>,
173173//! Named(~[(<ident of x>, <span of x>)]))])
174174//! ~~~
175+ //!
175176
176177use std:: cell:: RefCell ;
177178use std:: gc:: { Gc , GC } ;
@@ -212,6 +213,12 @@ pub struct TraitDef<'a> {
212213 pub methods : Vec < MethodDef < ' a > > ,
213214}
214215
216+ #[ deriving( PartialEq , Eq ) ]
217+ pub enum HandleNonMatchingEnums {
218+ NonMatchesCollapse , // handle all non-matches via one `_ => ..` clause
219+ NonMatchesExplode , // handle via n^k cases for n variants and k self-args
220+ NonMatchHandlingIrrelevant , // cannot encounter two enums of Self type
221+ }
215222
216223pub struct MethodDef < ' a > {
217224 /// name of the method
@@ -232,9 +239,17 @@ pub struct MethodDef<'a> {
232239
233240 pub attributes : Vec < ast:: Attribute > ,
234241
235- /// if the value of the nonmatching enums is independent of the
236- /// actual enum variants, i.e. can use _ => .. match.
237- pub const_nonmatching : bool ,
242+ /// How to handle nonmatching enums; `NonMatchesCollapse`
243+ /// indicates value is independent of the actual enum variants,
244+ /// i.e. can use _ => .. match.
245+ ///
246+ /// Note that if this is `NonMatchesExplode`, then deriving will
247+ /// generate `Omega(n^k)` code, where `n` is the number of
248+ /// variants and `k` is the number of arguments of `Self` type for
249+ /// the method (including the `self` argument, if any). Strive to
250+ /// avoid use of `NonMatchesExplode`, to avoid generating
251+ /// quadratic amounts of code (#15375) or worse.
252+ pub on_nonmatching : HandleNonMatchingEnums ,
238253
239254 pub combine_substructure : RefCell < CombineSubstructureFunc < ' a > > ,
240255}
@@ -758,7 +773,7 @@ impl<'a> MethodDef<'a> {
758773 A2(int)
759774 }
760775
761- // is equivalent to (with const_nonmatching == false )
776+ // is equivalent to (with on_nonmatching == NonMatchesExplode )
762777
763778 impl PartialEq for A {
764779 fn eq(&self, __arg_1: &A) {
@@ -893,7 +908,9 @@ impl<'a> MethodDef<'a> {
893908
894909 // the code for nonmatching variants only matters when
895910 // we've seen at least one other variant already
896- if self . const_nonmatching && match_count > 0 {
911+ assert ! ( match_count == 0 ||
912+ self . on_nonmatching != NonMatchHandlingIrrelevant ) ;
913+ if self . on_nonmatching == NonMatchesCollapse && match_count > 0 {
897914 // make a matching-variant match, and a _ match.
898915 let index = match matching {
899916 Some ( i) => i,
0 commit comments