summaryrefslogtreecommitdiffstats
path: root/src/test/ui/associated-types/defaults-suitability.rs
blob: 504c957d98753f377e5764171ce3bf3e0dceb382 (plain)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Checks that associated type defaults are properly validated.
//!
//! This means:
//! * Default types are checked against where clauses on the assoc. type
//!   (eg. `type Assoc: Clone = NotClone`)

#![feature(associated_type_defaults)]

struct NotClone;

// Assoc. type bounds must hold for the default type
trait Tr {
    type Ty: Clone = NotClone;
    //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
}

// Where-clauses defined on the trait must also be considered
trait Tr2
where
    Self::Ty: Clone,
{
    type Ty = NotClone;
    //~^ ERROR the trait bound `NotClone: Clone` is not satisfied
}

// Involved type parameters must fulfill all bounds required by defaults that mention them
trait Foo<T> {
    type Bar: Clone = Vec<T>;
    //~^ ERROR the trait bound `T: Clone` is not satisfied
}

trait Bar: Sized {
    // `(): Foo<Self>` might hold for some possible impls but not all.
    type Assoc: Foo<Self> = ();
    //~^ ERROR the trait bound `(): Foo<Self>` is not satisfied
}

trait IsU8<T> {}
impl<T> IsU8<u8> for T {}

// Test that mentioning the assoc. type inside where clauses is not allowed
trait C where
    Vec<Self::Assoc>: Clone,
    Self::Assoc: IsU8<Self::Assoc>,
    bool: IsU8<Self::Assoc>,
{
    type Assoc = u8;
}

// Test that we get all expected errors if that default is unsuitable
trait D where
    Vec<Self::Assoc>: Clone,
    Self::Assoc: IsU8<Self::Assoc>,
    bool: IsU8<Self::Assoc>,
{
    type Assoc = NotClone;
    //~^ ERROR the trait bound `NotClone: IsU8<NotClone>` is not satisfied
}

// Test behavior of the check when defaults refer to other defaults:

// Shallow substitution rejects this trait since `Baz` isn't guaranteed to be
// `Clone`.
trait Foo2<T> {
    type Bar: Clone = Vec<Self::Baz>;
    //~^ ERROR the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
    type Baz = T;
}

// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T`
// because of the shallow substitution. If we did a deep substitution instead,
// this would be accepted.
trait Foo25<T: Clone> {
    type Bar: Clone = Vec<Self::Baz>;
    //~^ ERROR the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
    type Baz = T;
}

// Adding the `Baz: Clone` bound isn't enough since the default is type
// parameter `T`, which also might not be `Clone`.
trait Foo3<T>
where
    Self::Bar: Clone,
    Self::Baz: Clone,
{
    type Bar = Vec<Self::Baz>;
    type Baz = T;
    //~^ ERROR the trait bound `T: Clone` is not satisfied
}

// This one finally works, with `Clone` bounds on all assoc. types and the type
// parameter.
trait Foo4<T>
where
    T: Clone,
{
    type Bar: Clone = Vec<Self::Baz>;
    type Baz: Clone = T;
}

fn main() {}