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