]> git.lizzy.rs Git - rust.git/commitdiff
Revise the `const_nonmatching` flag with more info about author's intent.
authorFelix S. Klock II <pnkfelix@pnkfx.org>
Sat, 5 Jul 2014 06:04:07 +0000 (08:04 +0200)
committerFelix S. Klock II <pnkfelix@pnkfx.org>
Fri, 11 Jul 2014 15:01:01 +0000 (17:01 +0200)
In particular, I want authors of deriving modes to understand what
they are opting into (namely quadratic code size or worse) when they
select NonMatchesExplode.

14 files changed:
src/libsyntax/ext/deriving/clone.rs
src/libsyntax/ext/deriving/cmp/eq.rs
src/libsyntax/ext/deriving/cmp/ord.rs
src/libsyntax/ext/deriving/cmp/totaleq.rs
src/libsyntax/ext/deriving/cmp/totalord.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/default.rs
src/libsyntax/ext/deriving/encodable.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/deriving/hash.rs
src/libsyntax/ext/deriving/primitive.rs
src/libsyntax/ext/deriving/rand.rs
src/libsyntax/ext/deriving/show.rs
src/libsyntax/ext/deriving/zero.rs

index 93e4920bc1de43f5df09cda2be599d4018d10e3c..1a296906cc2f90218b1c8987b817a459a08078d7 100644 (file)
@@ -39,7 +39,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                 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)
                 }),
index ef8d477a98e678f83e9ecd3108c5ca5cf3c44857..2eaeb0df7fbb702014652620d7ba0ec2090a882d 100644 (file)
@@ -45,7 +45,7 @@ macro_rules! md (
                 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)
                 })
index 59cdec1ea88f07f240ad27aca105053111f6b475..c8edf5c4157afa15a88b2c4b67c45ce3398b5b41 100644 (file)
@@ -35,7 +35,7 @@ macro_rules! md (
                 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)
                 })
@@ -59,7 +59,7 @@ macro_rules! md (
         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)
         })
index 8b1e0498d253c43907b43ce5dc0ae37c2b0ae89d..09aa24f9bfb5d608d0eb38800e3a0e4e9979f2ef 100644 (file)
@@ -57,7 +57,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span,
                 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)
                 })
index 271aa90cd24a4f5ea1114745a08fdedd16cbc3c7..24785a026d18eafb9386b380e27044bdfa90ee9c 100644 (file)
@@ -41,7 +41,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
                 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)
                 }),
index 6da5f1e2700f1a969c5cb962f22a06697171dea9..3422819c4fa95dc2bf4655dcf6d98c22a4b883aa 100644 (file)
@@ -54,7 +54,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                           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)
                 }),
index dfebc0f5e642111a25a1015b857e67cbd66faf43..e6fffaa2a3f0b4d2f56a5a97f9d8bd026a0b73c1 100644 (file)
@@ -39,7 +39,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
                 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)
                 })
index 3b34407edfeaa364b0d98a667e6cfdb1aa593f42..21a4c5fdaaf71590a588b58569e0c618fc7f0044 100644 (file)
@@ -121,7 +121,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                                 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)
                 }),
index c9f5936a9bb0532cc94deabae2a2a46380c75e5c..eebf55033b374209ec46a871bf1384cbcb36c178 100644 (file)
@@ -39,7 +39,7 @@
 //!   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};
@@ -212,6 +213,12 @@ pub struct TraitDef<'a> {
     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
@@ -232,9 +239,17 @@ pub struct MethodDef<'a> {
 
     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>>,
 }
@@ -758,7 +773,7 @@ enum 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) {
@@ -893,7 +908,9 @@ fn build_enum_match(&self,
 
             // 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,
index 1b3ac47092a2d2e4dde17efc74a904ff3af74774..253f8de8cdf4de8f6987734444c3f92d42aca5b7 100644 (file)
@@ -54,7 +54,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                 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)
                 })
index 735497d9a2cf6ccfd6d50e9473d4545851cda2d5..b1071e106d985eb421e7b038bdc52b3d68caf63f 100644 (file)
@@ -45,7 +45,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                                            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)
                 }),
@@ -62,7 +62,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                                            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)
                 }),
index 34b5f120d6ab8a62c4e094b30da52323b0960eba..f286ddc6f3093a5d650059c6ceee42c22a352806 100644 (file)
@@ -45,7 +45,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                 ),
                 ret_ty: Self,
                 attributes: Vec::new(),
-                const_nonmatching: false,
+                on_nonmatching: NonMatchHandlingIrrelevant,
                 combine_substructure: combine_substructure(|a, b, c| {
                     rand_substructure(a, b, c)
                 })
index 05b5131d7e4d332d6843e089e39ae192233bb425..722541d7dae53761488e2eb211b65b487bb5e24f 100644 (file)
@@ -45,7 +45,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
                 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)
                 })
index 93947251223fd18eacc5a2e6f6d3eab521f48f88..1d4f4c78fc044caf32764c35f33e952407141ab3 100644 (file)
@@ -39,7 +39,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
                 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)
                 })
@@ -51,7 +51,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
                 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 \