]> git.lizzy.rs Git - rust.git/blob - src/test/ui/hr-subtype/hr-subtype.rs
b31f198bd97bf8cee87182f5f2efae6780ce8870
[rust.git] / src / test / ui / hr-subtype / hr-subtype.rs
1 // Targeted tests for the higher-ranked subtyping code.
2
3 #![feature(rustc_attrs)]
4 #![allow(dead_code)]
5
6 // revisions: bound_a_vs_bound_a
7 // revisions: bound_a_vs_bound_b
8 // revisions: bound_inv_a_vs_bound_inv_b
9 // revisions: bound_co_a_vs_bound_co_b
10 // revisions: bound_a_vs_free_x
11 // revisions: free_x_vs_free_x
12 // revisions: free_x_vs_free_y
13 // revisions: free_inv_x_vs_free_inv_y
14 // revisions: bound_a_b_vs_bound_a
15 // revisions: bound_co_a_b_vs_bound_co_a
16 // revisions: bound_contra_a_contra_b_ret_co_a
17 // revisions: bound_co_a_co_b_ret_contra_a
18 // revisions: bound_inv_a_b_vs_bound_inv_a
19 // revisions: bound_a_b_ret_a_vs_bound_a_ret_a
20
21 fn gimme<T>(_: Option<T>) { }
22
23 struct Inv<'a> { x: *mut &'a u32 }
24
25 struct Co<'a> { x: fn(&'a u32) }
26
27 struct Contra<'a> { x: &'a u32 }
28
29 macro_rules! check {
30     ($rev:ident: ($t1:ty, $t2:ty)) => {
31         #[cfg($rev)]
32         fn subtype<'x,'y:'x,'z:'y>() {
33             gimme::<$t2>(None::<$t1>);
34             //[free_inv_x_vs_free_inv_y]~^ ERROR
35         }
36
37         #[cfg($rev)]
38         fn supertype<'x,'y:'x,'z:'y>() {
39             gimme::<$t1>(None::<$t2>);
40             //[bound_a_vs_free_x]~^ ERROR
41             //[free_x_vs_free_y]~^^ ERROR
42             //[bound_inv_a_b_vs_bound_inv_a]~^^^ ERROR
43             //[bound_a_b_ret_a_vs_bound_a_ret_a]~^^^^ ERROR
44             //[free_inv_x_vs_free_inv_y]~^^^^^ ERROR
45             //[bound_a_b_vs_bound_a]~^^^^^^ ERROR mismatched types
46             //[bound_co_a_co_b_ret_contra_a]~^^^^^^^ ERROR
47             //[bound_contra_a_contra_b_ret_co_a]~^^^^^^^^ ERROR
48             //[bound_co_a_b_vs_bound_co_a]~^^^^^^^^^ ERROR
49         }
50     }
51 }
52
53 // If both have bound regions, they are equivalent, regardless of
54 // variant.
55 check! { bound_a_vs_bound_a: (for<'a> fn(&'a u32),
56                               for<'a> fn(&'a u32)) }
57 check! { bound_a_vs_bound_b: (for<'a> fn(&'a u32),
58                               for<'b> fn(&'b u32)) }
59 check! { bound_inv_a_vs_bound_inv_b: (for<'a> fn(Inv<'a>),
60                                       for<'b> fn(Inv<'b>)) }
61 check! { bound_co_a_vs_bound_co_b: (for<'a> fn(Co<'a>),
62                                     for<'b> fn(Co<'b>)) }
63
64 // Bound is a subtype of free.
65 check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
66                              fn(&'x u32)) }
67
68 // Two free regions are relatable if subtyping holds.
69 check! { free_x_vs_free_x: (fn(&'x u32),
70                             fn(&'x u32)) }
71 check! { free_x_vs_free_y: (fn(&'x u32),
72                             fn(&'y u32)) }
73 check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>),
74                                     fn(Inv<'y>)) }
75
76 // Somewhat surprisingly, a fn taking two distinct bound lifetimes and
77 // a fn taking one bound lifetime can be interchangeable, but only if
78 // we are co- or contra-variant with respect to both lifetimes.
79 //
80 // The reason is:
81 // - if we are covariant, then 'a and 'b can be set to the call-site
82 //   intersection;
83 // - if we are contravariant, then 'a can be inferred to 'static.
84 check! { bound_a_b_vs_bound_a: (for<'a,'b> fn(&'a u32, &'b u32),
85                                 for<'a>    fn(&'a u32, &'a u32)) }
86 check! { bound_co_a_b_vs_bound_co_a: (for<'a,'b> fn(Co<'a>, Co<'b>),
87                                       for<'a>    fn(Co<'a>, Co<'a>)) }
88 check! { bound_contra_a_contra_b_ret_co_a: (for<'a,'b> fn(Contra<'a>, Contra<'b>) -> Co<'a>,
89                                             for<'a>    fn(Contra<'a>, Contra<'a>) -> Co<'a>) }
90 check! { bound_co_a_co_b_ret_contra_a: (for<'a,'b> fn(Co<'a>, Co<'b>) -> Contra<'a>,
91                                         for<'a>    fn(Co<'a>, Co<'a>) -> Contra<'a>) }
92
93 // If we make those lifetimes invariant, then the two types are not interchangeable.
94 check! { bound_inv_a_b_vs_bound_inv_a: (for<'a,'b> fn(Inv<'a>, Inv<'b>),
95                                         for<'a>    fn(Inv<'a>, Inv<'a>)) }
96 check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u32) -> &'a u32,
97                                             for<'a>    fn(&'a u32, &'a u32) -> &'a u32) }
98
99 #[rustc_error]
100 fn main() {
101 //[bound_a_vs_bound_a]~^ ERROR fatal error triggered by #[rustc_error]
102 //[bound_a_vs_bound_b]~^^ ERROR fatal error triggered by #[rustc_error]
103 //[bound_inv_a_vs_bound_inv_b]~^^^ ERROR fatal error triggered by #[rustc_error]
104 //[bound_co_a_vs_bound_co_b]~^^^^ ERROR fatal error triggered by #[rustc_error]
105 //[free_x_vs_free_x]~^^^^^ ERROR fatal error triggered by #[rustc_error]
106 }