Skip to content

Commit cf73e36

Browse files
committed
Rework trait-bound-conversion so be based on the AST and rework collect
to pass in the appropriate ast::generics etc
1 parent 36d0471 commit cf73e36

9 files changed

+552
-266
lines changed

src/librustc/metadata/tydecode.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,22 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
835835
}
836836
}
837837

838+
fn parse_object_lifetime_default<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
839+
conv: &mut F)
840+
-> Option<ty::ObjectLifetimeDefault>
841+
where F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
842+
{
843+
match next(st) {
844+
'n' => None,
845+
'a' => Some(ty::ObjectLifetimeDefault::Ambiguous),
846+
's' => {
847+
let region = parse_region_(st, conv);
848+
Some(ty::ObjectLifetimeDefault::Specific(region))
849+
}
850+
_ => panic!("parse_object_lifetime_default: bad input")
851+
}
852+
}
853+
838854
fn parse_existential_bounds<'a,'tcx, F>(st: &mut PState<'a,'tcx>,
839855
mut conv: F)
840856
-> ty::ExistentialBounds<'tcx> where

src/librustc_typeck/collect.rs

Lines changed: 334 additions & 256 deletions
Large diffs are not rendered by default.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
// Test equality constraints in a where clause where the type being
12+
// equated appears in a supertrait.
13+
14+
pub trait Vehicle {
15+
type Color;
16+
17+
fn go(&self) { }
18+
}
19+
20+
pub trait Box {
21+
type Color;
22+
23+
fn mail(&self) { }
24+
}
25+
26+
fn a<C:Vehicle+Box>(_: C::Color) {
27+
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
28+
}
29+
30+
fn b<C>(_: C::Color) where C : Vehicle+Box {
31+
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
32+
}
33+
34+
fn c<C>(_: C::Color) where C : Vehicle, C : Box {
35+
//~^ ERROR ambiguous associated type `Color` in bounds of `C`
36+
}
37+
38+
struct D<X>;
39+
impl<X> D<X> where X : Vehicle {
40+
fn d(&self, _: X::Color) where X : Box { }
41+
//~^ ERROR ambiguous associated type `Color` in bounds of `X`
42+
}
43+
44+
trait E<X:Vehicle> {
45+
fn e(&self, _: X::Color) where X : Box;
46+
//~^ ERROR ambiguous associated type `Color` in bounds of `X`
47+
48+
fn f(&self, _: X::Color) where X : Box { }
49+
//~^ ERROR ambiguous associated type `Color` in bounds of `X`
50+
}
51+
52+
pub fn main() { }
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2015 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+
// Example cycle where a bound on `T` uses a shorthand for `T`. This
12+
// creates a cycle because we have to know the bounds on `T` to figure
13+
// out what trait defines `Item`, but we can't know the bounds on `T`
14+
// without knowing how to handle `T::Item`.
15+
//
16+
// Note that in the future cases like this could perhaps become legal,
17+
// if we got more fine-grained about our cycle detection or changed
18+
// how we handle `T::Item` resolution.
19+
20+
use std::ops::Add;
21+
22+
// Preamble.
23+
trait Trait { type Item; }
24+
25+
struct A<T>
26+
where T : Trait,
27+
T : Add<T::Item>
28+
//~^ ERROR illegal recursive type
29+
{
30+
data: T
31+
}
32+
33+
fn main() {
34+
}

src/test/compile-fail/cycle-trait-supertrait-direct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Test a supertrait cycle where a trait extends itself.
1212

1313
trait Chromosome: Chromosome {
14-
//~^ ERROR cyclic reference detected
14+
//~^ ERROR unsupported cyclic reference
1515
}
1616

1717
fn main() { }

src/test/compile-fail/cycle-trait-supertrait-indirect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ trait A: B {
1515
}
1616

1717
trait B: C { }
18-
//~^ ERROR cyclic reference detected
1918

2019
trait C: B { }
20+
//~^ ERROR unsupported cyclic reference
2121

