summaryrefslogtreecommitdiffstats
path: root/src/test/ui/associated-types/defaults-specialization.rs
blob: 553705b2a4fab39c944dbae4802093ac3439ff66 (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
//! Tests the interaction of associated type defaults and specialization.

#![feature(associated_type_defaults, specialization)]
//~^ WARN the feature `specialization` is incomplete

trait Tr {
    type Ty = u8;

    fn make() -> Self::Ty {
        0u8
        //~^ error: mismatched types
    }
}

struct A<T>(T);
// In a `default impl`, assoc. types are defaulted as well,
// so their values can't be assumed.
default impl<T> Tr for A<T> {
    fn make() -> u8 { 0 }
    //~^ ERROR method `make` has an incompatible type for trait
}

struct A2<T>(T);
// ...same, but in the method body
default impl<T> Tr for A2<T> {
    fn make() -> Self::Ty { 0u8 }
    //~^ ERROR mismatched types
}

struct B<T>(T);
// Explicitly defaulting the type does the same.
impl<T> Tr for B<T> {
    default type Ty = bool;

    fn make() -> bool { true }
    //~^ ERROR method `make` has an incompatible type for trait
}

struct B2<T>(T);
// ...same, but in the method body
impl<T> Tr for B2<T> {
    default type Ty = bool;

    fn make() -> Self::Ty { true }
    //~^ ERROR mismatched types
}

struct C<T>(T);
// Only the method is defaulted, so this is fine.
impl<T> Tr for C<T> {
    type Ty = bool;

    default fn make() -> bool { true }
}

// Defaulted method *can* assume the type, if the default is kept.
struct D<T>(T);
impl<T> Tr for D<T> {
    default fn make() -> u8 { 0 }
}

impl Tr for D<bool> {
    fn make() -> u8 { 255 }
}

struct E<T>(T);
impl<T> Tr for E<T> {
    default type Ty = bool;
    default fn make() -> Self::Ty { panic!(); }
}

// This impl specializes and sets `Ty`, it can rely on `Ty=String`.
impl Tr for E<bool> {
    type Ty = String;

    fn make() -> String { String::new() }
}

fn main() {
    // Test that we can assume the right set of assoc. types from outside the impl

    // This is a `default impl`, which does *not* mean that `A`/`A2` actually implement the trait.
    // cf. https://github.com/rust-lang/rust/issues/48515
    //let _: <A<()> as Tr>::Ty = 0u8;
    //let _: <A2<()> as Tr>::Ty = 0u8;

    let _: <B<()> as Tr>::Ty = 0u8;   //~ error: mismatched types
    let _: <B<()> as Tr>::Ty = true;  //~ error: mismatched types
    let _: <B2<()> as Tr>::Ty = 0u8;  //~ error: mismatched types
    let _: <B2<()> as Tr>::Ty = true; //~ error: mismatched types

    let _: <C<()> as Tr>::Ty = true;

    let _: <D<()> as Tr>::Ty = 0u8;
    let _: <D<bool> as Tr>::Ty = 0u8;
}