File: projection-bound-cycle-generic.rs

package info (click to toggle)
rustc-web 1.78.0%2Bdfsg1-2~deb12u3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,245,420 kB
  • sloc: xml: 147,985; javascript: 18,022; sh: 11,083; python: 10,265; ansic: 6,172; cpp: 5,023; asm: 4,390; makefile: 4,269
file content (59 lines) | stat: -rw-r--r-- 1,503 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Like `projection-bound-cycle.rs` but this avoids using
// `feature(trivial_bounds)`.

trait Print {
    fn print();
}

trait Foo {
    type Item: Sized where <Self as Foo>::Item: Sized;
}

struct Number<T> { t: T }

impl<T> Foo for Number<T> {
    // Well-formedness checks require that the following
    // goal is true:
    // ```
    // if ([T]: Sized) { # if the where clauses hold
    //     [T]: Sized # then the bound on the associated type hold
    // }
    // ```
    // which it is :)
    type Item = [T] where [T]: Sized;
    //~^ ERROR overflow evaluating the requirement `<Number<T> as Foo>::Item == _`
}

struct OnlySized<T> where T: Sized { f: T }
impl<T> Print for OnlySized<T> {
    fn print() {
        println!("{}", std::mem::size_of::<T>());
    }
}

trait Bar {
    type Assoc: Print;
}

impl<T> Bar for T where T: Foo {
    // This is not ok, we need to prove `wf(<T as Foo>::Item)`, which requires
    // knowing that `<T as Foo>::Item: Sized` to satisfy the where clause. We
    // can use the bound on `Foo::Item` for this, but that requires
    // `wf(<T as Foo>::Item)`, which is an invalid cycle.
    type Assoc = OnlySized<<T as Foo>::Item>;
}

fn foo<T: Print>() {
    T::print() // oops, in fact `T = OnlySized<str>` which is ill-formed
}

fn bar<T: Bar>() {
    // we have `FromEnv(T: Bar)` hence
    // `<T as Bar>::Assoc` is well-formed and
    // `Implemented(<T as Bar>::Assoc: Print)` hold
    foo::<<T as Bar>::Assoc>()
}

fn main() {
    bar::<Number<u8>>()
}