]>
Commit | Line | Data |
---|---|---|
064997fb FG |
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 | ||
487cf647 FG |
125 | #[test] |
126 | fn if_else_adjust_for_branches_discard_type_var() { | |
127 | check_no_mismatches( | |
128 | r#" | |
129 | fn test() { | |
130 | let f = || { | |
131 | if true { | |
132 | &"" | |
133 | } else { | |
134 | "" | |
135 | } | |
136 | }; | |
137 | } | |
138 | "#, | |
139 | ); | |
140 | } | |
141 | ||
064997fb FG |
142 | #[test] |
143 | fn match_first_coerce() { | |
144 | check_no_mismatches( | |
145 | r#" | |
146 | //- minicore: coerce_unsized | |
147 | fn foo<T>(x: &[T]) -> &[T] { x } | |
148 | fn 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] | |
161 | fn match_second_coerce() { | |
162 | check_no_mismatches( | |
163 | r#" | |
164 | //- minicore: coerce_unsized | |
165 | fn foo<T>(x: &[T]) -> &[T] { loop {} } | |
166 | // ^^^^^^^ adjustments: NeverToAny | |
167 | fn 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] | |
179 | fn coerce_merge_one_by_one1() { | |
180 | cov_mark::check!(coerce_merge_fail_fallback); | |
181 | ||
182 | check( | |
183 | r" | |
184 | fn 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] |
203 | fn match_adjust_for_branches_discard_type_var() { | |
204 | check_no_mismatches( | |
205 | r#" | |
206 | fn test() { | |
207 | let f = || { | |
208 | match 0i32 { | |
209 | 0i32 => &"", | |
210 | _ => "", | |
211 | } | |
212 | }; | |
213 | } | |
214 | "#, | |
215 | ); | |
216 | } | |
217 | ||
064997fb FG |
218 | #[test] |
219 | fn return_coerce_unknown() { | |
220 | check_types( | |
221 | r" | |
222 | fn foo() -> u32 { | |
223 | return unknown; | |
224 | //^^^^^^^ u32 | |
225 | } | |
226 | ", | |
227 | ); | |
228 | } | |
229 | ||
230 | #[test] | |
231 | fn coerce_autoderef() { | |
232 | check_no_mismatches( | |
233 | r" | |
234 | struct Foo; | |
235 | fn takes_ref_foo(x: &Foo) {} | |
236 | fn test() { | |
237 | takes_ref_foo(&Foo); | |
238 | takes_ref_foo(&&Foo); | |
239 | takes_ref_foo(&&&Foo); | |
240 | }", | |
241 | ); | |
242 | } | |
243 | ||
244 | #[test] | |
245 | fn coerce_autoderef_generic() { | |
246 | check_no_mismatches( | |
247 | r#" | |
248 | struct Foo; | |
249 | fn takes_ref<T>(x: &T) -> T { *x } | |
250 | fn test() { | |
251 | takes_ref(&Foo); | |
252 | takes_ref(&&Foo); | |
253 | takes_ref(&&&Foo); | |
254 | } | |
255 | "#, | |
256 | ); | |
257 | } | |
258 | ||
259 | #[test] | |
260 | fn coerce_autoderef_block() { | |
353b0b11 | 261 | // FIXME: We should know mutability in overloaded deref |
064997fb FG |
262 | check_no_mismatches( |
263 | r#" | |
264 | //- minicore: deref | |
265 | struct String {} | |
266 | impl core::ops::Deref for String { type Target = str; } | |
267 | fn takes_ref_str(x: &str) {} | |
268 | fn returns_string() -> String { loop {} } | |
269 | fn 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] | |
278 | fn coerce_autoderef_implication_1() { | |
279 | check_no_mismatches( | |
280 | r" | |
281 | //- minicore: deref | |
282 | struct Foo<T>; | |
283 | impl core::ops::Deref for Foo<u32> { type Target = (); } | |
284 | ||
285 | fn takes_ref_foo<T>(x: &Foo<T>) {} | |
286 | fn 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] | |
299 | fn coerce_autoderef_implication_2() { | |
300 | check( | |
301 | r" | |
302 | //- minicore: deref | |
303 | struct Foo<T>; | |
304 | impl core::ops::Deref for Foo<u32> { type Target = (); } | |
305 | ||
306 | fn takes_ref_foo<T>(x: &Foo<T>) {} | |
307 | fn 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] | |
317 | fn closure_return_coerce() { | |
318 | check_no_mismatches( | |
319 | r" | |
320 | fn foo() { | |
321 | let x = || { | |
322 | if true { | |
323 | return &1u32; | |
324 | } | |
325 | &&1u32 | |
326 | }; | |
327 | }", | |
328 | ); | |
329 | } | |
330 | ||
2b03887a FG |
331 | #[test] |
332 | fn generator_yield_return_coerce() { | |
333 | check_no_mismatches( | |
334 | r#" | |
335 | fn 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] |
350 | fn assign_coerce() { | |
351 | check_no_mismatches( | |
352 | r" | |
353 | //- minicore: deref | |
354 | struct String; | |
355 | impl core::ops::Deref for String { type Target = str; } | |
356 | fn g(_text: &str) {} | |
357 | fn 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] | |
368 | fn destructuring_assign_coerce() { | |
369 | check_no_mismatches( | |
370 | r" | |
371 | //- minicore: deref | |
372 | struct String; | |
373 | impl core::ops::Deref for String { type Target = str; } | |
374 | fn g(_text: &str) {} | |
375 | fn 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] | |
386 | fn coerce_fn_item_to_fn_ptr() { | |
387 | check_no_mismatches( | |
388 | r" | |
389 | fn foo(x: u32) -> isize { 1 } | |
390 | fn 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] | |
400 | fn coerce_fn_items_in_match_arms() { | |
401 | cov_mark::check!(coerce_fn_reification); | |
402 | ||
403 | check_types( | |
404 | r" | |
405 | fn foo1(x: u32) -> isize { 1 } | |
406 | fn foo2(x: u32) -> isize { 2 } | |
407 | fn foo3(x: u32) -> isize { 3 } | |
408 | fn 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] | |
421 | fn coerce_closure_to_fn_ptr() { | |
422 | check_no_mismatches( | |
423 | r" | |
424 | fn 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] | |
434 | fn coerce_placeholder_ref() { | |
435 | // placeholders should unify, even behind references | |
436 | check_no_mismatches( | |
437 | r" | |
438 | struct S<T> { t: T } | |
439 | impl<TT> S<TT> { | |
440 | fn get(&self) -> &TT { | |
441 | &self.t | |
442 | } | |
443 | }", | |
444 | ); | |
445 | } | |
446 | ||
447 | #[test] | |
448 | fn coerce_unsize_array() { | |
449 | check_types( | |
450 | r#" | |
451 | //- minicore: coerce_unsized | |
452 | fn test() { | |
453 | let f: &[usize] = &[1, 2, 3]; | |
454 | //^ usize | |
455 | }"#, | |
456 | ); | |
457 | } | |
458 | ||
459 | #[test] | |
460 | fn coerce_unsize_trait_object_simple() { | |
461 | check_types( | |
462 | r#" | |
463 | //- minicore: coerce_unsized | |
464 | trait Foo<T, U> {} | |
465 | trait Bar<U, T, X>: Foo<T, U> {} | |
466 | trait Baz<T, X>: Bar<usize, T, X> {} | |
467 | ||
468 | struct S<T, X>; | |
469 | impl<T, X> Foo<T, usize> for S<T, X> {} | |
470 | impl<T, X> Bar<usize, T, X> for S<T, X> {} | |
471 | impl<T, X> Baz<T, X> for S<T, X> {} | |
472 | ||
473 | fn 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] | |
485 | fn coerce_unsize_super_trait_cycle() { | |
486 | check_no_mismatches( | |
487 | r#" | |
488 | //- minicore: coerce_unsized | |
489 | trait A {} | |
490 | trait B: C + A {} | |
491 | trait C: B {} | |
492 | trait D: C | |
493 | ||
494 | struct S; | |
495 | impl A for S {} | |
496 | impl B for S {} | |
497 | impl C for S {} | |
498 | impl D for S {} | |
499 | ||
500 | fn test() { | |
501 | let obj: &dyn D = &S; | |
502 | let obj: &dyn A = &S; | |
503 | } | |
504 | "#, | |
505 | ); | |
506 | } | |
507 | ||
508 | #[test] | |
509 | fn coerce_unsize_generic() { | |
510 | // FIXME: fix the type mismatches here | |
511 | check( | |
512 | r#" | |
513 | //- minicore: coerce_unsized | |
514 | struct Foo<T> { t: T }; | |
515 | struct Bar<T>(Foo<T>); | |
516 | ||
517 | fn 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] | |
528 | fn coerce_unsize_apit() { | |
529 | check( | |
530 | r#" | |
531 | //- minicore: coerce_unsized | |
532 | trait Foo {} | |
533 | ||
534 | fn 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] | |
544 | fn two_closures_lub() { | |
545 | check_types( | |
546 | r#" | |
547 | fn 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] | |
559 | fn match_diverging_branch_1() { | |
560 | check_types( | |
561 | r#" | |
562 | enum Result<T> { Ok(T), Err } | |
563 | fn parse<T>() -> T { loop {} } | |
564 | ||
565 | fn 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] | |
578 | fn match_diverging_branch_2() { | |
579 | // same as 1 except for order of branches | |
580 | check_types( | |
581 | r#" | |
582 | enum Result<T> { Ok(T), Err } | |
583 | fn parse<T>() -> T { loop {} } | |
584 | ||
585 | fn 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] | |
598 | fn panic_macro() { | |
599 | check_no_mismatches( | |
600 | r#" | |
601 | mod panic { | |
602 | #[macro_export] | |
603 | pub macro panic_2015 { | |
604 | () => ( | |
605 | $crate::panicking::panic() | |
606 | ), | |
607 | } | |
608 | } | |
609 | ||
610 | mod panicking { | |
611 | pub fn panic() -> ! { loop {} } | |
612 | } | |
613 | ||
614 | #[rustc_builtin_macro = "core_panic"] | |
615 | macro_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 | ||
623 | fn main() { | |
624 | panic!() | |
625 | } | |
626 | "#, | |
627 | ); | |
628 | } | |
629 | ||
630 | #[test] | |
631 | fn coerce_unsize_expected_type_1() { | |
632 | check_no_mismatches( | |
633 | r#" | |
634 | //- minicore: coerce_unsized | |
635 | fn 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] | |
652 | fn coerce_unsize_expected_type_2() { | |
653 | check_no_mismatches( | |
654 | r#" | |
655 | //- minicore: coerce_unsized | |
656 | struct InFile<T>; | |
657 | impl<T> InFile<T> { | |
658 | fn with_value<U>(self, value: U) -> InFile<U> { InFile } | |
659 | } | |
660 | struct RecordField; | |
661 | trait AstNode {} | |
662 | impl AstNode for RecordField {} | |
663 | ||
664 | fn takes_dyn(it: InFile<&dyn AstNode>) {} | |
665 | ||
666 | fn test() { | |
667 | let x: InFile<()> = InFile; | |
668 | let n = &RecordField; | |
669 | takes_dyn(x.with_value(n)); | |
670 | } | |
671 | "#, | |
672 | ); | |
673 | } | |
674 | ||
675 | #[test] | |
676 | fn coerce_unsize_expected_type_3() { | |
677 | check_no_mismatches( | |
678 | r#" | |
679 | //- minicore: coerce_unsized | |
680 | enum Option<T> { Some(T), None } | |
681 | struct RecordField; | |
682 | trait AstNode {} | |
683 | impl AstNode for RecordField {} | |
684 | ||
685 | fn takes_dyn(it: Option<&dyn AstNode>) {} | |
686 | ||
687 | fn test() { | |
688 | let x: InFile<()> = InFile; | |
689 | let n = &RecordField; | |
690 | takes_dyn(Option::Some(n)); | |
691 | } | |
692 | "#, | |
693 | ); | |
694 | } | |
695 | ||
696 | #[test] | |
697 | fn coerce_unsize_expected_type_4() { | |
698 | check_no_mismatches( | |
699 | r#" | |
700 | //- minicore: coerce_unsized | |
701 | use core::{marker::Unsize, ops::CoerceUnsized}; | |
702 | ||
703 | struct B<T: ?Sized>(*const T); | |
704 | impl<T: ?Sized> B<T> { | |
705 | fn new(t: T) -> Self { B(&t) } | |
706 | } | |
707 | ||
708 | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} | |
709 | ||
710 | fn test() { | |
711 | let _: B<[isize]> = B::new({ [1, 2, 3] }); | |
712 | } | |
713 | "#, | |
714 | ); | |
715 | } | |
716 | ||
717 | #[test] | |
718 | fn coerce_array_elems_lub() { | |
719 | check_no_mismatches( | |
720 | r#" | |
721 | fn f() {} | |
722 | fn g() {} | |
723 | ||
724 | fn test() { | |
725 | [f, g]; | |
726 | } | |
727 | "#, | |
728 | ); | |
729 | } | |
730 | ||
731 | #[test] | |
732 | fn coerce_type_var() { | |
733 | check_types( | |
734 | r#" | |
735 | //- minicore: from, coerce_unsized | |
736 | fn test() { | |
737 | let x = (); | |
738 | let _: &() = &x.into(); | |
739 | } //^^^^^^^^ () | |
740 | "#, | |
741 | ) | |
742 | } | |
743 | ||
744 | #[test] | |
745 | fn coerce_overloaded_binary_op_rhs() { | |
746 | check_types( | |
747 | r#" | |
748 | //- minicore: deref, add | |
749 | ||
750 | struct String {} | |
751 | impl core::ops::Deref for String { type Target = str; } | |
752 | ||
753 | impl core::ops::Add<&str> for String { | |
754 | type Output = String; | |
755 | } | |
756 | ||
757 | fn test() { | |
758 | let s1 = String {}; | |
759 | let s2 = String {}; | |
760 | s1 + &s2; | |
761 | //^^^^^^^^ String | |
762 | } | |
763 | ||
764 | "#, | |
765 | ); | |
766 | } | |
767 | ||
768 | #[test] | |
769 | fn assign_coerce_struct_fields() { | |
770 | check_no_mismatches( | |
771 | r#" | |
772 | //- minicore: coerce_unsized | |
773 | struct S; | |
774 | trait Tr {} | |
775 | impl Tr for S {} | |
776 | struct V<T> { t: T } | |
777 | ||
778 | fn 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] | |
790 | fn destructuring_assign_coerce_struct_fields() { | |
791 | check( | |
792 | r#" | |
793 | //- minicore: coerce_unsized | |
794 | struct S; | |
795 | trait Tr {} | |
796 | impl Tr for S {} | |
797 | struct V<T> { t: T } | |
798 | ||
799 | fn 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] | |
813 | fn adjust_comparison_arguments() { | |
814 | check_no_mismatches( | |
815 | r" | |
816 | //- minicore: eq | |
817 | struct Struct; | |
818 | impl core::cmp::PartialEq for Struct { | |
819 | fn eq(&self, other: &Self) -> bool { true } | |
820 | } | |
821 | fn test() { | |
822 | Struct == Struct; | |
823 | // ^^^^^^ adjustments: Borrow(Ref(Not)) | |
824 | // ^^^^^^ adjustments: Borrow(Ref(Not)) | |
825 | }", | |
826 | ); | |
827 | } | |
828 | ||
829 | #[test] | |
830 | fn adjust_assign_lhs() { | |
831 | check_no_mismatches( | |
832 | r" | |
833 | //- minicore: add | |
834 | struct Struct; | |
835 | impl core::ops::AddAssign for Struct { | |
836 | fn add_assign(&mut self, other: Self) {} | |
837 | } | |
838 | fn test() { | |
839 | Struct += Struct; | |
840 | // ^^^^^^ adjustments: Borrow(Ref(Mut)) | |
841 | // ^^^^^^ adjustments: | |
842 | }", | |
843 | ); | |
844 | } |