]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/coercion.rs
Clean up coercion tests
[rust.git] / crates / hir_ty / src / tests / coercion.rs
1 use super::{check, check_no_mismatches, check_types};
2
3 #[test]
4 fn block_expr_type_mismatch() {
5     // FIXME fix double type mismatch
6     check(
7         r"
8 fn test() {
9     let a: i32 = { 1i64 };
10               // ^^^^^^^^ expected i32, got i64
11                 // ^^^^ expected i32, got i64
12 }
13         ",
14     );
15 }
16
17 #[test]
18 fn coerce_places() {
19     check_no_mismatches(
20         r#"
21 //- minicore: coerce_unsized
22 struct S<T> { a: T }
23
24 fn f<T>(_: &[T]) -> T { loop {} }
25 fn g<T>(_: S<&[T]>) -> T { loop {} }
26
27 fn gen<T>() -> *mut [T; 2] { loop {} }
28 fn test1<U>() -> *mut [U] {
29     gen()
30 }
31
32 fn test2() {
33     let arr: &[u8; 1] = &[1];
34
35     let a: &[_] = arr;
36     let b = f(arr);
37     let c: &[_] = { arr };
38     let d = g(S { a: arr });
39     let e: [&[_]; 1] = [arr];
40     let f: [&[_]; 2] = [arr; 2];
41     let g: (&[_], &[_]) = (arr, arr);
42 }
43 "#,
44     );
45 }
46
47 #[test]
48 fn let_stmt_coerce() {
49     check_no_mismatches(
50         r"
51 //- minicore: coerce_unsized
52 fn test() {
53     let x: &[isize] = &[1];
54     let x: *const [isize] = &[1];
55 }
56 ",
57     );
58 }
59
60 #[test]
61 fn custom_coerce_unsized() {
62     check(
63         r#"
64 //- minicore: coerce_unsized
65 use core::{marker::Unsize, ops::CoerceUnsized};
66
67 struct A<T: ?Sized>(*const T);
68 struct B<T: ?Sized>(*const T);
69 struct C<T: ?Sized> { inner: *const T }
70
71 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
72 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
73
74 fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
75 fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
76 fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
77
78 fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
79     let d = foo1(a);
80               // ^ expected A<[{unknown}]>, got A<[u8; 2]>
81     let e = foo2(b);
82      // ^ type: B<[u8]>
83     let f = foo3(c);
84      // ^ type: C<[u8]>
85 }
86 "#,
87     );
88 }
89
90 #[test]
91 fn if_coerce() {
92     check_no_mismatches(
93         r#"
94 //- minicore: coerce_unsized
95 fn foo<T>(x: &[T]) -> &[T] { x }
96 fn test() {
97     let x = if true {
98         foo(&[1])
99     } else {
100         &[1]
101     };
102 }
103 "#,
104     );
105 }
106
107 #[test]
108 fn if_else_coerce() {
109     check_no_mismatches(
110         r#"
111 //- minicore: coerce_unsized
112 fn foo<T>(x: &[T]) -> &[T] { x }
113 fn test() {
114     let x = if true {
115         &[1]
116     } else {
117         foo(&[1])
118     };
119 }
120 "#,
121     )
122 }
123
124 #[test]
125 fn match_first_coerce() {
126     check_no_mismatches(
127         r#"
128 //- minicore: coerce_unsized
129 fn foo<T>(x: &[T]) -> &[T] { x }
130 fn test(i: i32) {
131     let x = match i {
132         2 => foo(&[2]),
133         1 => &[1],
134         _ => &[3],
135     };
136 }
137 "#,
138     );
139 }
140
141 #[test]
142 fn match_second_coerce() {
143     check_no_mismatches(
144         r#"
145 //- minicore: coerce_unsized
146 fn foo<T>(x: &[T]) -> &[T] { loop {} }
147 fn test(i: i32) {
148     let x = match i {
149         1 => &[1],
150         2 => foo(&[2]),
151         _ => &[3],
152     };
153 }
154 "#,
155     );
156 }
157
158 #[test]
159 fn coerce_merge_one_by_one1() {
160     cov_mark::check!(coerce_merge_fail_fallback);
161
162     check(
163         r"
164 fn test() {
165     let t = &mut 1;
166     let x = match 1 {
167         1 => t as *mut i32,
168         2 => t as &i32,
169            //^^^^^^^^^ expected *mut i32, got &i32
170         _ => t as *const i32,
171     };
172     x;
173   //^ type: *const i32
174 }
175         ",
176     );
177 }
178
179 #[test]
180 fn return_coerce_unknown() {
181     check_types(
182         r"
183 fn foo() -> u32 {
184     return unknown;
185          //^^^^^^^ u32
186 }
187         ",
188     );
189 }
190
191 #[test]
192 fn coerce_autoderef() {
193     check_no_mismatches(
194         r"
195 struct Foo;
196 fn takes_ref_foo(x: &Foo) {}
197 fn test() {
198     takes_ref_foo(&Foo);
199     takes_ref_foo(&&Foo);
200     takes_ref_foo(&&&Foo);
201 }",
202     );
203 }
204
205 #[test]
206 fn coerce_autoderef_generic() {
207     check_no_mismatches(
208         r#"
209 struct Foo;
210 fn takes_ref<T>(x: &T) -> T { *x }
211 fn test() {
212     takes_ref(&Foo);
213     takes_ref(&&Foo);
214     takes_ref(&&&Foo);
215 }
216 "#,
217     );
218 }
219
220 #[test]
221 fn coerce_autoderef_block() {
222     check_no_mismatches(
223         r#"
224 //- minicore: deref
225 struct String {}
226 impl core::ops::Deref for String { type Target = str; }
227 fn takes_ref_str(x: &str) {}
228 fn returns_string() -> String { loop {} }
229 fn test() {
230     takes_ref_str(&{ returns_string() });
231 }
232 "#,
233     );
234 }
235
236 #[test]
237 fn closure_return_coerce() {
238     check_no_mismatches(
239         r"
240 fn foo() {
241     let x = || {
242         if true {
243             return &1u32;
244         }
245         &&1u32
246     };
247 }",
248     );
249 }
250
251 #[test]
252 fn coerce_fn_item_to_fn_ptr() {
253     check_no_mismatches(
254         r"
255 fn foo(x: u32) -> isize { 1 }
256 fn test() {
257     let f: fn(u32) -> isize = foo;
258 }",
259     );
260 }
261
262 #[test]
263 fn coerce_fn_items_in_match_arms() {
264     cov_mark::check!(coerce_fn_reification);
265
266     check_types(
267         r"
268 fn foo1(x: u32) -> isize { 1 }
269 fn foo2(x: u32) -> isize { 2 }
270 fn foo3(x: u32) -> isize { 3 }
271 fn test() {
272     let x = match 1 {
273         1 => foo1,
274         2 => foo2,
275         _ => foo3,
276     };
277     x;
278   //^ fn(u32) -> isize
279 }",
280     );
281 }
282
283 #[test]
284 fn coerce_closure_to_fn_ptr() {
285     check_no_mismatches(
286         r"
287 fn test() {
288     let f: fn(u32) -> isize = |x| { 1 };
289 }",
290     );
291 }
292
293 #[test]
294 fn coerce_placeholder_ref() {
295     // placeholders should unify, even behind references
296     check_no_mismatches(
297         r"
298 struct S<T> { t: T }
299 impl<TT> S<TT> {
300     fn get(&self) -> &TT {
301         &self.t
302     }
303 }",
304     );
305 }
306
307 #[test]
308 fn coerce_unsize_array() {
309     check_types(
310         r#"
311 //- minicore: coerce_unsized
312 fn test() {
313     let f: &[usize] = &[1, 2, 3];
314                       //^ usize
315 }"#,
316     );
317 }
318
319 #[test]
320 fn coerce_unsize_trait_object_simple() {
321     check_types(
322         r#"
323 //- minicore: coerce_unsized
324 trait Foo<T, U> {}
325 trait Bar<U, T, X>: Foo<T, U> {}
326 trait Baz<T, X>: Bar<usize, T, X> {}
327
328 struct S<T, X>;
329 impl<T, X> Foo<T, usize> for S<T, X> {}
330 impl<T, X> Bar<usize, T, X> for S<T, X> {}
331 impl<T, X> Baz<T, X> for S<T, X> {}
332
333 fn test() {
334     let obj: &dyn Baz<i8, i16> = &S;
335                                 //^ S<i8, i16>
336     let obj: &dyn Bar<_, i8, i16> = &S;
337                                    //^ S<i8, i16>
338     let obj: &dyn Foo<i8, _> = &S;
339                               //^ S<i8, {unknown}>
340 }"#,
341     );
342 }
343
344 #[test]
345 fn coerce_unsize_super_trait_cycle() {
346     check_no_mismatches(
347         r#"
348 //- minicore: coerce_unsized
349 trait A {}
350 trait B: C + A {}
351 trait C: B {}
352 trait D: C
353
354 struct S;
355 impl A for S {}
356 impl B for S {}
357 impl C for S {}
358 impl D for S {}
359
360 fn test() {
361     let obj: &dyn D = &S;
362     let obj: &dyn A = &S;
363 }
364 "#,
365     );
366 }
367
368 #[test]
369 fn coerce_unsize_generic() {
370     // FIXME: fix the type mismatches here
371     check(
372         r#"
373 //- minicore: coerce_unsized
374 struct Foo<T> { t: T };
375 struct Bar<T>(Foo<T>);
376
377 fn test() {
378     let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
379                                    //^^^^^^^^^ expected [usize], got [usize; 3]
380     let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
381                          //^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &Bar<[usize]>, got &Bar<[i32; 3]>
382 }
383 "#,
384     );
385 }
386
387 #[test]
388 fn coerce_unsize_apit() {
389     // FIXME: #8984
390     check(
391         r#"
392 //- minicore: coerce_unsized
393 trait Foo {}
394
395 fn test(f: impl Foo) {
396     let _: &dyn Foo = &f;
397                     //^^ expected &dyn Foo, got &impl Foo
398 }
399         "#,
400     );
401 }
402
403 #[test]
404 fn two_closures_lub() {
405     check_types(
406         r#"
407 fn foo(c: i32) {
408     let add = |a: i32, b: i32| a + b;
409     let sub = |a, b| a - b;
410             //^^^^^^^^^^^^ |i32, i32| -> i32
411     if c > 42 { add } else { sub };
412   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32
413 }
414         "#,
415     )
416 }
417
418 #[test]
419 fn match_diverging_branch_1() {
420     check_types(
421         r#"
422 enum Result<T> { Ok(T), Err }
423 fn parse<T>() -> T { loop {} }
424
425 fn test() -> i32 {
426     let a = match parse() {
427         Ok(val) => val,
428         Err => return 0,
429     };
430     a
431   //^ i32
432 }
433         "#,
434     )
435 }
436
437 #[test]
438 fn match_diverging_branch_2() {
439     // same as 1 except for order of branches
440     check_types(
441         r#"
442 enum Result<T> { Ok(T), Err }
443 fn parse<T>() -> T { loop {} }
444
445 fn test() -> i32 {
446     let a = match parse() {
447         Err => return 0,
448         Ok(val) => val,
449     };
450     a
451   //^ i32
452 }
453         "#,
454     )
455 }
456
457 #[test]
458 fn panic_macro() {
459     check_no_mismatches(
460         r#"
461 mod panic {
462     #[macro_export]
463     pub macro panic_2015 {
464         () => (
465             $crate::panicking::panic()
466         ),
467     }
468 }
469
470 mod panicking {
471     pub fn panic() -> ! { loop {} }
472 }
473
474 #[rustc_builtin_macro = "core_panic"]
475 macro_rules! panic {
476     // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
477     // depending on the edition of the caller.
478     ($($arg:tt)*) => {
479         /* compiler built-in */
480     };
481 }
482
483 fn main() {
484     panic!()
485 }
486         "#,
487     );
488 }
489
490 #[test]
491 fn coerce_unsize_expected_type() {
492     check_no_mismatches(
493         r#"
494 //- minicore: coerce_unsized
495 fn main() {
496     let foo: &[u32] = &[1, 2];
497     let foo: &[u32] = match true {
498         true => &[1, 2],
499         false => &[1, 2, 3],
500     };
501     let foo: &[u32] = if true {
502         &[1, 2]
503     } else {
504         &[1, 2, 3]
505     };
506 }
507         "#,
508     );
509 }