Rework trait-bound-conversion so be based on the AST and rework collect

to pass in the appropriate ast::generics etc
This commit is contained in:
Niko Matsakis 2015-02-18 10:39:39 -05:00
parent 36d04711b7
commit cf73e36ab0
9 changed files with 549 additions and 263 deletions

View File

@ -835,6 +835,22 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
} }
} }
fn parse_object_lifetime_default<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
conv: &mut F)
-> Option<ty::ObjectLifetimeDefault>
where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
{
match next(st) {
'n' => None,
'a' => Some(ty::ObjectLifetimeDefault::Ambiguous),
's' => {
let region = parse_region_(st, conv);
Some(ty::ObjectLifetimeDefault::Specific(region))
}
_ => panic!("parse_object_lifetime_default: bad input")
}
}
fn parse_existential_bounds<'a,'tcx, F>(st: &mut PState<'a,'tcx>, fn parse_existential_bounds<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
mut conv: F) mut conv: F)
-> ty::ExistentialBounds<'tcx> where -> ty::ExistentialBounds<'tcx> where

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
// 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.
// Test equality constraints in a where clause where the type being
// equated appears in a supertrait.
pub trait Vehicle {
type Color;
fn go(&self) { }
}
pub trait Box {
type Color;
fn mail(&self) { }
}
fn a<C:Vehicle+Box>(_: C::Color) {
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
}
fn b<C>(_: C::Color) where C : Vehicle+Box {
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
}
fn c<C>(_: C::Color) where C : Vehicle, C : Box {
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
}
struct D<X>;
impl<X> D<X> where X : Vehicle {
fn d(&self, _: X::Color) where X : Box { }
//~^ ERROR ambiguous associated type `Color` in bounds of `X`
}
trait E<X:Vehicle> {
fn e(&self, _: X::Color) where X : Box;
//~^ ERROR ambiguous associated type `Color` in bounds of `X`
fn f(&self, _: X::Color) where X : Box { }
//~^ ERROR ambiguous associated type `Color` in bounds of `X`
}
pub fn main() { }

View File

@ -0,0 +1,34 @@
// Copyright 2015 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.
// Example cycle where a bound on `T` uses a shorthand for `T`. This
// creates a cycle because we have to know the bounds on `T` to figure
// out what trait defines `Item`, but we can't know the bounds on `T`
// without knowing how to handle `T::Item`.
//
// Note that in the future cases like this could perhaps become legal,
// if we got more fine-grained about our cycle detection or changed
// how we handle `T::Item` resolution.
use std::ops::Add;
// Preamble.
trait Trait { type Item; }
struct A<T>
where T : Trait,
T : Add<T::Item>
//~^ ERROR illegal recursive type
{
data: T
}
fn main() {
}

View File

@ -11,7 +11,7 @@
// Test a supertrait cycle where a trait extends itself. // Test a supertrait cycle where a trait extends itself.
trait Chromosome: Chromosome { trait Chromosome: Chromosome {
//~^ ERROR cyclic reference detected //~^ ERROR unsupported cyclic reference
} }
fn main() { } fn main() { }

View File

@ -15,8 +15,8 @@ trait A: B {
} }
trait B: C { } trait B: C { }
//~^ ERROR cyclic reference detected
trait C: B { } trait C: B { }
//~^ ERROR unsupported cyclic reference
fn main() { } fn main() { }

View File

@ -0,0 +1,107 @@
// Copyright 2015 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.
// Various uses of `T::Item` syntax where the bound that supplies
// `Item` originates in a where-clause, not the declaration of
// `T`. Issue #20300.
use std::marker::{MarkerTrait, PhantomData};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
use std::sync::atomic::Ordering::SeqCst;
static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
// Preamble.
trait Trait : MarkerTrait { type Item; }
struct Struct;
impl Trait for Struct {
type Item = u32;
}
// Where-clause attached on the method which declares `T`.
struct A;
impl A {
fn foo<T>(_x: T::Item) where T: Trait {
COUNTER.fetch_add(1, SeqCst);
}
}
// Where-clause attached on the method to a parameter from the struct.
struct B<T>(PhantomData<T>);
impl<T> B<T> {
fn foo(_x: T::Item) where T: Trait {
COUNTER.fetch_add(10, SeqCst);
}
}
// Where-clause attached to free fn.
fn c<T>(_: T::Item) where T : Trait {
COUNTER.fetch_add(100, SeqCst);
}
// Where-clause attached to defaulted and non-defaulted trait method.
trait AnotherTrait {
fn method<T>(&self, _: T::Item) where T: Trait;
fn default_method<T>(&self, _: T::Item) where T: Trait {
COUNTER.fetch_add(1000, SeqCst);
}
}
struct D;
impl AnotherTrait for D {
fn method<T>(&self, _: T::Item) where T: Trait {
COUNTER.fetch_add(10000, SeqCst);
}
}
// Where-clause attached to trait and impl containing the method.
trait YetAnotherTrait<T>
where T : Trait
{
fn method(&self, _: T::Item);
fn default_method(&self, _: T::Item) {
COUNTER.fetch_add(100000, SeqCst);
}
}
struct E<T>(PhantomData<T>);
impl<T> YetAnotherTrait<T> for E<T>
where T : Trait
{
fn method(&self, _: T::Item) {
COUNTER.fetch_add(1000000, SeqCst);
}
}
// Where-clause attached to inherent impl containing the method.
struct F<T>(PhantomData<T>);
impl<T> F<T> where T : Trait {
fn method(&self, _: T::Item) {
COUNTER.fetch_add(10000000, SeqCst);
}
}
// Where-clause attached to struct.
#[allow(dead_code)]
struct G<T> where T : Trait {
data: T::Item,
phantom: PhantomData<T>,
}
fn main() {
A::foo::<Struct>(22);
B::<Struct>::foo(22);
c::<Struct>(22);
D.method::<Struct>(22);
D.default_method::<Struct>(22);
E(PhantomData::<Struct>).method(22);
E(PhantomData::<Struct>).default_method(22);
F(PhantomData::<Struct>).method(22);
G::<Struct> { data: 22, phantom: PhantomData };
assert_eq!(COUNTER.load(SeqCst), 11111111);
}

View File

@ -8,12 +8,11 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// Regression test for #15477. This test should pass, vs reporting an // Regression test for #15477. This test just needs to compile.
// error as it does now, but at least this test shows it doesn't
// segfault.
trait Chromosome<X: Chromosome> { use std::marker::PhantomFn;
//~^ ERROR cyclic reference detected
trait Chromosome<X: Chromosome<i32>> : PhantomFn<(Self,X)> {
} }
fn main() { } fn main() { }

View File

@ -8,10 +8,10 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
// Test a supertrait cycle where a trait extends itself. // Test a case where a supertrait references a type that references
// the original trait. This poses no problem at the moment.
trait Chromosome: Get<Struct> { trait Chromosome: Get<Struct<i32>> {
//~^ ERROR cyclic reference detected
} }
trait Get<A> { trait Get<A> {