]> git.lizzy.rs Git - rust.git/blob - crates/hir_ty/src/tests/coercion.rs
Merge #11840
[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(
50         r"
51 //- minicore: coerce_unsized
52 fn test() {
53     let x: &[isize] = &[1];
54                    // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
55     let x: *const [isize] = &[1];
56                          // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
57 }
58 ",
59     );
60 }
61
62 #[test]
63 fn custom_coerce_unsized() {
64     check(
65         r#"
66 //- minicore: coerce_unsized
67 use core::{marker::Unsize, ops::CoerceUnsized};
68
69 struct A<T: ?Sized>(*const T);
70 struct B<T: ?Sized>(*const T);
71 struct C<T: ?Sized> { inner: *const T }
72
73 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
74 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {}
75
76 fn foo1<T>(x: A<[T]>) -> A<[T]> { x }
77 fn foo2<T>(x: B<[T]>) -> B<[T]> { x }
78 fn foo3<T>(x: C<[T]>) -> C<[T]> { x }
79
80 fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) {
81     let d = foo1(a);
82               // ^ expected A<[{unknown}]>, got A<[u8; 2]>
83     let e = foo2(b);
84      // ^ type: B<[u8]>
85     let f = foo3(c);
86      // ^ type: C<[u8]>
87 }
88 "#,
89     );
90 }
91
92 #[test]
93 fn if_coerce() {
94     check_no_mismatches(
95         r#"
96 //- minicore: coerce_unsized
97 fn foo<T>(x: &[T]) -> &[T] { x }
98 fn test() {
99     let x = if true {
100         foo(&[1])
101          // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
102     } else {
103         &[1]
104     };
105 }
106 "#,
107     );
108 }
109
110 #[test]
111 fn if_else_coerce() {
112     check_no_mismatches(
113         r#"
114 //- minicore: coerce_unsized
115 fn foo<T>(x: &[T]) -> &[T] { x }
116 fn test() {
117     let x = if true {
118         &[1]
119     } else {
120         foo(&[1])
121     };
122 }
123 "#,
124     )
125 }
126
127 #[test]
128 fn match_first_coerce() {
129     check_no_mismatches(
130         r#"
131 //- minicore: coerce_unsized
132 fn foo<T>(x: &[T]) -> &[T] { x }
133 fn test(i: i32) {
134     let x = match i {
135         2 => foo(&[2]),
136               // ^^^^ adjustments: Deref(None), Borrow(Ref(Not)), Pointer(Unsize)
137         1 => &[1],
138         _ => &[3],
139     };
140 }
141 "#,
142     );
143 }
144
145 #[test]
146 fn match_second_coerce() {
147     check_no_mismatches(
148         r#"
149 //- minicore: coerce_unsized
150 fn foo<T>(x: &[T]) -> &[T] { loop {} }
151                           // ^^^^^^^ adjustments: NeverToAny
152 fn test(i: i32) {
153     let x = match i {
154         1 => &[1],
155         2 => foo(&[2]),
156         _ => &[3],
157     };
158 }
159 "#,
160     );
161 }
162
163 #[test]
164 fn coerce_merge_one_by_one1() {
165     cov_mark::check!(coerce_merge_fail_fallback);
166
167     check(
168         r"
169 fn test() {
170     let t = &mut 1;
171     let x = match 1 {
172         1 => t as *mut i32,
173         2 => t as &i32,
174            //^^^^^^^^^ expected *mut i32, got &i32
175         _ => t as *const i32,
176           // ^^^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer)
177
178     };
179     x;
180   //^ type: *const i32
181
182 }
183         ",
184     );
185 }
186
187 #[test]
188 fn return_coerce_unknown() {
189     check_types(
190         r"
191 fn foo() -> u32 {
192     return unknown;
193          //^^^^^^^ u32
194 }
195         ",
196     );
197 }
198
199 #[test]
200 fn coerce_autoderef() {
201     check_no_mismatches(
202         r"
203 struct Foo;
204 fn takes_ref_foo(x: &Foo) {}
205 fn test() {
206     takes_ref_foo(&Foo);
207     takes_ref_foo(&&Foo);
208     takes_ref_foo(&&&Foo);
209 }",
210     );
211 }
212
213 #[test]
214 fn coerce_autoderef_generic() {
215     check_no_mismatches(
216         r#"
217 struct Foo;
218 fn takes_ref<T>(x: &T) -> T { *x }
219 fn test() {
220     takes_ref(&Foo);
221     takes_ref(&&Foo);
222     takes_ref(&&&Foo);
223 }
224 "#,
225     );
226 }
227
228 #[test]
229 fn coerce_autoderef_block() {
230     check_no_mismatches(
231         r#"
232 //- minicore: deref
233 struct String {}
234 impl core::ops::Deref for String { type Target = str; }
235 fn takes_ref_str(x: &str) {}
236 fn returns_string() -> String { loop {} }
237 fn test() {
238     takes_ref_str(&{ returns_string() });
239                // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Not))), Borrow(Ref(Not))
240 }
241 "#,
242     );
243 }
244
245 #[test]
246 fn coerce_autoderef_implication_1() {
247     check_no_mismatches(
248         r"
249 //- minicore: deref
250 struct Foo<T>;
251 impl core::ops::Deref for Foo<u32> { type Target = (); }
252
253 fn takes_ref_foo<T>(x: &Foo<T>) {}
254 fn test() {
255     let foo = Foo;
256       //^^^ type: Foo<{unknown}>
257     takes_ref_foo(&foo);
258
259     let foo = Foo;
260       //^^^ type: Foo<u32>
261     let _: &() = &foo;
262 }",
263     );
264 }
265
266 #[test]
267 fn coerce_autoderef_implication_2() {
268     check(
269         r"
270 //- minicore: deref
271 struct Foo<T>;
272 impl core::ops::Deref for Foo<u32> { type Target = (); }
273
274 fn takes_ref_foo<T>(x: &Foo<T>) {}
275 fn test() {
276     let foo = Foo;
277       //^^^ type: Foo<{unknown}>
278     let _: &u32 = &Foo;
279                 //^^^^ expected &u32, got &Foo<{unknown}>
280 }",
281     );
282 }
283
284 #[test]
285 fn closure_return_coerce() {
286     check_no_mismatches(
287         r"
288 fn foo() {
289     let x = || {
290         if true {
291             return &1u32;
292         }
293         &&1u32
294     };
295 }",
296     );
297 }
298
299 #[test]
300 fn assign_coerce() {
301     check_no_mismatches(
302         r"
303 //- minicore: deref
304 struct String;
305 impl core::ops::Deref for String { type Target = str; }
306 fn g(_text: &str) {}
307 fn f(text: &str) {
308     let mut text = text;
309     let tmp = String;
310     text = &tmp;
311     g(text);
312 }
313 ",
314     );
315 }
316
317 #[test]
318 fn coerce_fn_item_to_fn_ptr() {
319     check_no_mismatches(
320         r"
321 fn foo(x: u32) -> isize { 1 }
322 fn test() {
323     let f: fn(u32) -> isize = foo;
324                            // ^^^ adjustments: Pointer(ReifyFnPointer)
325     let f: unsafe fn(u32) -> isize = foo;
326                                   // ^^^ adjustments: Pointer(ReifyFnPointer)
327 }",
328     );
329 }
330
331 #[test]
332 fn coerce_fn_items_in_match_arms() {
333     cov_mark::check!(coerce_fn_reification);
334
335     check_types(
336         r"
337 fn foo1(x: u32) -> isize { 1 }
338 fn foo2(x: u32) -> isize { 2 }
339 fn foo3(x: u32) -> isize { 3 }
340 fn test() {
341     let x = match 1 {
342         1 => foo1,
343         2 => foo2,
344         _ => foo3,
345     };
346     x;
347   //^ fn(u32) -> isize
348 }",
349     );
350 }
351
352 #[test]
353 fn coerce_closure_to_fn_ptr() {
354     check_no_mismatches(
355         r"
356 fn test() {
357     let f: fn(u32) -> isize = |x| { 1 };
358 }",
359     );
360 }
361
362 #[test]
363 fn coerce_placeholder_ref() {
364     // placeholders should unify, even behind references
365     check_no_mismatches(
366         r"
367 struct S<T> { t: T }
368 impl<TT> S<TT> {
369     fn get(&self) -> &TT {
370         &self.t
371     }
372 }",
373     );
374 }
375
376 #[test]
377 fn coerce_unsize_array() {
378     check_types(
379         r#"
380 //- minicore: coerce_unsized
381 fn test() {
382     let f: &[usize] = &[1, 2, 3];
383                       //^ usize
384 }"#,
385     );
386 }
387
388 #[test]
389 fn coerce_unsize_trait_object_simple() {
390     check_types(
391         r#"
392 //- minicore: coerce_unsized
393 trait Foo<T, U> {}
394 trait Bar<U, T, X>: Foo<T, U> {}
395 trait Baz<T, X>: Bar<usize, T, X> {}
396
397 struct S<T, X>;
398 impl<T, X> Foo<T, usize> for S<T, X> {}
399 impl<T, X> Bar<usize, T, X> for S<T, X> {}
400 impl<T, X> Baz<T, X> for S<T, X> {}
401
402 fn test() {
403     let obj: &dyn Baz<i8, i16> = &S;
404                                 //^ S<i8, i16>
405     let obj: &dyn Bar<_, i8, i16> = &S;
406                                    //^ S<i8, i16>
407     let obj: &dyn Foo<i8, _> = &S;
408                               //^ S<i8, {unknown}>
409 }"#,
410     );
411 }
412
413 #[test]
414 fn coerce_unsize_super_trait_cycle() {
415     check_no_mismatches(
416         r#"
417 //- minicore: coerce_unsized
418 trait A {}
419 trait B: C + A {}
420 trait C: B {}
421 trait D: C
422
423 struct S;
424 impl A for S {}
425 impl B for S {}
426 impl C for S {}
427 impl D for S {}
428
429 fn test() {
430     let obj: &dyn D = &S;
431     let obj: &dyn A = &S;
432 }
433 "#,
434     );
435 }
436
437 #[test]
438 fn coerce_unsize_generic() {
439     // FIXME: fix the type mismatches here
440     check(
441         r#"
442 //- minicore: coerce_unsized
443 struct Foo<T> { t: T };
444 struct Bar<T>(Foo<T>);
445
446 fn test() {
447     let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] };
448                                    //^^^^^^^^^ expected [usize], got [usize; 3]
449     let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] });
450                                        //^^^^^^^^^ expected [usize], got [usize; 3]
451 }
452 "#,
453     );
454 }
455
456 #[test]
457 fn coerce_unsize_apit() {
458     check(
459         r#"
460 //- minicore: coerce_unsized
461 trait Foo {}
462
463 fn test(f: impl Foo, g: &(impl Foo + ?Sized)) {
464     let _: &dyn Foo = &f;
465     let _: &dyn Foo = g;
466                     //^ expected &dyn Foo, got &impl Foo + ?Sized
467 }
468         "#,
469     );
470 }
471
472 #[test]
473 fn two_closures_lub() {
474     check_types(
475         r#"
476 fn foo(c: i32) {
477     let add = |a: i32, b: i32| a + b;
478     let sub = |a, b| a - b;
479             //^^^^^^^^^^^^ |i32, i32| -> i32
480     if c > 42 { add } else { sub };
481   //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32
482 }
483         "#,
484     )
485 }
486
487 #[test]
488 fn match_diverging_branch_1() {
489     check_types(
490         r#"
491 enum Result<T> { Ok(T), Err }
492 fn parse<T>() -> T { loop {} }
493
494 fn test() -> i32 {
495     let a = match parse() {
496         Ok(val) => val,
497         Err => return 0,
498     };
499     a
500   //^ i32
501 }
502         "#,
503     )
504 }
505
506 #[test]
507 fn match_diverging_branch_2() {
508     // same as 1 except for order of branches
509     check_types(
510         r#"
511 enum Result<T> { Ok(T), Err }
512 fn parse<T>() -> T { loop {} }
513
514 fn test() -> i32 {
515     let a = match parse() {
516         Err => return 0,
517         Ok(val) => val,
518     };
519     a
520   //^ i32
521 }
522         "#,
523     )
524 }
525
526 #[test]
527 fn panic_macro() {
528     check_no_mismatches(
529         r#"
530 mod panic {
531     #[macro_export]
532     pub macro panic_2015 {
533         () => (
534             $crate::panicking::panic()
535         ),
536     }
537 }
538
539 mod panicking {
540     pub fn panic() -> ! { loop {} }
541 }
542
543 #[rustc_builtin_macro = "core_panic"]
544 macro_rules! panic {
545     // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021`
546     // depending on the edition of the caller.
547     ($($arg:tt)*) => {
548         /* compiler built-in */
549     };
550 }
551
552 fn main() {
553     panic!()
554 }
555         "#,
556     );
557 }
558
559 #[test]
560 fn coerce_unsize_expected_type_1() {
561     check_no_mismatches(
562         r#"
563 //- minicore: coerce_unsized
564 fn main() {
565     let foo: &[u32] = &[1, 2];
566     let foo: &[u32] = match true {
567         true => &[1, 2],
568         false => &[1, 2, 3],
569     };
570     let foo: &[u32] = if true {
571         &[1, 2]
572     } else {
573         &[1, 2, 3]
574     };
575 }
576         "#,
577     );
578 }
579
580 #[test]
581 fn coerce_unsize_expected_type_2() {
582     check_no_mismatches(
583         r#"
584 //- minicore: coerce_unsized
585 struct InFile<T>;
586 impl<T> InFile<T> {
587     fn with_value<U>(self, value: U) -> InFile<U> { InFile }
588 }
589 struct RecordField;
590 trait AstNode {}
591 impl AstNode for RecordField {}
592
593 fn takes_dyn(it: InFile<&dyn AstNode>) {}
594
595 fn test() {
596     let x: InFile<()> = InFile;
597     let n = &RecordField;
598     takes_dyn(x.with_value(n));
599 }
600         "#,
601     );
602 }
603
604 #[test]
605 fn coerce_unsize_expected_type_3() {
606     check_no_mismatches(
607         r#"
608 //- minicore: coerce_unsized
609 enum Option<T> { Some(T), None }
610 struct RecordField;
611 trait AstNode {}
612 impl AstNode for RecordField {}
613
614 fn takes_dyn(it: Option<&dyn AstNode>) {}
615
616 fn test() {
617     let x: InFile<()> = InFile;
618     let n = &RecordField;
619     takes_dyn(Option::Some(n));
620 }
621         "#,
622     );
623 }
624
625 #[test]
626 fn coerce_unsize_expected_type_4() {
627     check_no_mismatches(
628         r#"
629 //- minicore: coerce_unsized
630 use core::{marker::Unsize, ops::CoerceUnsized};
631
632 struct B<T: ?Sized>(*const T);
633 impl<T: ?Sized> B<T> {
634     fn new(t: T) -> Self { B(&t) }
635 }
636
637 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {}
638
639 fn test() {
640     let _: B<[isize]> = B::new({ [1, 2, 3] });
641 }
642         "#,
643     );
644 }
645
646 #[test]
647 fn coerce_array_elems_lub() {
648     check_no_mismatches(
649         r#"
650 fn f() {}
651 fn g() {}
652
653 fn test() {
654     [f, g];
655 }
656         "#,
657     );
658 }
659
660 #[test]
661 fn coerce_type_var() {
662     check_types(
663         r#"
664 //- minicore: from, coerce_unsized
665 fn test() {
666     let x = ();
667     let _: &() = &x.into();
668 }               //^^^^^^^^ ()
669 "#,
670     )
671 }
672
673 #[test]
674 fn coerce_overloaded_binary_op_rhs() {
675     check_types(
676         r#"
677 //- minicore: deref, add
678
679 struct String {}
680 impl core::ops::Deref for String { type Target = str; }
681
682 impl core::ops::Add<&str> for String {
683     type Output = String;
684 }
685
686 fn test() {
687     let s1 = String {};
688     let s2 = String {};
689     s1 + &s2;
690   //^^^^^^^^ String
691 }
692
693         "#,
694     );
695 }