Skip to content

Commit 88ec268

Browse files
committed
---
yaml --- r: 106311 b: refs/heads/auto c: 4112941 h: refs/heads/master i: 106309: 7255729 106307: aef00c0 106303: cfa1581 v: v3
1 parent 30d334f commit 88ec268

File tree

10 files changed

+342
-89
lines changed

10 files changed

+342
-89
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1313
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1414
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1515
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
16-
refs/heads/auto: c329a17461b29da3c9f004154d32e4f153d727df
16+
refs/heads/auto: 4112941202d89477f1b34f559f2c16ef981e8eb6
1717
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1818
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1919
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336

branches/auto/src/librustc/middle/trans/_match.rs

Lines changed: 81 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -256,43 +256,23 @@ enum Opt {
256256
vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
257257
}
258258

259+
fn lit_to_expr(tcx: &ty::ctxt, a: &Lit) -> @ast::Expr {
260+
match *a {
261+
ExprLit(existing_a_expr) => existing_a_expr,
262+
ConstLit(a_const) => const_eval::lookup_const_by_id(tcx, a_const).unwrap(),
263+
UnitLikeStructLit(_) => fail!("lit_to_expr: unexpected struct lit"),
264+
}
265+
}
266+
259267
fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
260268
match (a, b) {
269+
(&lit(UnitLikeStructLit(a)), &lit(UnitLikeStructLit(b))) => a == b,
261270
(&lit(a), &lit(b)) => {
262-
match (a, b) {
263-
(UnitLikeStructLit(a), UnitLikeStructLit(b)) => a == b,
264-
_ => {
265-
let a_expr;
266-
match a {
267-
ExprLit(existing_a_expr) => a_expr = existing_a_expr,
268-
ConstLit(a_const) => {
269-
let e = const_eval::lookup_const_by_id(tcx, a_const);
270-
a_expr = e.unwrap();
271-
}
272-
UnitLikeStructLit(_) => {
273-
fail!("UnitLikeStructLit should have been handled \
274-
above")
275-
}
276-
}
277-
278-
let b_expr;
279-
match b {
280-
ExprLit(existing_b_expr) => b_expr = existing_b_expr,
281-
ConstLit(b_const) => {
282-
let e = const_eval::lookup_const_by_id(tcx, b_const);
283-
b_expr = e.unwrap();
284-
}
285-
UnitLikeStructLit(_) => {
286-
fail!("UnitLikeStructLit should have been handled \
287-
above")
288-
}
289-
}
290-
291-
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
292-
Some(val1) => val1 == 0,
293-
None => fail!("compare_list_exprs: type mismatch"),
294-
}
295-
}
271+
let a_expr = lit_to_expr(tcx, &a);
272+
let b_expr = lit_to_expr(tcx, &b);
273+
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
274+
Some(val1) => val1 == 0,
275+
None => fail!("compare_list_exprs: type mismatch"),
296276
}
297277
}
298278
(&range(a1, a2), &range(b1, b2)) => {
@@ -310,6 +290,42 @@ fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
310290
}
311291
}
312292

293+
fn opt_overlap(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
294+
match (a, b) {
295+
(&lit(a), &lit(b)) => {
296+
let a_expr = lit_to_expr(tcx, &a);
297+
let b_expr = lit_to_expr(tcx, &b);
298+
match const_eval::compare_lit_exprs(tcx, a_expr, b_expr) {
299+
Some(val1) => val1 == 0,
300+
None => fail!("opt_overlap: type mismatch"),
301+
}
302+
}
303+
304+
(&range(a1, a2), &range(b1, b2)) => {
305+
let m1 = const_eval::compare_lit_exprs(tcx, a1, b2);
306+
let m2 = const_eval::compare_lit_exprs(tcx, b1, a2);
307+
match (m1, m2) {
308+
// two ranges [a1, a2] and [b1, b2] overlap iff:
309+
// a1 <= b2 && b1 <= a2
310+
(Some(val1), Some(val2)) => (val1 <= 0 && val2 <= 0),
311+
_ => fail!("opt_overlap: type mismatch"),
312+
}
313+
}
314+
315+
(&range(a1, a2), &lit(b)) | (&lit(b), &range(a1, a2)) => {
316+
let b_expr = lit_to_expr(tcx, &b);
317+
let m1 = const_eval::compare_lit_exprs(tcx, a1, b_expr);
318+
let m2 = const_eval::compare_lit_exprs(tcx, a2, b_expr);
319+
match (m1, m2) {
320+
// b is in range [a1, a2] iff a1 <= b and b <= a2
321+
(Some(val1), Some(val2)) => (val1 <= 0 && 0 <= val2),
322+
_ => fail!("opt_overlap: type mismatch"),
323+
}
324+
}
325+
_ => fail!("opt_overlap: expect lit or range")
326+
}
327+
}
328+
313329
pub enum opt_result<'a> {
314330
single_result(Result<'a>),
315331
lower_bound(Result<'a>),
@@ -490,7 +506,7 @@ fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
490506
}
491507
}
492508

493-
type enter_pat<'a> = 'a |@ast::Pat| -> Option<Vec<@ast::Pat> >;
509+
type enter_pat<'a> = 'a |@ast::Pat| -> Option<Vec<@ast::Pat>>;
494510

495511
fn enter_match<'r,'b>(
496512
bcx: &'b Block<'b>,
@@ -632,16 +648,30 @@ fn enter_opt<'r,'b>(
632648
let tcx = bcx.tcx();
633649
let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP};
634650
let mut i = 0;
651+
// By the virtue of fact that we are in `trans` already, `enter_opt` is able
652+
// to prune sub-match tree aggressively based on exact equality. But when it
653+
// comes to literal or range, that strategy may lead to wrong result if there
654+
// are guard function or multiple patterns inside tuple; in that case, pruning
655+
// based on the overlap of patterns is required.
656+
//
657+
// Ideally, when constructing the sub-match tree for certain arm, only those
658+
// arms beneath it matter. But that isn't how algorithm works right now and
659+
// all other arms are taken into consideration when computing `guarded` below.
660+
// That is ok since each round of `compile_submatch` guarantees to trim one
661+
// "column" of arm patterns and the algorithm will converge.
662+
let guarded = m.iter().any(|x| x.data.arm.guard.is_some());
663+
let multi_pats = m.len() > 0 && m[0].pats.len() > 1;
635664
enter_match(bcx, tcx.def_map, m, col, val, |p| {
636665
let answer = match p.node {
637666
ast::PatEnum(..) |
638667
ast::PatIdent(_, _, None) if pat_is_const(tcx.def_map, p) => {
639668
let const_def = tcx.def_map.borrow().get_copy(&p.id);
640669
let const_def_id = ast_util::def_id_of_def(const_def);
641-
if opt_eq(tcx, &lit(ConstLit(const_def_id)), opt) {
642-
Some(Vec::new())
643-
} else {
644-
None
670+
let konst = lit(ConstLit(const_def_id));
671+
match guarded || multi_pats {
672+
false if opt_eq(tcx, &konst, opt) => Some(Vec::new()),
673+
true if opt_overlap(tcx, &konst, opt) => Some(Vec::new()),
674+
_ => None,
645675
}
646676
}
647677
ast::PatEnum(_, ref subpats) => {
@@ -666,10 +696,20 @@ fn enter_opt<'r,'b>(
666696
}
667697
}
668698
ast::PatLit(l) => {
669-
if opt_eq(tcx, &lit(ExprLit(l)), opt) {Some(Vec::new())} else {None}
699+
let lit_expr = lit(ExprLit(l));
700+
match guarded || multi_pats {
701+
false if opt_eq(tcx, &lit_expr, opt) => Some(Vec::new()),
702+
true if opt_overlap(tcx, &lit_expr, opt) => Some(Vec::new()),
703+
_ => None,
704+
}
670705
}
671706
ast::PatRange(l1, l2) => {
672-
if opt_eq(tcx, &range(l1, l2), opt) {Some(Vec::new())} else {None}
707+
let rng = range(l1, l2);
708+
match guarded || multi_pats {
709+
false if opt_eq(tcx, &rng, opt) => Some(Vec::new()),
710+
true if opt_overlap(tcx, &rng, opt) => Some(Vec::new()),
711+
_ => None,
712+
}
673713
}
674714
ast::PatStruct(_, ref field_pats, _) => {
675715
if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {

branches/auto/src/libsyntax/parse/parser.rs

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ pub enum PathParsingMode {
111111
LifetimeAndTypesAndBounds,
112112
}
113113

114+
/// A pair of a path segment and group of type parameter bounds. (See `ast.rs`
115+
/// for the definition of a path segment.)
116+
struct PathSegmentAndBoundSet {
117+
segment: ast::PathSegment,
118+
bound_set: Option<OwnedSlice<TyParamBound>>,
119+
}
120+
114121
/// A path paired with optional type bounds.
115122
pub struct PathAndBounds {
116123
path: ast::Path,
@@ -1507,14 +1514,24 @@ impl<'a> Parser<'a> {
15071514
// First, parse an identifier.
15081515
let identifier = self.parse_ident();
15091516

1517+
// Next, parse a colon and bounded type parameters, if applicable.
1518+
let bound_set = if mode == LifetimeAndTypesAndBounds {
1519+
self.parse_optional_ty_param_bounds()
1520+
} else {
1521+
None
1522+
};
1523+
15101524
// Parse the '::' before type parameters if it's required. If
15111525
// it is required and wasn't present, then we're done.
15121526
if mode == LifetimeAndTypesWithColons &&
15131527
!self.eat(&token::MOD_SEP) {
1514-
segments.push(ast::PathSegment {
1515-
identifier: identifier,
1516-
lifetimes: Vec::new(),
1517-
types: OwnedSlice::empty(),
1528+
segments.push(PathSegmentAndBoundSet {
1529+
segment: ast::PathSegment {
1530+
identifier: identifier,
1531+
lifetimes: Vec::new(),
1532+
types: OwnedSlice::empty(),
1533+
},
1534+
bound_set: bound_set
15181535
});
15191536
break
15201537
}
@@ -1531,10 +1548,13 @@ impl<'a> Parser<'a> {
15311548
};
15321549

15331550
// Assemble and push the result.
1534-
segments.push(ast::PathSegment {
1535-
identifier: identifier,
1536-
lifetimes: lifetimes,
1537-
types: types,
1551+
segments.push(PathSegmentAndBoundSet {
1552+
segment: ast::PathSegment {
1553+
identifier: identifier,
1554+
lifetimes: lifetimes,
1555+
types: types,
1556+
},
1557+
bound_set: bound_set
15381558
});
15391559

15401560
// We're done if we don't see a '::', unless the mode required
@@ -1547,25 +1567,42 @@ impl<'a> Parser<'a> {
15471567
}
15481568
}
15491569

1550-
// Next, parse a colon and bounded type parameters, if applicable.
1551-
let bounds = if mode == LifetimeAndTypesAndBounds {
1552-
self.parse_optional_ty_param_bounds()
1553-
} else {
1554-
None
1555-
};
1556-
15571570
// Assemble the span.
15581571
let span = mk_sp(lo, self.last_span.hi);
15591572

1573+
// Assemble the path segments.
1574+
let mut path_segments = Vec::new();
1575+
let mut bounds = None;
1576+
let last_segment_index = segments.len() - 1;
1577+
for (i, segment_and_bounds) in segments.move_iter().enumerate() {
1578+
let PathSegmentAndBoundSet {
1579+
segment: segment,
1580+
bound_set: bound_set
1581+
} = segment_and_bounds;
1582+
path_segments.push(segment);
1583+
1584+
if bound_set.is_some() {
1585+
if i != last_segment_index {
1586+
self.span_err(span,
1587+
"type parameter bounds are allowed only \
1588+
before the last segment in a path")
1589+
}
1590+
1591+
bounds = bound_set
1592+
}
1593+
}
1594+
15601595
// Assemble the result.
1561-
PathAndBounds {
1596+
let path_and_bounds = PathAndBounds {
15621597
path: ast::Path {
15631598
span: span,
15641599
global: is_global,
1565-
segments: segments,
1600+
segments: path_segments,
15661601
},
15671602
bounds: bounds,
1568-
}
1603+
};
1604+
1605+
path_and_bounds
15691606
}
15701607

15711608
/// parses 0 or 1 lifetime

branches/auto/src/libsyntax/print/pprust.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ impl<'a> State<'a> {
15261526
}
15271527

15281528
let mut first = true;
1529-
for segment in path.segments.iter() {
1529+
for (i, segment) in path.segments.iter().enumerate() {
15301530
if first {
15311531
first = false
15321532
} else {
@@ -1535,6 +1535,14 @@ impl<'a> State<'a> {
15351535

15361536
try!(self.print_ident(segment.identifier));
15371537

1538+
// If this is the last segment, print the bounds.
1539+
if i == path.segments.len() - 1 {
1540+
match *opt_bounds {
1541+
None => {}
1542+
Some(ref bounds) => try!(self.print_bounds(bounds, true)),
1543+
}
1544+
}
1545+
15381546
if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
15391547
if colons_before_params {
15401548
try!(word(&mut self.s, "::"))
@@ -1563,11 +1571,7 @@ impl<'a> State<'a> {
15631571
try!(word(&mut self.s, ">"))
15641572
}
15651573
}
1566-
1567-
match *opt_bounds {
1568-
None => Ok(()),
1569-
Some(ref bounds) => self.print_bounds(bounds, true),
1570-
}
1574+
Ok(())
15711575
}
15721576

15731577
fn print_path(&mut self, path: &ast::Path,

branches/auto/src/test/compile-fail/kindck-owned-trait-contains.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ impl<A:Clone> Repeat<A> for A {
1414
fn get(&self) -> A { self.clone() }
1515
}
1616

17-
fn repeater<A:Clone>(v: A) -> ~Repeat<A>: {
18-
~v as ~Repeat<A>: // No
17+
fn repeater<A:Clone>(v: A) -> ~Repeat:<A> {
18+
~v as ~Repeat:<A> // No
1919
}
2020

2121
fn main() {

branches/auto/src/test/run-pass/alignment-gep-tup-like-1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ impl<A:Clone> Invokable<A> for Invoker<A> {
2727
}
2828
}
2929

30-
fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable<A>: {
30+
fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable:<A> {
3131
~Invoker {
3232
a: a,
3333
b: b,
34-
} as ~Invokable<A>:
34+
} as ~Invokable:<A>
3535
}
3636

3737
pub fn main() {

branches/auto/src/test/run-pass/close-over-big-then-small-data.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ impl<A:Clone> Invokable<A> for Invoker<A> {
3131
}
3232
}
3333

34-
fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable<A>: {
34+
fn f<A:Clone + 'static>(a: A, b: u16) -> ~Invokable:<A> {
3535
~Invoker {
3636
a: a,
3737
b: b,
38-
} as ~Invokable<A>:
38+
} as ~Invokable:<A>
3939
}
4040

4141
pub fn main() {

0 commit comments

Comments
 (0)