2222
fn main() { }
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright 2015 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+
// Various uses of `T::Item` syntax where the bound that supplies
12+
// `Item` originates in a where-clause, not the declaration of
13+
// `T`. Issue #20300.
14+
15+
use std::marker::{MarkerTrait, PhantomData};
16+
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
17+
use std::sync::atomic::Ordering::SeqCst;
18+
19+
static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
20+
21+
// Preamble.
22+
trait Trait : MarkerTrait { type Item; }
23+
struct Struct;
24+
impl Trait for Struct {
25+
type Item = u32;
26+
}
27+
28+
// Where-clause attached on the method which declares `T`.
29+
struct A;
30+
impl A {
31+
fn foo<T>(_x: T::Item) where T: Trait {
32+
COUNTER.fetch_add(1, SeqCst);
33+
}
34+
}
35+
36+
// Where-clause attached on the method to a parameter from the struct.
37+
struct B<T>(PhantomData<T>);
38+
impl<T> B<T> {
39+
fn foo(_x: T::Item) where T: Trait {
40+
COUNTER.fetch_add(10, SeqCst);
41+
}
42+
}
43+
44+
// Where-clause attached to free fn.
45+
fn c<T>(_: T::Item) where T : Trait {
46+
COUNTER.fetch_add(100, SeqCst);
47+
}
48+
49+
// Where-clause attached to defaulted and non-defaulted trait method.
50+
trait AnotherTrait {
51+
fn method<T>(&self, _: T::Item) where T: Trait;
52+
fn default_method<T>(&self, _: T::Item) where T: Trait {
53+
COUNTER.fetch_add(1000, SeqCst);
54+
}
55+
}
56+
struct D;
57+
impl AnotherTrait for D {
58+
fn method<T>(&self, _: T::Item) where T: Trait {
59+
COUNTER.fetch_add(10000, SeqCst);
60+
}
61+
}
62+
63+
// Where-clause attached to trait and impl containing the method.
64+
trait YetAnotherTrait<T>
65+
where T : Trait
66+
{
67+
fn method(&self, _: T::Item);
68+
fn default_method(&self, _: T::Item) {
69+
COUNTER.fetch_add(100000, SeqCst);
70+
}
71+
}
72+
struct E<T>(PhantomData<T>);
73+
impl<T> YetAnotherTrait<T> for E<T>
74+
where T : Trait
75+
{
76+
fn method(&self, _: T::Item) {
77+
COUNTER.fetch_add(1000000, SeqCst);
78+
}
79+
}
80+
81+
// Where-clause attached to inherent impl containing the method.
82+
struct F<T>(PhantomData<T>);
83+
impl<T> F<T> where T : Trait {
84+
fn method(&self, _: T::Item) {
85+
COUNTER.fetch_add(10000000, SeqCst);
86+
}
87+
}
88+
89+
// Where-clause attached to struct.
90+
#[allow(dead_code)]
91+
struct G<T> where T : Trait {
92+
data: T::Item,
93+
phantom: PhantomData<T>,
94+
}
95+
96+
fn main() {
97+
A::foo::<Struct>(22);
98+
B::<Struct>::foo(22);
99+
c::<Struct>(22);
100+
D.method::<Struct>(22);
101+
D.default_method::<Struct>(22);
102+
E(PhantomData::<Struct>).method(22);
103+
E(PhantomData::<Struct>).default_method(22);
104+
F(PhantomData::<Struct>).method(22);
105+
G::<Struct> { data: 22, phantom: PhantomData };
106+
assert_eq!(COUNTER.load(SeqCst), 11111111);
107+
}

src/test/compile-fail/cycle-generic-bound.rs renamed to src/test/run-pass/cycle-generic-bound.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// Regression test for #15477. This test should pass, vs reporting an
12-
// error as it does now, but at least this test shows it doesn't
13-
// segfault.
11+
// Regression test for #15477. This test just needs to compile.
1412

15-
trait Chromosome<X: Chromosome> {
16-
//~^ ERROR cyclic reference detected
13+
use std::marker::PhantomFn;
14+
15+
trait Chromosome<X: Chromosome<i32>> : PhantomFn<(Self,X)> {
1716
}
1817

1918
fn main() { }

src/test/compile-fail/cycle-trait-type-trait.rs renamed to src/test/run-pass/cycle-trait-type-trait.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// Test a supertrait cycle where a trait extends itself.
11+
// Test a case where a supertrait references a type that references
12+
// the original trait. This poses no problem at the moment.
1213

13-
trait Chromosome: Get<Struct> {
14-
//~^ ERROR cyclic reference detected
14+
trait Chromosome: Get<Struct<i32>> {
1515
}
1616

1717
trait Get<A> {

0 commit comments

Comments
 (0)