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