Skip to content

Commit bdd61f8

Browse files
committed
Add support for multiple region bounds in where clauses
1 parent e0cac48 commit bdd61f8

File tree

9 files changed

+76
-21
lines changed

9 files changed

+76
-21
lines changed

src/librustc/middle/resolve_lifetime.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,13 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
213213
visit::walk_ty_param_bounds_helper(self, bounds);
214214
}
215215
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
216-
ref bound,
216+
ref bounds,
217217
.. }) => {
218218

219219
self.visit_lifetime_ref(lifetime);
220-
self.visit_lifetime_ref(bound);
220+
for bound in bounds.iter() {
221+
self.visit_lifetime_ref(bound);
222+
}
221223
}
222224
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
223225
ref path,
@@ -558,10 +560,13 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
558560
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
559561
}
560562
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
561-
ref bound,
563+
ref bounds,
562564
..}) => {
563565
collector.visit_lifetime_ref(lifetime);
564-
collector.visit_lifetime_ref(bound);
566+
567+
for bound in bounds.iter() {
568+
collector.visit_lifetime_ref(bound);
569+
}
565570
}
566571
&ast::WherePredicate::EqPredicate(_) => unimplemented!()
567572
}

src/librustc_typeck/collect.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1827,9 +1827,11 @@ fn ty_generics<'tcx,AC>(this: &AC,
18271827

18281828
&ast::WherePredicate::RegionPredicate(ref region_pred) => {
18291829
let r1 = ast_region_to_region(this.tcx(), &region_pred.lifetime);
1830-
let r2 = ast_region_to_region(this.tcx(), &region_pred.bound);
1831-
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1832-
result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1830+
for bound in region_pred.bounds.iter() {
1831+
let r2 = ast_region_to_region(this.tcx(), bound);
1832+
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
1833+
result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
1834+
}
18331835
}
18341836

18351837
&ast::WherePredicate::EqPredicate(ref eq_pred) => {

src/libsyntax/ast.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -430,11 +430,9 @@ pub struct WhereBoundPredicate {
430430
pub struct WhereRegionPredicate {
431431
pub span: Span,
432432
pub lifetime: Lifetime,
433-
pub bound: Lifetime
433+
pub bounds: Vec<Lifetime>,
434434
}
435435

436-
impl Copy for WhereRegionPredicate {}
437-
438436
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
439437
pub struct WhereEqPredicate {
440438
pub id: NodeId,

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ impl<'a> TraitDef<'a> {
435435
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
436436
span: self.span,
437437
lifetime: rb.lifetime,
438-
bound: rb.bound
438+
bounds: rb.bounds.iter().map(|b| b.clone()).collect()
439439
})
440440
}
441441
ast::WherePredicate::EqPredicate(ref we) => {

src/libsyntax/fold.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -824,12 +824,12 @@ pub fn noop_fold_where_predicate<T: Folder>(
824824
})
825825
}
826826
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime,
827-
bound,
827+
bounds,
828828
span}) => {
829829
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
830830
span: fld.new_span(span),
831831
lifetime: fld.fold_lifetime(lifetime),
832-
bound: fld.fold_lifetime(bound)
832+
bounds: bounds.move_map(|bound| fld.fold_lifetime(bound))
833833
})
834834
}
835835
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,

src/libsyntax/parse/parser.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -4199,9 +4199,8 @@ impl<'a> Parser<'a> {
41994199

42004200
self.eat(&token::Colon);
42014201

4202-
// FIXME(#20049)
4203-
let bounding_lifetime =
4204-
self.parse_lifetime();
4202+
let bounds =
4203+
self.parse_lifetimes(token::BinOp(token::Plus));
42054204

42064205
let hi = self.span.hi;
42074206
let span = mk_sp(lo, hi);
@@ -4210,7 +4209,7 @@ impl<'a> Parser<'a> {
42104209
ast::WhereRegionPredicate {
42114210
span: span,
42124211
lifetime: bounded_lifetime,
4213-
bound: bounding_lifetime
4212+
bounds: bounds
42144213
}
42154214
));
42164215

src/libsyntax/print/pprust.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -2444,11 +2444,18 @@ impl<'a> State<'a> {
24442444
try!(self.print_bounds(":", bounds.as_slice()));
24452445
}
24462446
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
2447-
ref bound,
2447+
ref bounds,
24482448
..}) => {
24492449
try!(self.print_lifetime(lifetime));
24502450
try!(word(&mut self.s, ":"));
2451-
try!(self.print_lifetime(bound));
2451+
2452+
for (i, bound) in bounds.iter().enumerate() {
2453+
try!(self.print_lifetime(bound));
2454+
2455+
if i != 0 {
2456+
try!(word(&mut self.s, ":"));
2457+
}
2458+
}
24522459
}
24532460
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
24542461
try!(self.print_path(path, false));

src/libsyntax/visit.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -590,10 +590,13 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics
590590
walk_ty_param_bounds_helper(visitor, bounds);
591591
}
592592
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
593-
ref bound,
593+
ref bounds,
594594
..}) => {
595595
visitor.visit_lifetime_ref(lifetime);
596-
visitor.visit_lifetime_ref(bound);
596+
597+
for bound in bounds.iter() {
598+
visitor.visit_lifetime_ref(bound);
599+
}
597600
}
598601
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
599602
ref path,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn a<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) where 'b: 'a + 'c {
12+
// Note: this is legal because of the `'b:'a` declaration.
13+
*x = *y;
14+
*z = *y;
15+
}
16+
17+
fn b<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) {
18+
// Illegal now because there is no `'b:'a` declaration.
19+
*x = *y; //~ ERROR mismatched types
20+
*z = *y; //~ ERROR mismatched types
21+
}
22+
23+
fn c<'a,'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) {
24+
// Here we try to call `foo` but do not know that `'a` and `'b` are
25+
// related as required.
26+
a(x, y, z); //~ ERROR cannot infer
27+
}
28+
29+
fn d() {
30+
// 'a and 'b are early bound in the function `a` because they appear
31+
// inconstraints:
32+
let _: fn(&mut &int, &mut &int, &mut &int) = a; //~ ERROR mismatched types
33+
}
34+
35+
fn e() {
36+
// 'a and 'b are late bound in the function `b` because there are
37+
// no constraints:
38+
let _: fn(&mut &int, &mut &int, &mut &int) = b;
39+
}
40+
41+
fn main() { }

0 commit comments

Comments
 (0)