Add support for multiple region bounds in where clauses
This commit is contained in:
parent
e0cac488ac
commit
d87b308b67
11 changed files with 79 additions and 24 deletions
|
@ -213,12 +213,14 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
||||||
visit::walk_ty_param_bounds_helper(self, bounds);
|
visit::walk_ty_param_bounds_helper(self, bounds);
|
||||||
}
|
}
|
||||||
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
||||||
ref bound,
|
ref bounds,
|
||||||
.. }) => {
|
.. }) => {
|
||||||
|
|
||||||
self.visit_lifetime_ref(lifetime);
|
self.visit_lifetime_ref(lifetime);
|
||||||
|
for bound in bounds.iter() {
|
||||||
self.visit_lifetime_ref(bound);
|
self.visit_lifetime_ref(bound);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
|
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ id,
|
||||||
ref path,
|
ref path,
|
||||||
ref ty,
|
ref ty,
|
||||||
|
@ -558,11 +560,14 @@ fn early_bound_lifetime_names(generics: &ast::Generics) -> Vec<ast::Name> {
|
||||||
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
|
visit::walk_ty_param_bounds_helper(&mut collector, bounds);
|
||||||
}
|
}
|
||||||
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
||||||
ref bound,
|
ref bounds,
|
||||||
..}) => {
|
..}) => {
|
||||||
collector.visit_lifetime_ref(lifetime);
|
collector.visit_lifetime_ref(lifetime);
|
||||||
|
|
||||||
|
for bound in bounds.iter() {
|
||||||
collector.visit_lifetime_ref(bound);
|
collector.visit_lifetime_ref(bound);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
&ast::WherePredicate::EqPredicate(_) => unimplemented!()
|
&ast::WherePredicate::EqPredicate(_) => unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1827,10 +1827,12 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||||
|
|
||||||
&ast::WherePredicate::RegionPredicate(ref region_pred) => {
|
&ast::WherePredicate::RegionPredicate(ref region_pred) => {
|
||||||
let r1 = ast_region_to_region(this.tcx(), ®ion_pred.lifetime);
|
let r1 = ast_region_to_region(this.tcx(), ®ion_pred.lifetime);
|
||||||
let r2 = ast_region_to_region(this.tcx(), ®ion_pred.bound);
|
for bound in region_pred.bounds.iter() {
|
||||||
|
let r2 = ast_region_to_region(this.tcx(), bound);
|
||||||
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
|
let pred = ty::Binder(ty::OutlivesPredicate(r1, r2));
|
||||||
result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
|
result.predicates.push(space, ty::Predicate::RegionOutlives(pred))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
|
&ast::WherePredicate::EqPredicate(ref eq_pred) => {
|
||||||
// FIXME(#20041)
|
// FIXME(#20041)
|
||||||
|
|
|
@ -430,11 +430,9 @@ pub struct WhereBoundPredicate {
|
||||||
pub struct WhereRegionPredicate {
|
pub struct WhereRegionPredicate {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub lifetime: Lifetime,
|
pub lifetime: Lifetime,
|
||||||
pub bound: Lifetime
|
pub bounds: Vec<Lifetime>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Copy for WhereRegionPredicate {}
|
|
||||||
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
pub struct WhereEqPredicate {
|
pub struct WhereEqPredicate {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
|
|
|
@ -435,7 +435,7 @@ impl<'a> TraitDef<'a> {
|
||||||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
lifetime: rb.lifetime,
|
lifetime: rb.lifetime,
|
||||||
bound: rb.bound
|
bounds: rb.bounds.iter().map(|b| b.clone()).collect()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::WherePredicate::EqPredicate(ref we) => {
|
ast::WherePredicate::EqPredicate(ref we) => {
|
||||||
|
|
|
@ -824,12 +824,12 @@ pub fn noop_fold_where_predicate<T: Folder>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime,
|
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime,
|
||||||
bound,
|
bounds,
|
||||||
span}) => {
|
span}) => {
|
||||||
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
|
||||||
span: fld.new_span(span),
|
span: fld.new_span(span),
|
||||||
lifetime: fld.fold_lifetime(lifetime),
|
lifetime: fld.fold_lifetime(lifetime),
|
||||||
bound: fld.fold_lifetime(bound)
|
bounds: bounds.move_map(|bound| fld.fold_lifetime(bound))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
|
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
|
||||||
|
|
|
@ -4199,9 +4199,8 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
self.eat(&token::Colon);
|
self.eat(&token::Colon);
|
||||||
|
|
||||||
// FIXME(#20049)
|
let bounds =
|
||||||
let bounding_lifetime =
|
self.parse_lifetimes(token::BinOp(token::Plus));
|
||||||
self.parse_lifetime();
|
|
||||||
|
|
||||||
let hi = self.span.hi;
|
let hi = self.span.hi;
|
||||||
let span = mk_sp(lo, hi);
|
let span = mk_sp(lo, hi);
|
||||||
|
@ -4210,7 +4209,7 @@ impl<'a> Parser<'a> {
|
||||||
ast::WhereRegionPredicate {
|
ast::WhereRegionPredicate {
|
||||||
span: span,
|
span: span,
|
||||||
lifetime: bounded_lifetime,
|
lifetime: bounded_lifetime,
|
||||||
bound: bounding_lifetime
|
bounds: bounds
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -2444,11 +2444,18 @@ impl<'a> State<'a> {
|
||||||
try!(self.print_bounds(":", bounds.as_slice()));
|
try!(self.print_bounds(":", bounds.as_slice()));
|
||||||
}
|
}
|
||||||
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
||||||
ref bound,
|
ref bounds,
|
||||||
..}) => {
|
..}) => {
|
||||||
try!(self.print_lifetime(lifetime));
|
try!(self.print_lifetime(lifetime));
|
||||||
try!(word(&mut self.s, ":"));
|
try!(word(&mut self.s, ":"));
|
||||||
|
|
||||||
|
for (i, bound) in bounds.iter().enumerate() {
|
||||||
try!(self.print_lifetime(bound));
|
try!(self.print_lifetime(bound));
|
||||||
|
|
||||||
|
if i != 0 {
|
||||||
|
try!(word(&mut self.s, ":"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
|
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
|
||||||
try!(self.print_path(path, false));
|
try!(self.print_path(path, false));
|
||||||
|
|
|
@ -590,11 +590,14 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics
|
||||||
walk_ty_param_bounds_helper(visitor, bounds);
|
walk_ty_param_bounds_helper(visitor, bounds);
|
||||||
}
|
}
|
||||||
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
||||||
ref bound,
|
ref bounds,
|
||||||
..}) => {
|
..}) => {
|
||||||
visitor.visit_lifetime_ref(lifetime);
|
visitor.visit_lifetime_ref(lifetime);
|
||||||
|
|
||||||
|
for bound in bounds.iter() {
|
||||||
visitor.visit_lifetime_ref(bound);
|
visitor.visit_lifetime_ref(bound);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
|
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
|
||||||
ref path,
|
ref path,
|
||||||
ref ty,
|
ref ty,
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn a<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) where 'b: 'a + 'c {
|
||||||
|
// Note: this is legal because of the `'b:'a` declaration.
|
||||||
|
*x = *y;
|
||||||
|
*z = *y;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn b<'a, 'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) {
|
||||||
|
// Illegal now because there is no `'b:'a` declaration.
|
||||||
|
*x = *y; //~ ERROR mismatched types
|
||||||
|
*z = *y; //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn c<'a,'b, 'c>(x: &mut &'a int, y: &mut &'b int, z: &mut &'c int) {
|
||||||
|
// Here we try to call `foo` but do not know that `'a` and `'b` are
|
||||||
|
// related as required.
|
||||||
|
a(x, y, z); //~ ERROR cannot infer
|
||||||
|
}
|
||||||
|
|
||||||
|
fn d() {
|
||||||
|
// 'a and 'b are early bound in the function `a` because they appear
|
||||||
|
// inconstraints:
|
||||||
|
let _: fn(&mut &int, &mut &int, &mut &int) = a; //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn e() {
|
||||||
|
// 'a and 'b are late bound in the function `b` because there are
|
||||||
|
// no constraints:
|
||||||
|
let _: fn(&mut &int, &mut &int, &mut &int) = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
|
@ -26,5 +26,5 @@ impl Bar<X> for int {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
1.method::<X>();
|
1.method::<X>();
|
||||||
//~^ ERROR the trait `Foo<_>` is not implemented for the type `X`
|
//~^ ERROR the trait `Foo<X>` is not implemented for the type `X`
|
||||||
}
|
}
|
|
@ -26,5 +26,5 @@ impl<T> Foo<T> {
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = Foo { value: Bar };
|
let x = Foo { value: Bar };
|
||||||
x.equals(&x);
|
x.equals(&x);
|
||||||
//~^ ERROR the trait `core::cmp::Eq` is not not implemented
|
//~^ ERROR the trait `core::cmp::Eq` is not implemented for the type `Bar`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue