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