Skip to content

Commit 5d1bdc3

Browse files
committed
Revise the const_nonmatching flag with more info about author's intent.
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.
1 parent c9a77d0 commit 5d1bdc3

File tree

14 files changed

+40
-23
lines changed

14 files changed

+40
-23
lines changed

src/libsyntax/ext/deriving/clone.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
3939
args: Vec::new(),
4040
ret_ty: Self,
4141
attributes: attrs,
42-
const_nonmatching: false,
42+
on_nonmatching: NonMatchHandlingIrrelevant,
4343
combine_substructure: combine_substructure(|c, s, sub| {
4444
cs_clone("Clone", c, s, sub)
4545
}),

src/libsyntax/ext/deriving/cmp/eq.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
4545
args: vec!(borrowed_self()),
4646
ret_ty: Literal(Path::new(vec!("bool"))),
4747
attributes: attrs,
48-
const_nonmatching: true,
48+
on_nonmatching: NonMatchesCollapse,
4949
combine_substructure: combine_substructure(|a, b, c| {
5050
$f(a, b, c)
5151
})

src/libsyntax/ext/deriving/cmp/ord.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
3535
args: vec!(borrowed_self()),
3636
ret_ty: Literal(Path::new(vec!("bool"))),
3737
attributes: attrs,
38-
const_nonmatching: false,
38+
on_nonmatching: NonMatchesExplode,
3939
combine_substructure: combine_substructure(|cx, span, substr| {
4040
cs_op($op, $equal, cx, span, substr)
4141
})
@@ -59,7 +59,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
5959
args: vec![borrowed_self()],
6060
ret_ty: ret_ty,
6161
attributes: attrs,
62-
const_nonmatching: false,
62+
on_nonmatching: NonMatchesExplode,
6363
combine_substructure: combine_substructure(|cx, span, substr| {
6464
cs_partial_cmp(cx, span, substr)
6565
})

src/libsyntax/ext/deriving/cmp/totaleq.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
5757
args: vec!(),
5858
ret_ty: nil_ty(),
5959
attributes: attrs,
60-
const_nonmatching: true,
60+
on_nonmatching: NonMatchesCollapse,
6161
combine_substructure: combine_substructure(|a, b, c| {
6262
cs_total_eq_assert(a, b, c)
6363
})

src/libsyntax/ext/deriving/cmp/totalord.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
4141
args: vec!(borrowed_self()),
4242
ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
4343
attributes: attrs,
44-
const_nonmatching: false,
44+
on_nonmatching: NonMatchesExplode,
4545
combine_substructure: combine_substructure(|a, b, c| {
4646
cs_cmp(a, b, c)
4747
}),

src/libsyntax/ext/deriving/decodable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
5454
vec!(box Self,
5555
box Literal(Path::new_local("__E"))), true)),
5656
attributes: Vec::new(),
57-
const_nonmatching: true,
57+
on_nonmatching: NonMatchHandlingIrrelevant,
5858
combine_substructure: combine_substructure(|a, b, c| {
5959
decodable_substructure(a, b, c)
6060
}),

src/libsyntax/ext/deriving/default.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
3939
args: Vec::new(),
4040
ret_ty: Self,
4141
attributes: attrs,
42-
const_nonmatching: false,
42+
on_nonmatching: NonMatchHandlingIrrelevant,
4343
combine_substructure: combine_substructure(|a, b, c| {
4444
default_substructure(a, b, c)
4545
})

src/libsyntax/ext/deriving/encodable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
121121
box Literal(Path::new_local("__E"))),
122122
true)),
123123
attributes: Vec::new(),
124-
const_nonmatching: true,
124+
on_nonmatching: NonMatchHandlingIrrelevant,
125125
combine_substructure: combine_substructure(|a, b, c| {
126126
encodable_substructure(a, b, c)
127127
}),

src/libsyntax/ext/deriving/generic/mod.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
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
@@ -135,7 +135,7 @@
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>,
@@ -172,6 +172,7 @@
172172
//! (<ident of C1>, <span of C1>,
173173
//! Named(~[(<ident of x>, <span of x>)]))])
174174
//! ~~~
175+
//!
175176
176177
use std::cell::RefCell;
177178
use 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

216223
pub 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,

src/libsyntax/ext/deriving/hash.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
5454
args: vec!(Ptr(box Literal(args), Borrowed(None, MutMutable))),
5555
ret_ty: nil_ty(),
5656
attributes: attrs,
57-
const_nonmatching: false,
57+
on_nonmatching: NonMatchHandlingIrrelevant,
5858
combine_substructure: combine_substructure(|a, b, c| {
5959
hash_substructure(a, b, c)
6060
})

src/libsyntax/ext/deriving/primitive.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
4545
true)),
4646
// #[inline] liable to cause code-bloat
4747
attributes: attrs.clone(),
48-
const_nonmatching: false,
48+
on_nonmatching: NonMatchHandlingIrrelevant,
4949
combine_substructure: combine_substructure(|c, s, sub| {
5050
cs_from("i64", c, s, sub)
5151
}),
@@ -62,7 +62,7 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
6262
true)),
6363
// #[inline] liable to cause code-bloat
6464
attributes: attrs,
65-
const_nonmatching: false,
65+
on_nonmatching: NonMatchHandlingIrrelevant,
6666
combine_substructure: combine_substructure(|c, s, sub| {
6767
cs_from("u64", c, s, sub)
6868
}),

src/libsyntax/ext/deriving/rand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
4545
),
4646
ret_ty: Self,
4747
attributes: Vec::new(),
48-
const_nonmatching: false,
48+
on_nonmatching: NonMatchHandlingIrrelevant,
4949
combine_substructure: combine_substructure(|a, b, c| {
5050
rand_substructure(a, b, c)
5151
})

src/libsyntax/ext/deriving/show.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
4545
args: vec!(fmtr),
4646
ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
4747
attributes: Vec::new(),
48-
const_nonmatching: false,
48+
on_nonmatching: NonMatchHandlingIrrelevant,
4949
combine_substructure: combine_substructure(|a, b, c| {
5050
show_substructure(a, b, c)
5151
})

src/libsyntax/ext/deriving/zero.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
3939
args: Vec::new(),
4040
ret_ty: Self,
4141
attributes: attrs.clone(),
42-
const_nonmatching: false,
42+
on_nonmatching: NonMatchHandlingIrrelevant,
4343
combine_substructure: combine_substructure(|a, b, c| {
4444
zero_substructure(a, b, c)
4545
})
@@ -51,7 +51,7 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
5151
args: Vec::new(),
5252
ret_ty: Literal(Path::new(vec!("bool"))),
5353
attributes: attrs,
54-
const_nonmatching: false,
54+
on_nonmatching: NonMatchHandlingIrrelevant,
5555
combine_substructure: combine_substructure(|cx, span, substr| {
5656
cs_and(|cx, span, _, _| cx.span_bug(span,
5757
"Non-matching enum \

0 commit comments

Comments
 (0)