|  | use super::{check, check_no_mismatches, check_types}; | 
|  |  | 
|  | #[test] | 
|  | fn block_expr_type_mismatch() { | 
|  | check( | 
|  | r" | 
|  | fn test() { | 
|  | let a: i32 = { 1i64 }; | 
|  | // ^^^^ expected i32, got i64 | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_places() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | struct S<T> { a: T } | 
|  |  | 
|  | fn f<T>(_: &[T]) -> T { loop {} } | 
|  | fn g<T>(_: S<&[T]>) -> T { loop {} } | 
|  |  | 
|  | fn generate<T>() -> *mut [T; 2] { loop {} } | 
|  | fn test1<U>() -> *mut [U] { | 
|  | generate() | 
|  | } | 
|  |  | 
|  | fn test2() { | 
|  | let arr: &[u8; 1] = &[1]; | 
|  |  | 
|  | let a: &[_] = arr; | 
|  | let b = f(arr); | 
|  | let c: &[_] = { arr }; | 
|  | let d = g(S { a: arr }); | 
|  | let e: [&[_]; 1] = [arr]; | 
|  | let f: [&[_]; 2] = [arr; 2]; | 
|  | let g: (&[_], &[_]) = (arr, arr); | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn let_stmt_coerce() { | 
|  | check( | 
|  | r" | 
|  | //- minicore: coerce_unsized | 
|  | fn test() { | 
|  | let x: &[isize] = &[1]; | 
|  | // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize) | 
|  | let x: *const [isize] = &[1]; | 
|  | // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize) | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn custom_coerce_unsized() { | 
|  | check( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | use core::{marker::Unsize, ops::CoerceUnsized}; | 
|  |  | 
|  | struct A<T: ?Sized>(*const T); | 
|  | struct B<T: ?Sized>(*const T); | 
|  | struct C<T: ?Sized> { inner: *const T } | 
|  |  | 
|  | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} | 
|  | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<C<U>> for C<T> {} | 
|  |  | 
|  | fn foo1<T>(x: A<[T]>) -> A<[T]> { x } | 
|  | fn foo2<T>(x: B<[T]>) -> B<[T]> { x } | 
|  | fn foo3<T>(x: C<[T]>) -> C<[T]> { x } | 
|  |  | 
|  | fn test(a: A<[u8; 2]>, b: B<[u8; 2]>, c: C<[u8; 2]>) { | 
|  | let d = foo1(a); | 
|  | // ^ expected A<[{unknown}]>, got A<[u8; 2]> | 
|  | let e = foo2(b); | 
|  | // ^ type: B<[u8]> | 
|  | let f = foo3(c); | 
|  | // ^ type: C<[u8]> | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_coerce() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | fn foo<T>(x: &[T]) -> &[T] { x } | 
|  | fn test() { | 
|  | let x = if true { | 
|  | foo(&[1]) | 
|  | // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize) | 
|  | } else { | 
|  | &[1] | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_else_coerce() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | fn foo<T>(x: &[T]) -> &[T] { x } | 
|  | fn test() { | 
|  | let x = if true { | 
|  | &[1] | 
|  | } else { | 
|  | foo(&[1]) | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn if_else_adjust_for_branches_discard_type_var() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | fn test() { | 
|  | let f = || { | 
|  | if true { | 
|  | &"" | 
|  | } else { | 
|  | "" | 
|  | } | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn match_first_coerce() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | fn foo<T>(x: &[T]) -> &[T] { x } | 
|  | fn test(i: i32) { | 
|  | let x = match i { | 
|  | 2 => foo(&[2]), | 
|  | // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize) | 
|  | 1 => &[1], | 
|  | _ => &[3], | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn match_second_coerce() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | fn foo<T>(x: &[T]) -> &[T] { loop {} } | 
|  | // ^^^^^^^ adjustments: NeverToAny | 
|  | fn test(i: i32) { | 
|  | let x = match i { | 
|  | 1 => &[1], | 
|  | 2 => foo(&[2]), | 
|  | _ => &[3], | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_merge_one_by_one1() { | 
|  | check( | 
|  | r" | 
|  | fn test() { | 
|  | let t = &mut 1; | 
|  | let x = match 1 { | 
|  | 1 => t as *mut i32, | 
|  | //^ adjustments: Deref(None), Borrow(RawPtr(Mut)) | 
|  | _ => t as *const i32, | 
|  | }; | 
|  | x; | 
|  | // ^ type: *const i32 | 
|  | let x = match 1 { | 
|  | 1 => t as *mut i32, | 
|  | 2 => t as &i32, | 
|  | //^^^^^^^^^ expected *mut i32, got &'? i32 | 
|  | _ => t as *const i32, | 
|  | }; | 
|  |  | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn match_adjust_for_branches_discard_type_var() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | fn test() { | 
|  | let f = || { | 
|  | match 0i32 { | 
|  | 0i32 => &"", | 
|  | _ => "", | 
|  | } | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn return_coerce_unknown() { | 
|  | check_types( | 
|  | r" | 
|  | fn foo() -> u32 { | 
|  | return unknown; | 
|  | //^^^^^^^ u32 | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_autoderef() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | struct Foo; | 
|  | fn takes_ref_foo(x: &Foo) {} | 
|  | fn test() { | 
|  | takes_ref_foo(&Foo); | 
|  | takes_ref_foo(&&Foo); | 
|  | takes_ref_foo(&&&Foo); | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_autoderef_generic() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | struct Foo; | 
|  | fn takes_ref<T>(x: &T) -> T { *x } | 
|  | fn test() { | 
|  | takes_ref(&Foo); | 
|  | takes_ref(&&Foo); | 
|  | takes_ref(&&&Foo); | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_autoderef_block() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: deref | 
|  | struct String {} | 
|  | impl core::ops::Deref for String { type Target = str; } | 
|  | fn takes_ref_str(x: &str) {} | 
|  | fn returns_string() -> String { loop {} } | 
|  | fn test() { | 
|  | takes_ref_str(&{ returns_string() }); | 
|  | // ^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(None), Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('{error}, Not)) | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_autoderef_implication_1() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | //- minicore: deref, phantom_data | 
|  | use core::marker::PhantomData; | 
|  |  | 
|  | struct Foo<T>(PhantomData<T>); | 
|  | impl core::ops::Deref for Foo<u32> { type Target = (); } | 
|  |  | 
|  | fn takes_ref_foo<T>(x: &Foo<T>) {} | 
|  | fn test() { | 
|  | let foo = Foo(PhantomData); | 
|  | //^^^ type: Foo<{unknown}> | 
|  | takes_ref_foo(&foo); | 
|  |  | 
|  | let foo = Foo(PhantomData); | 
|  | //^^^ type: Foo<u32> | 
|  | let _: &() = &foo; | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_autoderef_implication_2() { | 
|  | check( | 
|  | r" | 
|  | //- minicore: deref, phantom_data | 
|  | use core::marker::PhantomData; | 
|  |  | 
|  | struct Foo<T>(PhantomData<T>); | 
|  | impl core::ops::Deref for Foo<u32> { type Target = (); } | 
|  |  | 
|  | fn takes_ref_foo<T>(x: &Foo<T>) {} | 
|  | fn test() { | 
|  | let foo = Foo(PhantomData); | 
|  | //^^^ type: Foo<{unknown}> | 
|  | let _: &u32 = &Foo(PhantomData); | 
|  | //^^^^^^^^^^^^^^^^^ expected &'? u32, got &'? Foo<{unknown}> | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn closure_return_coerce() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | fn foo() { | 
|  | let x = || { | 
|  | if true { | 
|  | return &1u32; | 
|  | } | 
|  | &&1u32 | 
|  | }; | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coroutine_yield_return_coerce() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | fn test() { | 
|  | let g = || { | 
|  | yield &1u32; | 
|  | yield &&1u32; | 
|  | if true { | 
|  | return &1u32; | 
|  | } | 
|  | &&1u32 | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn assign_coerce() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | //- minicore: deref | 
|  | struct String; | 
|  | impl core::ops::Deref for String { type Target = str; } | 
|  | fn g(_text: &str) {} | 
|  | fn f(text: &str) { | 
|  | let mut text = text; | 
|  | let tmp = String; | 
|  | text = &tmp; | 
|  | g(text); | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn destructuring_assign_coerce() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | //- minicore: deref | 
|  | struct String; | 
|  | impl core::ops::Deref for String { type Target = str; } | 
|  | fn g(_text: &str) {} | 
|  | fn f(text: &str) { | 
|  | let mut text = text; | 
|  | let tmp = String; | 
|  | [text, _] = [&tmp, &tmp]; | 
|  | g(text); | 
|  | } | 
|  | ", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_fn_item_to_fn_ptr() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | fn foo(x: u32) -> isize { 1 } | 
|  | fn test() { | 
|  | let f: fn(u32) -> isize = foo; | 
|  | // ^^^ adjustments: Pointer(ReifyFnPointer) | 
|  | let f: unsafe fn(u32) -> isize = foo; | 
|  | // ^^^ adjustments: Pointer(ReifyFnPointer), Pointer(UnsafeFnPointer) | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_fn_item_to_fn_ptr_in_array() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | fn foo(x: u32) -> isize { 1 } | 
|  | fn bar(x: u32) -> isize { 1 } | 
|  | fn test() { | 
|  | let f = [foo, bar]; | 
|  | // ^^^ adjustments: Pointer(ReifyFnPointer) | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_fn_items_in_match_arms() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | fn foo1(x: u32) -> isize { 1 } | 
|  | fn foo2(x: u32) -> isize { 2 } | 
|  | fn foo3(x: u32) -> isize { 3 } | 
|  | fn test() { | 
|  | let x = match 1 { | 
|  | 1 => foo1, | 
|  | // ^^^^ adjustments: Pointer(ReifyFnPointer) | 
|  | 2 => foo2, | 
|  | // ^^^^ adjustments: Pointer(ReifyFnPointer) | 
|  | _ => foo3, | 
|  | // ^^^^ adjustments: Pointer(ReifyFnPointer) | 
|  | }; | 
|  | x; | 
|  | }", | 
|  | ); | 
|  | check_types( | 
|  | r" | 
|  | fn foo1(x: u32) -> isize { 1 } | 
|  | fn foo2(x: u32) -> isize { 2 } | 
|  | fn foo3(x: u32) -> isize { 3 } | 
|  | fn test() { | 
|  | let x = match 1 { | 
|  | 1 => foo1, | 
|  | 2 => foo2, | 
|  | _ => foo3, | 
|  | }; | 
|  | x; | 
|  | //^ fn(u32) -> isize | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_closure_to_fn_ptr() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | fn test() { | 
|  | let f: fn(u32) -> u32 = |x| x; | 
|  | // ^^^^^ adjustments: Pointer(ClosureFnPointer(Safe)) | 
|  | let f: unsafe fn(u32) -> u32 = |x| x; | 
|  | // ^^^^^ adjustments: Pointer(ClosureFnPointer(Unsafe)) | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_placeholder_ref() { | 
|  | // placeholders should unify, even behind references | 
|  | check_no_mismatches( | 
|  | r" | 
|  | struct S<T> { t: T } | 
|  | impl<TT> S<TT> { | 
|  | fn get(&self) -> &TT { | 
|  | &self.t | 
|  | } | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_array() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | fn test() { | 
|  | let f: &[usize] = &[1, 2, 3]; | 
|  | //^ usize | 
|  | }"#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | // FIXME(next-solver): We could learn more from the `&S` -> `&dyn Foo<i8, _>` coercion if we followed the rustc model | 
|  | // where unsized is successful if all unsizing trait goals are certain (and non-unsizing goals are delayed). | 
|  | #[test] | 
|  | fn coerce_unsize_trait_object_simple() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | trait Foo<T, U> {} | 
|  | trait Bar<U, T, X>: Foo<T, U> {} | 
|  | trait Baz<T, X>: Bar<usize, T, X> {} | 
|  |  | 
|  | struct S<T, X>; | 
|  | impl<T, X> Foo<T, usize> for S<T, X> {} | 
|  | impl<T, X> Bar<usize, T, X> for S<T, X> {} | 
|  | impl<T, X> Baz<T, X> for S<T, X> {} | 
|  |  | 
|  | fn test() { | 
|  | let obj: &dyn Baz<i8, i16> = &S; | 
|  | //^ S<i8, i16> | 
|  | let obj: &dyn Bar<_, i8, i16> = &S; | 
|  | //^ S<i8, i16> | 
|  | //let obj: &dyn Foo<i8, _> = &S; | 
|  | // S<{unknown}, {unknown}> | 
|  | }"#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_super_trait_cycle() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | trait A {} | 
|  | trait B: C + A {} | 
|  | trait C: B {} | 
|  | trait D: C | 
|  |  | 
|  | struct S; | 
|  | impl A for S {} | 
|  | impl B for S {} | 
|  | impl C for S {} | 
|  | impl D for S {} | 
|  |  | 
|  | fn test() { | 
|  | let obj: &dyn D = &S; | 
|  | let obj: &dyn A = &S; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_generic() { | 
|  | check( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | struct Foo<T> { t: T }; | 
|  | struct Bar<T>(Foo<T>); | 
|  |  | 
|  | fn test() { | 
|  | let _: &Foo<[usize]> = &Foo { t: [1, 2, 3] }; | 
|  | //^^^^^^^^^^^^^^^^^^^^^ type: &'? Foo<[usize; 3]> | 
|  | let _: &Bar<[usize]> = &Bar(Foo { t: [1, 2, 3] }); | 
|  | //^^^^^^^^^^^^^^^^^^^^^^^^^^ type: &'? Bar<[usize; 3]> | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_apit() { | 
|  | check( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | trait Foo {} | 
|  |  | 
|  | fn test(f: impl Foo, g: &(impl Foo + ?Sized)) { | 
|  | let _: &dyn Foo = &f; | 
|  | let _: &dyn Foo = g; | 
|  | //^ expected &'? (dyn Foo + '?), got &'? impl Foo + ?Sized | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn two_closures_lub() { | 
|  | check_types( | 
|  | r#" | 
|  | fn foo(c: i32) { | 
|  | let add = |a: i32, b: i32| a + b; | 
|  | //^^^^^^^^^^^^^^^^^^^^^^ impl Fn(i32, i32) -> i32 | 
|  | let sub = |a, b| a - b; | 
|  | //^^^^^^^^^^^^ impl Fn(i32, i32) -> i32 | 
|  | if c > 42 { add } else { sub }; | 
|  | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fn(i32, i32) -> i32 | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn match_diverging_branch_1() { | 
|  | check_types( | 
|  | r#" | 
|  | enum Result<T> { Ok(T), Err } | 
|  | fn parse<T>() -> T { loop {} } | 
|  |  | 
|  | fn test() -> i32 { | 
|  | let a = match parse() { | 
|  | Ok(val) => val, | 
|  | Err => return 0, | 
|  | }; | 
|  | a | 
|  | //^ i32 | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn match_diverging_branch_2() { | 
|  | // same as 1 except for order of branches | 
|  | check_types( | 
|  | r#" | 
|  | enum Result<T> { Ok(T), Err } | 
|  | fn parse<T>() -> T { loop {} } | 
|  |  | 
|  | fn test() -> i32 { | 
|  | let a = match parse() { | 
|  | Err => return 0, | 
|  | Ok(val) => val, | 
|  | }; | 
|  | a | 
|  | //^ i32 | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn panic_macro() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | mod panic { | 
|  | #[macro_export] | 
|  | pub macro panic_2015 { | 
|  | () => ( | 
|  | $crate::panicking::panic() | 
|  | ), | 
|  | } | 
|  | } | 
|  |  | 
|  | mod panicking { | 
|  | pub fn panic() -> ! { loop {} } | 
|  | } | 
|  |  | 
|  | #[rustc_builtin_macro = "core_panic"] | 
|  | macro_rules! panic { | 
|  | // Expands to either `$crate::panic::panic_2015` or `$crate::panic::panic_2021` | 
|  | // depending on the edition of the caller. | 
|  | ($($arg:tt)*) => { | 
|  | /* compiler built-in */ | 
|  | }; | 
|  | } | 
|  |  | 
|  | fn main() { | 
|  | panic!() | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_expected_type_1() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | fn main() { | 
|  | let foo: &[u32] = &[1, 2]; | 
|  | let foo: &[u32] = match true { | 
|  | true => &[1, 2], | 
|  | false => &[1, 2, 3], | 
|  | }; | 
|  | let foo: &[u32] = if true { | 
|  | &[1, 2] | 
|  | } else { | 
|  | &[1, 2, 3] | 
|  | }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_expected_type_2() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | struct InFile<T>(T); | 
|  | impl<T> InFile<T> { | 
|  | fn with_value<U>(self, value: U) -> InFile<U> { InFile(loop {}) } | 
|  | } | 
|  | struct RecordField; | 
|  | trait AstNode {} | 
|  | impl AstNode for RecordField {} | 
|  |  | 
|  | fn takes_dyn(it: InFile<&dyn AstNode>) {} | 
|  |  | 
|  | fn test() { | 
|  | let x: InFile<()> = InFile(()); | 
|  | let n = &RecordField; | 
|  | takes_dyn(x.with_value(n)); | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_expected_type_3() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | enum Option<T> { Some(T), None } | 
|  | struct RecordField; | 
|  | trait AstNode {} | 
|  | impl AstNode for RecordField {} | 
|  |  | 
|  | fn takes_dyn(it: Option<&dyn AstNode>) {} | 
|  |  | 
|  | fn test() { | 
|  | let x: InFile<()> = InFile; | 
|  | let n = &RecordField; | 
|  | takes_dyn(Option::Some(n)); | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_unsize_expected_type_4() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | use core::{marker::Unsize, ops::CoerceUnsized}; | 
|  |  | 
|  | struct B<T: ?Sized>(*const T); | 
|  | impl<T: ?Sized> B<T> { | 
|  | fn new(t: T) -> Self { B(&t) } | 
|  | } | 
|  |  | 
|  | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<B<U>> for B<T> {} | 
|  |  | 
|  | fn test() { | 
|  | let _: B<[isize]> = B::new({ [1, 2, 3] }); | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_array_elems_lub() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | fn f() {} | 
|  | fn g() {} | 
|  |  | 
|  | fn test() { | 
|  | [f, g]; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_type_var() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: from, coerce_unsized | 
|  | fn test() { | 
|  | let x = (); | 
|  | let _: &() = &x.into(); | 
|  | }               //^^^^^^^^ () | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn coerce_overloaded_binary_op_rhs() { | 
|  | check_types( | 
|  | r#" | 
|  | //- minicore: deref, add | 
|  |  | 
|  | struct String {} | 
|  | impl core::ops::Deref for String { type Target = str; } | 
|  |  | 
|  | impl core::ops::Add<&str> for String { | 
|  | type Output = String; | 
|  | } | 
|  |  | 
|  | fn test() { | 
|  | let s1 = String {}; | 
|  | let s2 = String {}; | 
|  | s1 + &s2; | 
|  | //^^^^^^^^ String | 
|  | } | 
|  |  | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn assign_coerce_struct_fields() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | struct S; | 
|  | trait Tr {} | 
|  | impl Tr for S {} | 
|  | struct V<T> { t: T } | 
|  |  | 
|  | fn main() { | 
|  | let a: V<&dyn Tr>; | 
|  | a = V { t: &S }; | 
|  |  | 
|  | let mut a: V<&dyn Tr> = V { t: &S }; | 
|  | a = V { t: &S }; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn destructuring_assign_coerce_struct_fields() { | 
|  | check( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | struct S; | 
|  | trait Tr {} | 
|  | impl Tr for S {} | 
|  | struct V<T> { t: T } | 
|  |  | 
|  | fn main() { | 
|  | let a: V<&dyn Tr>; | 
|  | (a,) = V { t: &S }; | 
|  | //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,) | 
|  |  | 
|  | let mut a: V<&dyn Tr> = V { t: &S }; | 
|  | (a,) = V { t: &S }; | 
|  | //^^^^expected V<&'? S>, got (V<&'? (dyn Tr + '?)>,) | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn adjust_comparison_arguments() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | //- minicore: eq | 
|  | struct Struct; | 
|  | impl core::cmp::PartialEq for Struct { | 
|  | fn eq(&self, other: &Self) -> bool { true } | 
|  | } | 
|  | fn test() { | 
|  | Struct == Struct; | 
|  | // ^^^^^^ adjustments: Borrow(Ref('{error}, Not)) | 
|  | // ^^^^^^ adjustments: Borrow(Ref('{error}, Not)) | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn adjust_assign_lhs() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | //- minicore: add | 
|  | struct Struct; | 
|  | impl core::ops::AddAssign for Struct { | 
|  | fn add_assign(&mut self, other: Self) {} | 
|  | } | 
|  | fn test() { | 
|  | Struct += Struct; | 
|  | // ^^^^^^ adjustments: Borrow(Ref('{error}, Mut)) | 
|  | // ^^^^^^ adjustments: | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn adjust_index() { | 
|  | check_no_mismatches( | 
|  | r" | 
|  | //- minicore: index, slice, coerce_unsized | 
|  | fn test() { | 
|  | let x = [1, 2, 3]; | 
|  | x[2] = 6; | 
|  | // ^ adjustments: Borrow(Ref('?0, Mut)) | 
|  | } | 
|  | ", | 
|  | ); | 
|  | check_no_mismatches( | 
|  | r" | 
|  | //- minicore: index | 
|  | struct Struct; | 
|  | impl core::ops::Index<usize> for Struct { | 
|  | type Output = (); | 
|  |  | 
|  | fn index(&self, index: usize) -> &Self::Output { &() } | 
|  | } | 
|  | struct StructMut; | 
|  |  | 
|  | impl core::ops::Index<usize> for StructMut { | 
|  | type Output = (); | 
|  |  | 
|  | fn index(&self, index: usize) -> &Self::Output { &() } | 
|  | } | 
|  | impl core::ops::IndexMut<usize> for StructMut { | 
|  | fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut () } | 
|  | } | 
|  | fn test() { | 
|  | Struct[0]; | 
|  | // ^^^^^^ adjustments: Borrow(Ref('?0, Not)) | 
|  | StructMut[0]; | 
|  | // ^^^^^^^^^ adjustments: Borrow(Ref('?1, Not)) | 
|  | &mut StructMut[0]; | 
|  | // ^^^^^^^^^ adjustments: Borrow(Ref('?2, Mut)) | 
|  | }", | 
|  | ); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn regression_14443_dyn_coercion_block_impls() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | //- minicore: coerce_unsized | 
|  | trait T {} | 
|  |  | 
|  | fn dyn_t(d: &dyn T) {} | 
|  |  | 
|  | fn main() { | 
|  | struct A; | 
|  | impl T for A {} | 
|  |  | 
|  | let a = A; | 
|  |  | 
|  | let b = { | 
|  | struct B; | 
|  | impl T for B {} | 
|  |  | 
|  | B | 
|  | }; | 
|  |  | 
|  | dyn_t(&a); | 
|  | dyn_t(&b); | 
|  | } | 
|  | "#, | 
|  | ) | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn regression_18626() { | 
|  | check_no_mismatches( | 
|  | r#" | 
|  | fn f() { | 
|  | trait T { | 
|  | fn f() {} | 
|  | } | 
|  | impl T for i32 {} | 
|  | impl T for u32 {} | 
|  | &[i32::f, u32::f] as &[fn()]; | 
|  | } | 
|  | "#, | 
|  | ); | 
|  | } |