use cov_mark::check;
use expect_test::expect;

use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types};

#[test]
fn infer_await() {
    check_types(
        r#"
//- minicore: future
struct IntFuture;

impl core::future::Future for IntFuture {
    type Output = u64;
}

fn test() {
    let r = IntFuture;
    let v = r.await;
    v;
} //^ u64
"#,
    );
}

#[test]
fn infer_async() {
    check_types(
        r#"
//- minicore: future
async fn foo() -> u64 { 128 }

fn test() {
    let r = foo();
    let v = r.await;
    v;
} //^ u64
"#,
    );
}

#[test]
fn infer_desugar_async() {
    check_types(
        r#"
//- minicore: future, sized
async fn foo() -> u64 { 128 }

fn test() {
    let r = foo();
    r;
} //^ impl Future<Output = u64>
"#,
    );
}

#[test]
fn infer_async_block() {
    check_types(
        r#"
//- minicore: future, option
async fn test() {
    let a = async { 42 };
    a;
//  ^ impl Future<Output = i32>
    let x = a.await;
    x;
//  ^ i32
    let b = async {}.await;
    b;
//  ^ ()
    let c = async {
        let y = None;
        y
    //  ^ Option<u64>
    };
    let _: Option<u64> = c.await;
    c;
//  ^ impl Future<Output = Option<u64>>
}
"#,
    );
}

#[test]
fn infer_async_closure() {
    check_types(
        r#"
//- minicore: future, option
async fn test() {
    let f = async move |x: i32| x + 42;
    f;
//  ^ impl Fn(i32) -> impl Future<Output = i32>
    let a = f(4);
    a;
//  ^ impl Future<Output = i32>
    let x = a.await;
    x;
//  ^ i32
    let f = async move || 42;
    f;
//  ^ impl Fn() -> impl Future<Output = i32>
    let a = f();
    a;
//  ^ impl Future<Output = i32>
    let x = a.await;
    x;
//  ^ i32
    let b = ((async move || {})()).await;
    b;
//  ^ ()
    let c = async move || {
        let y = None;
        y
    //  ^ Option<u64>
    };
    let _: Option<u64> = c().await;
    c;
//  ^ impl Fn() -> impl Future<Output = Option<u64>>
}
"#,
    );
}

#[test]
fn auto_sized_async_block() {
    check_no_mismatches(
        r#"
//- minicore: future, sized

use core::future::Future;
struct MyFut<Fut>(Fut);

impl<Fut> Future for MyFut<Fut>
where Fut: Future
{
    type Output = Fut::Output;
}
async fn reproduction() -> usize {
    let f = async {999usize};
    MyFut(f).await
}
    "#,
    );
    check_no_mismatches(
        r#"
//- minicore: future
//#11815
#[lang = "sized"]
pub trait Sized {}

#[lang = "unsize"]
pub trait Unsize<T: ?Sized> {}

#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T> {}

pub unsafe trait Allocator {}

pub struct Global;
unsafe impl Allocator for Global {}

#[lang = "owned_box"]
#[fundamental]
pub struct Box<T: ?Sized, A: Allocator = Global>(T);

impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<Box<U, A>> for Box<T, A> {}

fn send() ->  Box<dyn Future<Output = ()> + Send + 'static>{
    Box(async move {})
}

fn not_send() -> Box<dyn Future<Output = ()> + 'static> {
    Box(async move {})
}
    "#,
    );
}

#[test]
fn into_future_trait() {
    check_types(
        r#"
//- minicore: future
struct Futurable;
impl core::future::IntoFuture for Futurable {
    type Output = u64;
    type IntoFuture = IntFuture;
}

struct IntFuture;
impl core::future::Future for IntFuture {
    type Output = u64;
}

fn test() {
    let r = Futurable;
    let v = r.await;
    v;
} //^ u64
"#,
    );
}

#[test]
fn infer_try_trait() {
    check_types(
        r#"
//- minicore: try, result, from
fn test() {
    let r: Result<i32, u64> = Result::Ok(1);
    let v = r?;
    v;
} //^ i32
"#,
    );
}

#[test]
fn infer_try_block() {
    // FIXME: We should test more cases, but it currently doesn't work, since
    // our labeled block type inference is broken.
    check_types(
        r#"
//- minicore: try, option
fn test() {
    let x: Option<_> = try { Some(2)?; };
      //^ Option<()>
}
"#,
    );
}

#[test]
fn infer_for_loop() {
    check_types(
        r#"
//- minicore: iterator
//- /main.rs crate:main deps:alloc
#![no_std]
use alloc::collections::Vec;

fn test() {
    let v = Vec::new();
    v.push("foo");
    for x in v {
        x;
    } //^ &str
}

//- /alloc.rs crate:alloc
#![no_std]
pub mod collections {
    pub struct Vec<T> {}
    impl<T> Vec<T> {
        pub fn new() -> Self { Vec {} }
        pub fn push(&mut self, t: T) { }
    }

    impl<T> IntoIterator for Vec<T> {
        type Item = T;
        type IntoIter = IntoIter<T>;
    }

    struct IntoIter<T> {}
    impl<T> Iterator for IntoIter<T> {
        type Item = T;
    }
}
"#,
    );
}

#[test]
fn infer_ops_neg() {
    check_types(
        r#"
//- /main.rs crate:main deps:std
struct Bar;
struct Foo;

impl std::ops::Neg for Bar {
    type Output = Foo;
}

fn test() {
    let a = Bar;
    let b = -a;
    b;
} //^ Foo

//- /std.rs crate:std
#[prelude_import] use ops::*;
mod ops {
    #[lang = "neg"]
    pub trait Neg {
        type Output;
    }
}
"#,
    );
}

#[test]
fn infer_ops_not() {
    check_types(
        r#"
//- /main.rs crate:main deps:std
struct Bar;
struct Foo;

impl std::ops::Not for Bar {
    type Output = Foo;
}

fn test() {
    let a = Bar;
    let b = !a;
    b;
} //^ Foo

//- /std.rs crate:std
#[prelude_import] use ops::*;
mod ops {
    #[lang = "not"]
    pub trait Not {
        type Output;
    }
}
"#,
    );
}

#[test]
fn infer_from_bound_1() {
    check_types(
        r#"
trait Trait<T> {}
struct S<T>(T);
impl<U> Trait<U> for S<U> {}
fn foo<T: Trait<u32>>(t: T) {}
fn test() {
    let s = S(unknown);
           // ^^^^^^^ u32
    foo(s);
}"#,
    );
}

#[test]
fn infer_from_bound_2() {
    check_types(
        r#"
trait Trait<T> {}
struct S<T>(T);
impl<U> Trait<U> for S<U> {}
fn foo<U, T: Trait<U>>(t: T) -> U { loop {} }
fn test() {
    let s = S(unknown);
           // ^^^^^^^ u32
    let x: u32 = foo(s);
}"#,
    );
}

#[test]
fn trait_default_method_self_bound_implements_trait() {
    cov_mark::check!(trait_self_implements_self);
    check(
        r#"
trait Trait {
    fn foo(&self) -> i64;
    fn bar(&self) -> () {
        self.foo();
     // ^^^^^^^^^^ type: i64
    }
}"#,
    );
}

#[test]
fn trait_default_method_self_bound_implements_super_trait() {
    check(
        r#"
trait SuperTrait {
    fn foo(&self) -> i64;
}
trait Trait: SuperTrait {
    fn bar(&self) -> () {
        self.foo();
     // ^^^^^^^^^^ type: i64
    }
}"#,
    );
}

#[test]
fn infer_project_associated_type() {
    check_types(
        r#"
trait Iterable {
    type Item;
}
struct S;
impl Iterable for S { type Item = u32; }
fn test<T: Iterable>() {
    let x: <S as Iterable>::Item = 1;
                                // ^ u32
    let y: <T as Iterable>::Item = u;
                                // ^ Iterable::Item<T>
    let z: T::Item = u;
                  // ^ Iterable::Item<T>
    let a: <T>::Item = u;
                    // ^ Iterable::Item<T>
}"#,
    );
}

#[test]
fn infer_return_associated_type() {
    check_types(
        r#"
trait Iterable {
    type Item;
}
struct S;
impl Iterable for S { type Item = u32; }
fn foo1<T: Iterable>(t: T) -> T::Item { loop {} }
fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item { loop {} }
fn foo3<T: Iterable>(t: T) -> <T>::Item { loop {} }
fn test() {
    foo1(S);
 // ^^^^^^^ u32
    foo2(S);
 // ^^^^^^^ u32
    foo3(S);
 // ^^^^^^^ u32
}"#,
    );
}

#[test]
fn associated_type_shorthand_from_method_bound() {
    check_types(
        r#"
trait Iterable {
    type Item;
}
struct S<T>;
impl<T> S<T> {
    fn foo(self) -> T::Item where T: Iterable { loop {} }
}
fn test<T: Iterable>() {
    let s: S<T>;
    s.foo();
 // ^^^^^^^ Iterable::Item<T>
}"#,
    );
}

#[test]
fn associated_type_shorthand_from_self_issue_12484() {
    check_types(
        r#"
trait Bar {
    type A;
}
trait Foo {
    type A;
    fn test(a: Self::A, _: impl Bar) {
        a;
      //^ Foo::A<Self>
    }
}"#,
    );
}

#[test]
fn infer_associated_type_bound() {
    check_types(
        r#"
trait Iterable {
    type Item;
}
fn test<T: Iterable<Item=u32>>() {
    let y: T::Item = unknown;
                  // ^^^^^^^ u32
}"#,
    );
}

#[test]
fn infer_const_body() {
    // FIXME make check_types work with other bodies
    check_infer(
        r#"
const A: u32 = 1 + 1;
static B: u64 = { let x = 1; x };
"#,
        expect![[r#"
            15..16 '1': u32
            15..20 '1 + 1': u32
            19..20 '1': u32
            38..54 '{ let ...1; x }': u64
            44..45 'x': u64
            48..49 '1': u64
            51..52 'x': u64
        "#]],
    );
}

#[test]
fn tuple_struct_fields() {
    check_infer(
        r#"
struct S(i32, u64);
fn test() -> u64 {
    let a = S(4, 6);
    let b = a.0;
    a.1
}"#,
        expect![[r#"
            37..86 '{     ... a.1 }': u64
            47..48 'a': S
            51..52 'S': S(i32, u64) -> S
            51..58 'S(4, 6)': S
            53..54 '4': i32
            56..57 '6': u64
            68..69 'b': i32
            72..73 'a': S
            72..75 'a.0': i32
            81..82 'a': S
            81..84 'a.1': u64
        "#]],
    );
}

#[test]
fn tuple_struct_with_fn() {
    check_infer(
        r#"
struct S(fn(u32) -> u64);
fn test() -> u64 {
    let a = S(|i| 2*i as u64);
    let b = a.0(4);
    a.0(2)
}"#,
        expect![[r#"
            43..108 '{     ...0(2) }': u64
            53..54 'a': S
            57..58 'S': S(fn(u32) -> u64) -> S
            57..74 'S(|i| ...s u64)': S
            59..73 '|i| 2*i as u64': impl Fn(u32) -> u64
            60..61 'i': u32
            63..64 '2': u64
            63..73 '2*i as u64': u64
            65..66 'i': u32
            65..73 'i as u64': u64
            84..85 'b': u64
            88..89 'a': S
            88..91 'a.0': fn(u32) -> u64
            88..94 'a.0(4)': u64
            92..93 '4': u32
            100..101 'a': S
            100..103 'a.0': fn(u32) -> u64
            100..106 'a.0(2)': u64
            104..105 '2': u32
        "#]],
    );
}

#[test]
fn indexing_arrays() {
    check_infer(
        "fn main() { &mut [9][2]; }",
        expect![[r#"
            10..26 '{ &mut...[2]; }': ()
            12..23 '&mut [9][2]': &mut {unknown}
            17..20 '[9]': [i32; 1]
            17..23 '[9][2]': {unknown}
            18..19 '9': i32
            21..22 '2': i32
        "#]],
    )
}

#[test]
fn infer_ops_index() {
    check_types(
        r#"
//- minicore: index
struct Bar;
struct Foo;

impl core::ops::Index<u32> for Bar {
    type Output = Foo;
}

fn test() {
    let a = Bar;
    let b = a[1u32];
    b;
} //^ Foo
"#,
    );
}

#[test]
fn infer_ops_index_field() {
    check_types(
        r#"
//- minicore: index
struct Bar;
struct Foo {
    field: u32;
}

impl core::ops::Index<u32> for Bar {
    type Output = Foo;
}

fn test() {
    let a = Bar;
    let b = a[1u32].field;
    b;
} //^ u32
"#,
    );
}

#[test]
fn infer_ops_index_field_autoderef() {
    check_types(
        r#"
//- minicore: index
struct Bar;
struct Foo {
    field: u32;
}

impl core::ops::Index<u32> for Bar {
    type Output = Foo;
}

fn test() {
    let a = Bar;
    let b = (&a[1u32]).field;
    b;
} //^ u32
"#,
    );
}

#[test]
fn infer_ops_index_int() {
    check_types(
        r#"
//- minicore: index
struct Bar;
struct Foo;

impl core::ops::Index<u32> for Bar {
    type Output = Foo;
}

struct Range;
impl core::ops::Index<Range> for Bar {
    type Output = Bar;
}

fn test() {
    let a = Bar;
    let b = a[1];
    b;
  //^ Foo
}
"#,
    );
}

#[test]
fn infer_ops_index_autoderef() {
    check_types(
        r#"
//- minicore: index, slice
fn test() {
    let a = &[1u32, 2, 3];
    let b = a[1];
    b;
} //^ u32
"#,
    );
}

#[test]
fn deref_trait() {
    check_types(
        r#"
//- minicore: deref
struct Arc<T: ?Sized>;
impl<T: ?Sized> core::ops::Deref for Arc<T> {
    type Target = T;
}

struct S;
impl S {
    fn foo(&self) -> u128 { 0 }
}

fn test(s: Arc<S>) {
    (*s, s.foo());
} //^^^^^^^^^^^^^ (S, u128)
"#,
    );
}

#[test]
fn deref_trait_with_inference_var() {
    check_types(
        r#"
//- minicore: deref
struct Arc<T: ?Sized>;
fn new_arc<T: ?Sized>() -> Arc<T> { Arc }
impl<T: ?Sized> core::ops::Deref for Arc<T> {
    type Target = T;
}

struct S;
fn foo(a: Arc<S>) {}

fn test() {
    let a = new_arc();
    let b = *a;
          //^^ S
    foo(a);
}
"#,
    );
}

#[test]
fn deref_trait_infinite_recursion() {
    check_types(
        r#"
//- minicore: deref
struct S;

impl core::ops::Deref for S {
    type Target = S;
}

fn test(s: S) {
    s.foo();
} //^^^^^^^ {unknown}
"#,
    );
}

#[test]
fn deref_trait_with_question_mark_size() {
    check_types(
        r#"
//- minicore: deref
struct Arc<T: ?Sized>;
impl<T: ?Sized> core::ops::Deref for Arc<T> {
    type Target = T;
}

struct S;
impl S {
    fn foo(&self) -> u128 { 0 }
}

fn test(s: Arc<S>) {
    (*s, s.foo());
} //^^^^^^^^^^^^^ (S, u128)
"#,
    );
}

#[test]
fn deref_trait_with_implicit_sized_requirement_on_inference_var() {
    check_types(
        r#"
//- minicore: deref
struct Foo<T>;
impl<T> core::ops::Deref for Foo<T> {
    type Target = ();
}
fn test() {
    let foo = Foo;
    *foo;
  //^^^^ ()
    let _: Foo<u8> = foo;
}
"#,
    )
}

#[test]
fn obligation_from_function_clause() {
    check_types(
        r#"
struct S;

trait Trait<T> {}
impl Trait<u32> for S {}

fn foo<T: Trait<U>, U>(t: T) -> U { loop {} }

fn test(s: S) {
    foo(s);
} //^^^^^^ u32
"#,
    );
}

#[test]
fn obligation_from_method_clause() {
    check_types(
        r#"
//- /main.rs
struct S;

trait Trait<T> {}
impl Trait<isize> for S {}

struct O;
impl O {
    fn foo<T: Trait<U>, U>(&self, t: T) -> U { loop {} }
}

fn test() {
    O.foo(S);
} //^^^^^^^^ isize
"#,
    );
}

#[test]
fn obligation_from_self_method_clause() {
    check_types(
        r#"
struct S;

trait Trait<T> {}
impl Trait<i64> for S {}

impl S {
    fn foo<U>(&self) -> U where Self: Trait<U> { loop {} }
}

fn test() {
    S.foo();
} //^^^^^^^ i64
"#,
    );
}

#[test]
fn obligation_from_impl_clause() {
    check_types(
        r#"
struct S;

trait Trait<T> {}
impl Trait<&str> for S {}

struct O<T>;
impl<U, T: Trait<U>> O<T> {
    fn foo(&self) -> U { loop {} }
}

fn test(o: O<S>) {
    o.foo();
} //^^^^^^^ &str
"#,
    );
}

#[test]
fn generic_param_env_1() {
    check_types(
        r#"
trait Clone {}
trait Trait { fn foo(self) -> u128; }
struct S;
impl Clone for S {}
impl<T> Trait for T where T: Clone {}
fn test<T: Clone>(t: T) { t.foo(); }
                        //^^^^^^^ u128
"#,
    );
}

#[test]
fn generic_param_env_1_not_met() {
    check_types(
        r#"
//- /main.rs
trait Clone {}
trait Trait { fn foo(self) -> u128; }
struct S;
impl Clone for S {}
impl<T> Trait for T where T: Clone {}
fn test<T>(t: T) { t.foo(); }
                 //^^^^^^^ {unknown}
"#,
    );
}

#[test]
fn generic_param_env_2() {
    check_types(
        r#"
trait Trait { fn foo(self) -> u128; }
struct S;
impl Trait for S {}
fn test<T: Trait>(t: T) { t.foo(); }
                        //^^^^^^^ u128
"#,
    );
}

#[test]
fn generic_param_env_2_not_met() {
    check_types(
        r#"
trait Trait { fn foo(self) -> u128; }
struct S;
impl Trait for S {}
fn test<T>(t: T) { t.foo(); }
                 //^^^^^^^ {unknown}
"#,
    );
}

#[test]
fn generic_param_env_deref() {
    check_types(
        r#"
//- minicore: deref
trait Trait {}
impl<T> core::ops::Deref for T where T: Trait {
    type Target = i128;
}
fn test<T: Trait>(t: T) { *t; }
                        //^^ i128
"#,
    );
}

#[test]
fn associated_type_placeholder() {
    // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out<T>` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types].
    check_types(
        r#"
pub trait ApplyL {
    type Out;
}

pub struct RefMutL<T>;

impl<T> ApplyL for RefMutL<T> {
    type Out = <T as ApplyL>::Out;
}

fn test<T: ApplyL>() {
    let y: <RefMutL<T> as ApplyL>::Out = no_matter;
    y;
} //^ ApplyL::Out<T>
"#,
    );
}

#[test]
fn associated_type_placeholder_2() {
    check_types(
        r#"
pub trait ApplyL {
    type Out;
}
fn foo<T: ApplyL>(t: T) -> <T as ApplyL>::Out;

fn test<T: ApplyL>(t: T) {
    let y = foo(t);
    y;
} //^ ApplyL::Out<T>
"#,
    );
}

#[test]
fn argument_impl_trait() {
    check_infer_with_mismatches(
        r#"
//- minicore: sized
trait Trait<T> {
    fn foo(&self) -> T;
    fn foo2(&self) -> i64;
}
fn bar(x: impl Trait<u16>) {}
struct S<T>(T);
impl<T> Trait<T> for S<T> {}

fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
    x;
    y;
    let z = S(1);
    bar(z);
    x.foo();
    y.foo();
    z.foo();
    x.foo2();
    y.foo2();
    z.foo2();
}"#,
        expect![[r#"
            29..33 'self': &Self
            54..58 'self': &Self
            77..78 'x': impl Trait<u16>
            97..99 '{}': ()
            154..155 'x': impl Trait<u64>
            174..175 'y': &impl Trait<u32>
            195..323 '{     ...2(); }': ()
            201..202 'x': impl Trait<u64>
            208..209 'y': &impl Trait<u32>
            219..220 'z': S<u16>
            223..224 'S': S<u16>(u16) -> S<u16>
            223..227 'S(1)': S<u16>
            225..226 '1': u16
            233..236 'bar': fn bar(S<u16>)
            233..239 'bar(z)': ()
            237..238 'z': S<u16>
            245..246 'x': impl Trait<u64>
            245..252 'x.foo()': u64
            258..259 'y': &impl Trait<u32>
            258..265 'y.foo()': u32
            271..272 'z': S<u16>
            271..278 'z.foo()': u16
            284..285 'x': impl Trait<u64>
            284..292 'x.foo2()': i64
            298..299 'y': &impl Trait<u32>
            298..306 'y.foo2()': i64
            312..313 'z': S<u16>
            312..320 'z.foo2()': i64
        "#]],
    );
}

#[test]
fn argument_impl_trait_type_args_1() {
    check_infer_with_mismatches(
        r#"
//- minicore: sized
trait Trait {}
trait Foo {
    // this function has an implicit Self param, an explicit type param,
    // and an implicit impl Trait param!
    fn bar<T>(x: impl Trait) -> T { loop {} }
}
fn foo<T>(x: impl Trait) -> T { loop {} }
struct S;
impl Trait for S {}
struct F;
impl Foo for F {}

fn test() {
    Foo::bar(S);
    <F as Foo>::bar(S);
    F::bar(S);
    Foo::bar::<u32>(S);
    <F as Foo>::bar::<u32>(S);

    foo(S);
    foo::<u32>(S);
    foo::<u32, i32>(S); // we should ignore the extraneous i32
}"#,
        expect![[r#"
            155..156 'x': impl Trait
            175..186 '{ loop {} }': T
            177..184 'loop {}': !
            182..184 '{}': ()
            199..200 'x': impl Trait
            219..230 '{ loop {} }': T
            221..228 'loop {}': !
            226..228 '{}': ()
            300..509 '{     ... i32 }': ()
            306..314 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown}
            306..317 'Foo::bar(S)': {unknown}
            315..316 'S': S
            323..338 '<F as Foo>::bar': fn bar<F, {unknown}>(S) -> {unknown}
            323..341 '<F as ...bar(S)': {unknown}
            339..340 'S': S
            347..353 'F::bar': fn bar<F, {unknown}>(S) -> {unknown}
            347..356 'F::bar(S)': {unknown}
            354..355 'S': S
            362..377 'Foo::bar::<u32>': fn bar<{unknown}, u32>(S) -> u32
            362..380 'Foo::b...32>(S)': u32
            378..379 'S': S
            386..408 '<F as ...:<u32>': fn bar<F, u32>(S) -> u32
            386..411 '<F as ...32>(S)': u32
            409..410 'S': S
            418..421 'foo': fn foo<{unknown}>(S) -> {unknown}
            418..424 'foo(S)': {unknown}
            422..423 'S': S
            430..440 'foo::<u32>': fn foo<u32>(S) -> u32
            430..443 'foo::<u32>(S)': u32
            441..442 'S': S
            449..464 'foo::<u32, i32>': fn foo<u32>(S) -> u32
            449..467 'foo::<...32>(S)': u32
            465..466 'S': S
        "#]],
    );
}

#[test]
fn argument_impl_trait_type_args_2() {
    check_infer_with_mismatches(
        r#"
//- minicore: sized
trait Trait {}
struct S;
impl Trait for S {}
struct F<T>;
impl<T> F<T> {
    fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} }
}

fn test() {
    F.foo(S);
    F::<u32>.foo(S);
    F::<u32>.foo::<i32>(S);
    F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored
}"#,
        expect![[r#"
            87..91 'self': F<T>
            93..94 'x': impl Trait
            118..129 '{ loop {} }': (T, U)
            120..127 'loop {}': !
            125..127 '{}': ()
            143..283 '{     ...ored }': ()
            149..150 'F': F<{unknown}>
            149..157 'F.foo(S)': ({unknown}, {unknown})
            155..156 'S': S
            163..171 'F::<u32>': F<u32>
            163..178 'F::<u32>.foo(S)': (u32, {unknown})
            176..177 'S': S
            184..192 'F::<u32>': F<u32>
            184..206 'F::<u3...32>(S)': (u32, i32)
            204..205 'S': S
            212..220 'F::<u32>': F<u32>
            212..239 'F::<u3...32>(S)': (u32, i32)
            237..238 'S': S
        "#]],
    );
}

#[test]
fn argument_impl_trait_to_fn_pointer() {
    check_infer_with_mismatches(
        r#"
//- minicore: sized
trait Trait {}
fn foo(x: impl Trait) { loop {} }
struct S;
impl Trait for S {}

fn test() {
    let f: fn(S) -> () = foo;
}"#,
        expect![[r#"
            22..23 'x': impl Trait
            37..48 '{ loop {} }': ()
            39..46 'loop {}': !
            44..46 '{}': ()
            90..123 '{     ...foo; }': ()
            100..101 'f': fn(S)
            117..120 'foo': fn foo(S)
        "#]],
    );
}

#[test]
fn impl_trait() {
    check_infer(
        r#"
//- minicore: sized
trait Trait<T> {
    fn foo(&self) -> T;
    fn foo2(&self) -> i64;
}
fn bar() -> impl Trait<u64> {}

fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
    x;
    y;
    let z = bar();
    x.foo();
    y.foo();
    z.foo();
    x.foo2();
    y.foo2();
    z.foo2();
}"#,
        expect![[r#"
            29..33 'self': &Self
            54..58 'self': &Self
            98..100 '{}': ()
            110..111 'x': impl Trait<u64>
            130..131 'y': &impl Trait<u64>
            151..268 '{     ...2(); }': ()
            157..158 'x': impl Trait<u64>
            164..165 'y': &impl Trait<u64>
            175..176 'z': impl Trait<u64>
            179..182 'bar': fn bar() -> impl Trait<u64>
            179..184 'bar()': impl Trait<u64>
            190..191 'x': impl Trait<u64>
            190..197 'x.foo()': u64
            203..204 'y': &impl Trait<u64>
            203..210 'y.foo()': u64
            216..217 'z': impl Trait<u64>
            216..223 'z.foo()': u64
            229..230 'x': impl Trait<u64>
            229..237 'x.foo2()': i64
            243..244 'y': &impl Trait<u64>
            243..251 'y.foo2()': i64
            257..258 'z': impl Trait<u64>
            257..265 'z.foo2()': i64
        "#]],
    );
}

#[test]
fn simple_return_pos_impl_trait() {
    cov_mark::check!(lower_rpit);
    check_infer(
        r#"
//- minicore: sized
trait Trait<T> {
    fn foo(&self) -> T;
}
fn bar() -> impl Trait<u64> { loop {} }

fn test() {
    let a = bar();
    a.foo();
}"#,
        expect![[r#"
            29..33 'self': &Self
            71..82 '{ loop {} }': !
            73..80 'loop {}': !
            78..80 '{}': ()
            94..129 '{     ...o(); }': ()
            104..105 'a': impl Trait<u64>
            108..111 'bar': fn bar() -> impl Trait<u64>
            108..113 'bar()': impl Trait<u64>
            119..120 'a': impl Trait<u64>
            119..126 'a.foo()': u64
        "#]],
    );
}

#[test]
fn more_return_pos_impl_trait() {
    check_infer(
        r#"
//- minicore: sized
trait Iterator {
    type Item;
    fn next(&mut self) -> Self::Item;
}
trait Trait<T> {
    fn foo(&self) -> T;
}
fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} }
fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} }

fn test() {
    let (a, b) = bar();
    a.next().foo();
    b.foo();
    let (c, d) = baz(1u128);
    c.next().foo();
    d.foo();
}"#,
        expect![[r#"
            49..53 'self': &mut Self
            101..105 'self': &Self
            184..195 '{ loop {} }': ({unknown}, {unknown})
            186..193 'loop {}': !
            191..193 '{}': ()
            206..207 't': T
            268..279 '{ loop {} }': ({unknown}, {unknown})
            270..277 'loop {}': !
            275..277 '{}': ()
            291..413 '{     ...o(); }': ()
            301..307 '(a, b)': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>)
            302..303 'a': impl Iterator<Item = impl Trait<u32>>
            305..306 'b': impl Trait<u64>
            310..313 'bar': fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>)
            310..315 'bar()': (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>)
            321..322 'a': impl Iterator<Item = impl Trait<u32>>
            321..329 'a.next()': impl Trait<u32>
            321..335 'a.next().foo()': u32
            341..342 'b': impl Trait<u64>
            341..348 'b.foo()': u64
            358..364 '(c, d)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
            359..360 'c': impl Iterator<Item = impl Trait<u128>>
            362..363 'd': impl Trait<u128>
            367..370 'baz': fn baz<u128>(u128) -> (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
            367..377 'baz(1u128)': (impl Iterator<Item = impl Trait<u128>>, impl Trait<u128>)
            371..376 '1u128': u128
            383..384 'c': impl Iterator<Item = impl Trait<u128>>
            383..391 'c.next()': impl Trait<u128>
            383..397 'c.next().foo()': u128
            403..404 'd': impl Trait<u128>
            403..410 'd.foo()': u128
        "#]],
    );
}

#[test]
fn infer_from_return_pos_impl_trait() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn, sized
trait Trait<T> {}
struct Bar<T>(T);
impl<T> Trait<T> for Bar<T> {}
fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
    (|input, t| {}, Bar(C))
}
"#,
        expect![[r#"
            134..165 '{     ...(C)) }': (impl Fn(&str, T), Bar<u8>)
            140..163 '(|inpu...ar(C))': (impl Fn(&str, T), Bar<u8>)
            141..154 '|input, t| {}': impl Fn(&str, T)
            142..147 'input': &str
            149..150 't': T
            152..154 '{}': ()
            156..159 'Bar': Bar<u8>(u8) -> Bar<u8>
            156..162 'Bar(C)': Bar<u8>
            160..161 'C': u8
        "#]],
    );
}

#[test]
fn return_pos_impl_trait_in_projection() {
    // Note that the unused type param `X` is significant; see #13307.
    check_no_mismatches(
        r#"
//- minicore: sized
trait Future { type Output; }
impl Future for () { type Output = i32; }
type Foo<F> = (<F as Future>::Output, F);
fn foo<X>() -> Foo<impl Future<Output = ()>> {
    (0, ())
}
"#,
    )
}

#[test]
fn dyn_trait() {
    check_infer(
        r#"
//- minicore: sized
trait Trait<T> {
    fn foo(&self) -> T;
    fn foo2(&self) -> i64;
}
fn bar() -> dyn Trait<u64> {}

fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
    x;
    y;
    let z = bar();
    x.foo();
    y.foo();
    z.foo();
    x.foo2();
    y.foo2();
    z.foo2();
}"#,
        expect![[r#"
            29..33 'self': &Self
            54..58 'self': &Self
            97..99 '{}': dyn Trait<u64>
            109..110 'x': dyn Trait<u64>
            128..129 'y': &dyn Trait<u64>
            148..265 '{     ...2(); }': ()
            154..155 'x': dyn Trait<u64>
            161..162 'y': &dyn Trait<u64>
            172..173 'z': dyn Trait<u64>
            176..179 'bar': fn bar() -> dyn Trait<u64>
            176..181 'bar()': dyn Trait<u64>
            187..188 'x': dyn Trait<u64>
            187..194 'x.foo()': u64
            200..201 'y': &dyn Trait<u64>
            200..207 'y.foo()': u64
            213..214 'z': dyn Trait<u64>
            213..220 'z.foo()': u64
            226..227 'x': dyn Trait<u64>
            226..234 'x.foo2()': i64
            240..241 'y': &dyn Trait<u64>
            240..248 'y.foo2()': i64
            254..255 'z': dyn Trait<u64>
            254..262 'z.foo2()': i64
        "#]],
    );
}

#[test]
fn dyn_trait_in_impl() {
    check_infer(
        r#"
//- minicore: sized
trait Trait<T, U> {
    fn foo(&self) -> (T, U);
}
struct S<T, U> {}
impl<T, U> S<T, U> {
    fn bar(&self) -> &dyn Trait<T, U> { loop {} }
}
trait Trait2<T, U> {
    fn baz(&self) -> (T, U);
}
impl<T, U> Trait2<T, U> for dyn Trait<T, U> { }

fn test(s: S<u32, i32>) {
    s.bar().baz();
}"#,
        expect![[r#"
            32..36 'self': &Self
            102..106 'self': &S<T, U>
            128..139 '{ loop {} }': &dyn Trait<T, U>
            130..137 'loop {}': !
            135..137 '{}': ()
            175..179 'self': &Self
            251..252 's': S<u32, i32>
            267..289 '{     ...z(); }': ()
            273..274 's': S<u32, i32>
            273..280 's.bar()': &dyn Trait<u32, i32>
            273..286 's.bar().baz()': (u32, i32)
        "#]],
    );
}

#[test]
fn dyn_trait_bare() {
    check_infer(
        r#"
//- minicore: sized
trait Trait {
    fn foo(&self) -> u64;
}
fn bar() -> Trait {}

fn test(x: Trait, y: &Trait) -> u64 {
    x;
    y;
    let z = bar();
    x.foo();
    y.foo();
    z.foo();
}"#,
        expect![[r#"
            26..30 'self': &Self
            60..62 '{}': dyn Trait
            72..73 'x': dyn Trait
            82..83 'y': &dyn Trait
            100..175 '{     ...o(); }': u64
            106..107 'x': dyn Trait
            113..114 'y': &dyn Trait
            124..125 'z': dyn Trait
            128..131 'bar': fn bar() -> dyn Trait
            128..133 'bar()': dyn Trait
            139..140 'x': dyn Trait
            139..146 'x.foo()': u64
            152..153 'y': &dyn Trait
            152..159 'y.foo()': u64
            165..166 'z': dyn Trait
            165..172 'z.foo()': u64
        "#]],
    );

    check_infer_with_mismatches(
        r#"
//- minicore: fn, coerce_unsized
struct S;
impl S {
    fn foo(&self) {}
}
fn f(_: &Fn(S)) {}
fn main() {
    f(&|number| number.foo());
}
        "#,
        expect![[r#"
            31..35 'self': &S
            37..39 '{}': ()
            47..48 '_': &dyn Fn(S)
            58..60 '{}': ()
            71..105 '{     ...()); }': ()
            77..78 'f': fn f(&dyn Fn(S))
            77..102 'f(&|nu...foo())': ()
            79..101 '&|numb....foo()': &impl Fn(S)
            80..101 '|numbe....foo()': impl Fn(S)
            81..87 'number': S
            89..95 'number': S
            89..101 'number.foo()': ()
        "#]],
    )
}

#[test]
fn weird_bounds() {
    check_infer(
        r#"
//- minicore: sized
trait Trait {}
fn test(
    a: impl Trait + 'lifetime,
    b: impl 'lifetime,
    c: impl (Trait),
    d: impl ('lifetime),
    e: impl ?Sized,
    f: impl Trait + ?Sized
) {}
"#,
        expect![[r#"
            28..29 'a': impl Trait
            59..60 'b': impl Sized
            82..83 'c': impl Trait
            103..104 'd': impl Sized
            128..129 'e': impl ?Sized
            148..149 'f': impl Trait + ?Sized
            173..175 '{}': ()
        "#]],
    );
}

#[test]
fn error_bound_chalk() {
    check_types(
        r#"
trait Trait {
    fn foo(&self) -> u32 { 0 }
}

fn test(x: (impl Trait + UnknownTrait)) {
    x.foo();
} //^^^^^^^ u32
"#,
    );
}

#[test]
fn assoc_type_bindings() {
    check_infer(
        r#"
//- minicore: sized
trait Trait {
    type Type;
}

fn get<T: Trait>(t: T) -> <T as Trait>::Type {}
fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
fn set<T: Trait<Type = u64>>(t: T) -> T {t}

struct S<T>;
impl<T> Trait for S<T> { type Type = T; }

fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
    get(x);
    get2(x);
    get(y);
    get2(y);
    get(set(S));
    get2(set(S));
    get2(S::<str>);
}"#,
        expect![[r#"
            49..50 't': T
            77..79 '{}': Trait::Type<T>
            111..112 't': T
            122..124 '{}': U
            154..155 't': T
            165..168 '{t}': T
            166..167 't': T
            256..257 'x': T
            262..263 'y': impl Trait<Type = i64>
            289..397 '{     ...r>); }': ()
            295..298 'get': fn get<T>(T) -> <T as Trait>::Type
            295..301 'get(x)': u32
            299..300 'x': T
            307..311 'get2': fn get2<u32, T>(T) -> u32
            307..314 'get2(x)': u32
            312..313 'x': T
            320..323 'get': fn get<impl Trait<Type = i64>>(impl Trait<Type = i64>) -> <impl Trait<Type = i64> as Trait>::Type
            320..326 'get(y)': i64
            324..325 'y': impl Trait<Type = i64>
            332..336 'get2': fn get2<i64, impl Trait<Type = i64>>(impl Trait<Type = i64>) -> i64
            332..339 'get2(y)': i64
            337..338 'y': impl Trait<Type = i64>
            345..348 'get': fn get<S<u64>>(S<u64>) -> <S<u64> as Trait>::Type
            345..356 'get(set(S))': u64
            349..352 'set': fn set<S<u64>>(S<u64>) -> S<u64>
            349..355 'set(S)': S<u64>
            353..354 'S': S<u64>
            362..366 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64
            362..374 'get2(set(S))': u64
            367..370 'set': fn set<S<u64>>(S<u64>) -> S<u64>
            367..373 'set(S)': S<u64>
            371..372 'S': S<u64>
            380..384 'get2': fn get2<str, S<str>>(S<str>) -> str
            380..394 'get2(S::<str>)': str
            385..393 'S::<str>': S<str>
        "#]],
    );
}

#[test]
fn impl_trait_assoc_binding_projection_bug() {
    check_types(
        r#"
//- minicore: iterator
pub trait Language {
    type Kind;
}
pub enum RustLanguage {}
impl Language for RustLanguage {
    type Kind = SyntaxKind;
}
struct SyntaxNode<L> {}
fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {}

trait Clone {
    fn clone(&self) -> Self;
}

fn api_walkthrough() {
    for node in foo() {
        node.clone();
    } //^^^^^^^^^^^^ {unknown}
}
"#,
    );
}

#[test]
fn projection_eq_within_chalk() {
    check_infer(
        r#"
trait Trait1 {
    type Type;
}
trait Trait2<T> {
    fn foo(self) -> T;
}
impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {}

fn test<T: Trait1<Type = u32>>(x: T) {
    x.foo();
}"#,
        expect![[r#"
            61..65 'self': Self
            163..164 'x': T
            169..185 '{     ...o(); }': ()
            175..176 'x': T
            175..182 'x.foo()': u32
        "#]],
    );
}

#[test]
fn where_clause_trait_in_scope_for_method_resolution() {
    check_types(
        r#"
mod foo {
    pub trait Trait {
        fn foo(&self) -> u32 { 0 }
    }
}

fn test<T: foo::Trait>(x: T) {
    x.foo();
} //^^^^^^^ u32
"#,
    );
}

#[test]
fn super_trait_method_resolution() {
    check_infer(
        r#"
mod foo {
    pub trait SuperTrait {
        fn foo(&self) -> u32 {}
    }
}
trait Trait1: foo::SuperTrait {}
trait Trait2 where Self: foo::SuperTrait {}

fn test<T: Trait1, U: Trait2>(x: T, y: U) {
    x.foo();
    y.foo();
}"#,
        expect![[r#"
            53..57 'self': &Self
            66..68 '{}': u32
            185..186 'x': T
            191..192 'y': U
            197..226 '{     ...o(); }': ()
            203..204 'x': T
            203..210 'x.foo()': u32
            216..217 'y': U
            216..223 'y.foo()': u32
        "#]],
    );
}

#[test]
fn super_trait_impl_trait_method_resolution() {
    check_infer(
        r#"
//- minicore: sized
mod foo {
    pub trait SuperTrait {
        fn foo(&self) -> u32 {}
    }
}
trait Trait1: foo::SuperTrait {}

fn test(x: &impl Trait1) {
    x.foo();
}"#,
        expect![[r#"
            53..57 'self': &Self
            66..68 '{}': u32
            119..120 'x': &impl Trait1
            136..152 '{     ...o(); }': ()
            142..143 'x': &impl Trait1
            142..149 'x.foo()': u32
        "#]],
    );
}

#[test]
fn super_trait_cycle() {
    // This just needs to not crash
    check_infer(
        r#"
        trait A: B {}
        trait B: A {}

        fn test<T: A>(x: T) {
            x.foo();
        }
        "#,
        expect![[r#"
            43..44 'x': T
            49..65 '{     ...o(); }': ()
            55..56 'x': T
            55..62 'x.foo()': {unknown}
        "#]],
    );
}

#[test]
fn super_trait_assoc_type_bounds() {
    check_infer(
        r#"
trait SuperTrait { type Type; }
trait Trait where Self: SuperTrait {}

fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
fn set<T: Trait<Type = u64>>(t: T) -> T {t}

struct S<T>;
impl<T> SuperTrait for S<T> { type Type = T; }
impl<T> Trait for S<T> {}

fn test() {
    get2(set(S));
}"#,
        expect![[r#"
            102..103 't': T
            113..115 '{}': U
            145..146 't': T
            156..159 '{t}': T
            157..158 't': T
            258..279 '{     ...S)); }': ()
            264..268 'get2': fn get2<u64, S<u64>>(S<u64>) -> u64
            264..276 'get2(set(S))': u64
            269..272 'set': fn set<S<u64>>(S<u64>) -> S<u64>
            269..275 'set(S)': S<u64>
            273..274 'S': S<u64>
        "#]],
    );
}

#[test]
fn fn_trait() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn

fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
    f.call_once((1, 2));
}"#,
        expect![[r#"
            38..39 'f': F
            44..72 '{     ...2)); }': ()
            50..51 'f': F
            50..69 'f.call...1, 2))': u128
            62..68 '(1, 2)': (u32, u64)
            63..64 '1': u32
            66..67 '2': u64
        "#]],
    );
}

#[test]
fn fn_ptr_and_item() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn

trait Foo<T> {
    fn foo(&self) -> T;
}

struct Bar<T>(T);

impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
    fn foo(&self) -> (A1, R) { loop {} }
}

enum Opt<T> { None, Some(T) }
impl<T> Opt<T> {
    fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> { loop {} }
}

fn test() {
    let bar: Bar<fn(u8) -> u32>;
    bar.foo();

    let opt: Opt<u8>;
    let f: fn(u8) -> u32;
    opt.map(f);
}"#,
        expect![[r#"
            28..32 'self': &Self
            132..136 'self': &Bar<F>
            149..160 '{ loop {} }': (A1, R)
            151..158 'loop {}': !
            156..158 '{}': ()
            244..248 'self': Opt<T>
            250..251 'f': F
            266..277 '{ loop {} }': Opt<U>
            268..275 'loop {}': !
            273..275 '{}': ()
            291..407 '{     ...(f); }': ()
            301..304 'bar': Bar<fn(u8) -> u32>
            330..333 'bar': Bar<fn(u8) -> u32>
            330..339 'bar.foo()': (u8, u32)
            350..353 'opt': Opt<u8>
            372..373 'f': fn(u8) -> u32
            394..397 'opt': Opt<u8>
            394..404 'opt.map(f)': Opt<u32>
            402..403 'f': fn(u8) -> u32
        "#]],
    );
}

#[test]
fn fn_trait_deref_with_ty_default() {
    check_infer(
        r#"
//- minicore: deref, fn
struct Foo;

impl Foo {
    fn foo(&self) -> usize {}
}

struct Lazy<T, F = fn() -> T>(F);

impl<T, F> Lazy<T, F> {
    pub fn new(f: F) -> Lazy<T, F> {}
}

impl<T, F: FnOnce() -> T> core::ops::Deref for Lazy<T, F> {
    type Target = T;
}

fn test() {
    let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
    let r1 = lazy1.foo();

    fn make_foo_fn() -> Foo {}
    let make_foo_fn_ptr: fn() -> Foo = make_foo_fn;
    let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr);
    let r2 = lazy2.foo();
}"#,
        expect![[r#"
            36..40 'self': &Foo
            51..53 '{}': usize
            131..132 'f': F
            151..153 '{}': Lazy<T, F>
            251..497 '{     ...o(); }': ()
            261..266 'lazy1': Lazy<Foo, impl Fn() -> Foo>
            283..292 'Lazy::new': fn new<Foo, impl Fn() -> Foo>(impl Fn() -> Foo) -> Lazy<Foo, impl Fn() -> Foo>
            283..300 'Lazy::...| Foo)': Lazy<Foo, impl Fn() -> Foo>
            293..299 '|| Foo': impl Fn() -> Foo
            296..299 'Foo': Foo
            310..312 'r1': usize
            315..320 'lazy1': Lazy<Foo, impl Fn() -> Foo>
            315..326 'lazy1.foo()': usize
            368..383 'make_foo_fn_ptr': fn() -> Foo
            399..410 'make_foo_fn': fn make_foo_fn() -> Foo
            420..425 'lazy2': Lazy<Foo, fn() -> Foo>
            442..451 'Lazy::new': fn new<Foo, fn() -> Foo>(fn() -> Foo) -> Lazy<Foo, fn() -> Foo>
            442..468 'Lazy::...n_ptr)': Lazy<Foo, fn() -> Foo>
            452..467 'make_foo_fn_ptr': fn() -> Foo
            478..480 'r2': usize
            483..488 'lazy2': Lazy<Foo, fn() -> Foo>
            483..494 'lazy2.foo()': usize
            357..359 '{}': Foo
        "#]],
    );
}

#[test]
fn closure_1() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn
enum Option<T> { Some(T), None }
impl<T> Option<T> {
    fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} }
}

fn test() {
    let x = Option::Some(1u32);
    x.map(|v| v + 1);
    x.map(|_v| 1u64);
    let y: Option<i64> = x.map(|_v| 1);
}"#,
        expect![[r#"
            86..90 'self': Option<T>
            92..93 'f': F
            111..122 '{ loop {} }': Option<U>
            113..120 'loop {}': !
            118..120 '{}': ()
            136..255 '{     ... 1); }': ()
            146..147 'x': Option<u32>
            150..162 'Option::Some': Some<u32>(u32) -> Option<u32>
            150..168 'Option...(1u32)': Option<u32>
            163..167 '1u32': u32
            174..175 'x': Option<u32>
            174..190 'x.map(...v + 1)': Option<u32>
            180..189 '|v| v + 1': impl Fn(u32) -> u32
            181..182 'v': u32
            184..185 'v': u32
            184..189 'v + 1': u32
            188..189 '1': u32
            196..197 'x': Option<u32>
            196..212 'x.map(... 1u64)': Option<u64>
            202..211 '|_v| 1u64': impl Fn(u32) -> u64
            203..205 '_v': u32
            207..211 '1u64': u64
            222..223 'y': Option<i64>
            239..240 'x': Option<u32>
            239..252 'x.map(|_v| 1)': Option<i64>
            245..251 '|_v| 1': impl Fn(u32) -> i64
            246..248 '_v': u32
            250..251 '1': i64
        "#]],
    );
}

#[test]
fn closure_2() {
    check_types(
        r#"
//- minicore: add, fn

impl core::ops::Add for u64 {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {0}
}

impl core::ops::Add for u128 {
    type Output = Self;
    fn add(self, rhs: u128) -> Self::Output {0}
}

fn test<F: FnOnce(u32) -> u64>(f: F) {
    f(1);
  //  ^ u32
  //^^^^ u64
    let g = |v| v + 1;
              //^^^^^ u64
          //^^^^^^^^^ impl Fn(u64) -> u64
    g(1u64);
  //^^^^^^^ u64
    let h = |v| 1u128 + v;
          //^^^^^^^^^^^^^ impl Fn(u128) -> u128
}"#,
    );
}

#[test]
fn closure_as_argument_inference_order() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn
fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U { loop {} }
fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U { loop {} }

struct S;
impl S {
    fn method(self) -> u64;

    fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U { loop {} }
    fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U { loop {} }
}

fn test() {
    let x1 = foo1(S, |s| s.method());
    let x2 = foo2(|s| s.method(), S);
    let x3 = S.foo1(S, |s| s.method());
    let x4 = S.foo2(|s| s.method(), S);
}"#,
        expect![[r#"
            33..34 'x': T
            39..40 'f': F
            50..61 '{ loop {} }': U
            52..59 'loop {}': !
            57..59 '{}': ()
            95..96 'f': F
            101..102 'x': T
            112..123 '{ loop {} }': U
            114..121 'loop {}': !
            119..121 '{}': ()
            158..162 'self': S
            210..214 'self': S
            216..217 'x': T
            222..223 'f': F
            233..244 '{ loop {} }': U
            235..242 'loop {}': !
            240..242 '{}': ()
            282..286 'self': S
            288..289 'f': F
            294..295 'x': T
            305..316 '{ loop {} }': U
            307..314 'loop {}': !
            312..314 '{}': ()
            330..489 '{     ... S); }': ()
            340..342 'x1': u64
            345..349 'foo1': fn foo1<S, u64, impl Fn(S) -> u64>(S, impl Fn(S) -> u64) -> u64
            345..368 'foo1(S...hod())': u64
            350..351 'S': S
            353..367 '|s| s.method()': impl Fn(S) -> u64
            354..355 's': S
            357..358 's': S
            357..367 's.method()': u64
            378..380 'x2': u64
            383..387 'foo2': fn foo2<S, u64, impl Fn(S) -> u64>(impl Fn(S) -> u64, S) -> u64
            383..406 'foo2(|...(), S)': u64
            388..402 '|s| s.method()': impl Fn(S) -> u64
            389..390 's': S
            392..393 's': S
            392..402 's.method()': u64
            404..405 'S': S
            416..418 'x3': u64
            421..422 'S': S
            421..446 'S.foo1...hod())': u64
            428..429 'S': S
            431..445 '|s| s.method()': impl Fn(S) -> u64
            432..433 's': S
            435..436 's': S
            435..445 's.method()': u64
            456..458 'x4': u64
            461..462 'S': S
            461..486 'S.foo2...(), S)': u64
            468..482 '|s| s.method()': impl Fn(S) -> u64
            469..470 's': S
            472..473 's': S
            472..482 's.method()': u64
            484..485 'S': S
        "#]],
    );
}

#[test]
fn fn_item_fn_trait() {
    check_types(
        r#"
//- minicore: fn
struct S;

fn foo() -> S { S }

fn takes_closure<U, F: FnOnce() -> U>(f: F) -> U { f() }

fn test() {
    takes_closure(foo);
} //^^^^^^^^^^^^^^^^^^ S
"#,
    );
}

#[test]
fn unselected_projection_in_trait_env_1() {
    check_types(
        r#"
//- /main.rs
trait Trait {
    type Item;
}

trait Trait2 {
    fn foo(&self) -> u32;
}

fn test<T: Trait>() where T::Item: Trait2 {
    let x: T::Item = no_matter;
    x.foo();
} //^^^^^^^ u32
"#,
    );
}

#[test]
fn unselected_projection_in_trait_env_2() {
    check_types(
        r#"
trait Trait<T> {
    type Item;
}

trait Trait2 {
    fn foo(&self) -> u32;
}

fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
    let x: T::Item = no_matter;
    x.foo();
} //^^^^^^^ u32
"#,
    );
}

#[test]
fn unselected_projection_on_impl_self() {
    check_infer(
        r#"
//- /main.rs
trait Trait {
    type Item;

    fn f(&self, x: Self::Item);
}

struct S;

impl Trait for S {
    type Item = u32;
    fn f(&self, x: Self::Item) { let y = x; }
}

struct S2;

impl Trait for S2 {
    type Item = i32;
    fn f(&self, x: <Self>::Item) { let y = x; }
}"#,
        expect![[r#"
            40..44 'self': &Self
            46..47 'x': Trait::Item<Self>
            126..130 'self': &S
            132..133 'x': u32
            147..161 '{ let y = x; }': ()
            153..154 'y': u32
            157..158 'x': u32
            228..232 'self': &S2
            234..235 'x': i32
            251..265 '{ let y = x; }': ()
            257..258 'y': i32
            261..262 'x': i32
        "#]],
    );
}

#[test]
fn unselected_projection_on_trait_self() {
    check_types(
        r#"
trait Trait {
    type Item;

    fn f(&self) -> Self::Item { loop {} }
}

struct S;
impl Trait for S {
    type Item = u32;
}

fn test() {
    S.f();
} //^^^^^ u32
"#,
    );
}

#[test]
fn unselected_projection_chalk_fold() {
    check_types(
        r#"
trait Interner {}
trait Fold<I: Interner, TI = I> {
    type Result;
}

struct Ty<I: Interner> {}
impl<I: Interner, TI: Interner> Fold<I, TI> for Ty<I> {
    type Result = Ty<TI>;
}

fn fold<I: Interner, T>(interner: &I, t: T) -> T::Result
where
    T: Fold<I, I>,
{
    loop {}
}

fn foo<I: Interner>(interner: &I, t: Ty<I>) {
    fold(interner, t);
} //^^^^^^^^^^^^^^^^^ Ty<I>
"#,
    );
}

#[test]
fn trait_impl_self_ty() {
    check_types(
        r#"
trait Trait<T> {
   fn foo(&self);
}

struct S;

impl Trait<Self> for S {}

fn test() {
    S.foo();
} //^^^^^^^ ()
"#,
    );
}

#[test]
fn trait_impl_self_ty_cycle() {
    check_types(
        r#"
trait Trait {
   fn foo(&self);
}

struct S<T>;

impl Trait for S<Self> {}

fn test() {
    S.foo();
} //^^^^^^^ {unknown}
"#,
    );
}

#[test]
fn unselected_projection_in_trait_env_cycle_1() {
    // This is not a cycle, because the `T: Trait2<T::Item>` bound depends only on the `T: Trait`
    // bound, not on itself (since only `Trait` can define `Item`).
    check_types(
        r#"
trait Trait {
    type Item;
}

trait Trait2<T> {}

fn test<T: Trait>() where T: Trait2<T::Item> {
    let x: T::Item = no_matter;
}                  //^^^^^^^^^ Trait::Item<T>
"#,
    );
}

#[test]
fn unselected_projection_in_trait_env_cycle_2() {
    // this is a legitimate cycle
    check_types(
        r#"
//- /main.rs
trait Trait<T> {
    type Item;
}

fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
    let x: T::Item = no_matter;
}                  //^^^^^^^^^ {unknown}
"#,
    );
}

#[test]
fn unselected_projection_in_trait_env_cycle_3() {
    // this is a cycle for rustc; we currently accept it
    check_types(
        r#"
//- /main.rs
trait Trait {
    type Item;
    type OtherItem;
}

fn test<T>() where T: Trait<OtherItem = T::Item> {
    let x: T::Item = no_matter;
}                  //^^^^^^^^^ Trait::Item<T>
"#,
    );
}

#[test]
fn unselected_projection_in_trait_env_no_cycle() {
    // this is not a cycle
    check_types(
        r#"
//- minicore: index
use core::ops::Index;

type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;

pub trait UnificationStoreBase: Index<Output = Key<Self>> {
    type Key;

    fn len(&self) -> usize;
}

pub trait UnificationStoreMut: UnificationStoreBase {
    fn push(&mut self, value: Self::Key);
}

fn test<T>(t: T) where T: UnificationStoreMut {
    let x;
    t.push(x);
    let y: Key<T>;
    (x, y);
} //^^^^^^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>)
"#,
    );
}

#[test]
fn inline_assoc_type_bounds_1() {
    check_types(
        r#"
trait Iterator {
    type Item;
}
trait OtherTrait<T> {
    fn foo(&self) -> T;
}

// workaround for Chalk assoc type normalization problems
pub struct S<T>;
impl<T: Iterator> Iterator for S<T> {
    type Item = <T as Iterator>::Item;
}

fn test<I: Iterator<Item: OtherTrait<u32>>>() {
    let x: <S<I> as Iterator>::Item;
    x.foo();
} //^^^^^^^ u32
"#,
    );
}

#[test]
fn inline_assoc_type_bounds_2() {
    check_types(
        r#"
trait Iterator {
    type Item;
}

fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
    let x: <<I as Iterator>::Item as Iterator>::Item;
    x;
} //^ u32
"#,
    );
}

#[test]
fn proc_macro_server_types() {
    check_infer(
        r#"
macro_rules! with_api {
    ($S:ident, $self:ident, $m:ident) => {
        $m! {
            TokenStream {
                fn new() -> $S::TokenStream;
            },
            Group {
            },
        }
    };
}
macro_rules! associated_item {
    (type TokenStream) =>
        (type TokenStream: 'static;);
    (type Group) =>
        (type Group: 'static;);
    ($($item:tt)*) => ($($item)*;)
}
macro_rules! declare_server_traits {
    ($($name:ident {
        $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
    }),* $(,)?) => {
        pub trait Types {
            $(associated_item!(type $name);)*
        }

        $(pub trait $name: Types {
            $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
        })*

        pub trait Server: Types $(+ $name)* {}
        impl<S: Types $(+ $name)*> Server for S {}
    }
}

with_api!(Self, self_, declare_server_traits);
struct G {}
struct T {}
struct RustAnalyzer;
impl Types for RustAnalyzer {
    type TokenStream = T;
    type Group = G;
}

fn make<T>() -> T { loop {} }
impl TokenStream for RustAnalyzer {
    fn new() -> Self::TokenStream {
        let group: Self::Group = make();
        make()
    }
}"#,
        expect![[r#"
            1075..1086 '{ loop {} }': T
            1077..1084 'loop {}': !
            1082..1084 '{}': ()
            1157..1220 '{     ...     }': T
            1171..1176 'group': G
            1192..1196 'make': fn make<G>() -> G
            1192..1198 'make()': G
            1208..1212 'make': fn make<T>() -> T
            1208..1214 'make()': T
        "#]],
    );
}

#[test]
fn unify_impl_trait() {
    check_infer_with_mismatches(
        r#"
//- minicore: sized
trait Trait<T> {}

fn foo(x: impl Trait<u32>) { loop {} }
fn bar<T>(x: impl Trait<T>) -> T { loop {} }

struct S<T>(T);
impl<T> Trait<T> for S<T> {}

fn default<T>() -> T { loop {} }

fn test() -> impl Trait<i32> {
    let s1 = S(default());
    foo(s1);
    let x: i32 = bar(S(default()));
    S(default())
}"#,
        expect![[r#"
            26..27 'x': impl Trait<u32>
            46..57 '{ loop {} }': ()
            48..55 'loop {}': !
            53..55 '{}': ()
            68..69 'x': impl Trait<T>
            91..102 '{ loop {} }': T
            93..100 'loop {}': !
            98..100 '{}': ()
            171..182 '{ loop {} }': T
            173..180 'loop {}': !
            178..180 '{}': ()
            213..309 '{     ...t()) }': S<i32>
            223..225 's1': S<u32>
            228..229 'S': S<u32>(u32) -> S<u32>
            228..240 'S(default())': S<u32>
            230..237 'default': fn default<u32>() -> u32
            230..239 'default()': u32
            246..249 'foo': fn foo(S<u32>)
            246..253 'foo(s1)': ()
            250..252 's1': S<u32>
            263..264 'x': i32
            272..275 'bar': fn bar<i32>(S<i32>) -> i32
            272..289 'bar(S(...lt()))': i32
            276..277 'S': S<i32>(i32) -> S<i32>
            276..288 'S(default())': S<i32>
            278..285 'default': fn default<i32>() -> i32
            278..287 'default()': i32
            295..296 'S': S<i32>(i32) -> S<i32>
            295..307 'S(default())': S<i32>
            297..304 'default': fn default<i32>() -> i32
            297..306 'default()': i32
        "#]],
    );
}

#[test]
fn assoc_types_from_bounds() {
    check_infer(
        r#"
//- minicore: fn
trait T {
    type O;
}

impl T for () {
    type O = ();
}

fn f<X, F>(_v: F)
where
    X: T,
    F: FnOnce(&X::O),
{ }

fn main() {
    f::<(), _>(|z| { z; });
}"#,
        expect![[r#"
            72..74 '_v': F
            117..120 '{ }': ()
            132..163 '{     ... }); }': ()
            138..148 'f::<(), _>': fn f<(), impl Fn(&())>(impl Fn(&()))
            138..160 'f::<()... z; })': ()
            149..159 '|z| { z; }': impl Fn(&())
            150..151 'z': &()
            153..159 '{ z; }': ()
            155..156 'z': &()
        "#]],
    );
}

#[test]
fn associated_type_bound() {
    check_types(
        r#"
pub trait Trait {
    type Item: OtherTrait<u32>;
}
pub trait OtherTrait<T> {
    fn foo(&self) -> T;
}

// this is just a workaround for chalk#234
pub struct S<T>;
impl<T: Trait> Trait for S<T> {
    type Item = <T as Trait>::Item;
}

fn test<T: Trait>() {
    let y: <S<T> as Trait>::Item = no_matter;
    y.foo();
} //^^^^^^^ u32
"#,
    );
}

#[test]
fn associated_type_in_type_bound() {
    check_types(
        r#"
//- minicore: deref
fn fb(f: Foo<&u8>) {
    f.foobar();
  //^^^^^^^^^^ u8
}
trait Bar {
    fn bar(&self) -> u8;
}
impl Bar for u8 {
    fn bar(&self) -> u8 { *self }
}

struct Foo<F> {
    foo: F,
}
impl<F: core::ops::Deref<Target = impl Bar>> Foo<F> {
    fn foobar(&self) -> u8 {
        self.foo.deref().bar()
    }
}
"#,
    )
}

#[test]
fn dyn_trait_through_chalk() {
    check_types(
        r#"
//- minicore: deref
struct Box<T: ?Sized> {}
impl<T: ?Sized> core::ops::Deref for Box<T> {
    type Target = T;
}
trait Trait {
    fn foo(&self);
}

fn test(x: Box<dyn Trait>) {
    x.foo();
} //^^^^^^^ ()
"#,
    );
}

#[test]
fn string_to_owned() {
    check_types(
        r#"
struct String {}
pub trait ToOwned {
    type Owned;
    fn to_owned(&self) -> Self::Owned;
}
impl ToOwned for str {
    type Owned = String;
}
fn test() {
    "foo".to_owned();
} //^^^^^^^^^^^^^^^^ String
"#,
    );
}

#[test]
fn iterator_chain() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn, option
pub trait Iterator {
    type Item;

    fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
    where
        F: FnMut(Self::Item) -> Option<B>,
    { loop {} }

    fn for_each<F>(self, f: F)
    where
        F: FnMut(Self::Item),
    { loop {} }
}

pub trait IntoIterator {
    type Item;
    type IntoIter: Iterator<Item = Self::Item>;
    fn into_iter(self) -> Self::IntoIter;
}

pub struct FilterMap<I, F> { }
impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
where
    F: FnMut(I::Item) -> Option<B>,
{
    type Item = B;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator> IntoIterator for I {
    type Item = I::Item;
    type IntoIter = I;

    fn into_iter(self) -> I {
        self
    }
}

struct Vec<T> {}
impl<T> Vec<T> {
    fn new() -> Self { loop {} }
}

impl<T> IntoIterator for Vec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;
}

pub struct IntoIter<T> { }
impl<T> Iterator for IntoIter<T> {
    type Item = T;
}

fn main() {
    Vec::<i32>::new().into_iter()
    .filter_map(|x| if x > 0 { Some(x as u32) } else { None })
    .for_each(|y| { y; });
}"#,
        expect![[r#"
            61..65 'self': Self
            67..68 'f': F
            152..163 '{ loop {} }': FilterMap<Self, F>
            154..161 'loop {}': !
            159..161 '{}': ()
            184..188 'self': Self
            190..191 'f': F
            240..251 '{ loop {} }': ()
            242..249 'loop {}': !
            247..249 '{}': ()
            360..364 'self': Self
            689..693 'self': I
            700..720 '{     ...     }': I
            710..714 'self': I
            779..790 '{ loop {} }': Vec<T>
            781..788 'loop {}': !
            786..788 '{}': ()
            977..1104 '{     ... }); }': ()
            983..998 'Vec::<i32>::new': fn new<i32>() -> Vec<i32>
            983..1000 'Vec::<...:new()': Vec<i32>
            983..1012 'Vec::<...iter()': IntoIter<i32>
            983..1075 'Vec::<...one })': FilterMap<IntoIter<i32>, impl Fn(i32) -> Option<u32>>
            983..1101 'Vec::<... y; })': ()
            1029..1074 '|x| if...None }': impl Fn(i32) -> Option<u32>
            1030..1031 'x': i32
            1033..1074 'if x >...None }': Option<u32>
            1036..1037 'x': i32
            1036..1041 'x > 0': bool
            1040..1041 '0': i32
            1042..1060 '{ Some...u32) }': Option<u32>
            1044..1048 'Some': Some<u32>(u32) -> Option<u32>
            1044..1058 'Some(x as u32)': Option<u32>
            1049..1050 'x': i32
            1049..1057 'x as u32': u32
            1066..1074 '{ None }': Option<u32>
            1068..1072 'None': Option<u32>
            1090..1100 '|y| { y; }': impl Fn(u32)
            1091..1092 'y': u32
            1094..1100 '{ y; }': ()
            1096..1097 'y': u32
        "#]],
    );
}

#[test]
fn nested_assoc() {
    check_types(
        r#"
struct Bar;
struct Foo;

trait A {
    type OutputA;
}

impl A for Bar {
    type OutputA = Foo;
}

trait B {
    type Output;
    fn foo() -> Self::Output;
}

impl<T:A> B for T {
    type Output = T::OutputA;
    fn foo() -> Self::Output { loop {} }
}

fn main() {
    Bar::foo();
} //^^^^^^^^^^ Foo
"#,
    );
}

#[test]
fn trait_object_no_coercion() {
    check_infer_with_mismatches(
        r#"
trait Foo {}

fn foo(x: &dyn Foo) {}

fn test(x: &dyn Foo) {
    foo(x);
}"#,
        expect![[r#"
            21..22 'x': &dyn Foo
            34..36 '{}': ()
            46..47 'x': &dyn Foo
            59..74 '{     foo(x); }': ()
            65..68 'foo': fn foo(&dyn Foo)
            65..71 'foo(x)': ()
            69..70 'x': &dyn Foo
        "#]],
    );
}

#[test]
fn builtin_copy() {
    check_infer_with_mismatches(
        r#"
//- minicore: copy
struct IsCopy;
impl Copy for IsCopy {}
struct NotCopy;

trait Test { fn test(&self) -> bool; }
impl<T: Copy> Test for T {}

fn test() {
    IsCopy.test();
    NotCopy.test();
    (IsCopy, IsCopy).test();
    (IsCopy, NotCopy).test();
}"#,
        expect![[r#"
            78..82 'self': &Self
            134..235 '{     ...t(); }': ()
            140..146 'IsCopy': IsCopy
            140..153 'IsCopy.test()': bool
            159..166 'NotCopy': NotCopy
            159..173 'NotCopy.test()': {unknown}
            179..195 '(IsCop...sCopy)': (IsCopy, IsCopy)
            179..202 '(IsCop...test()': bool
            180..186 'IsCopy': IsCopy
            188..194 'IsCopy': IsCopy
            208..225 '(IsCop...tCopy)': (IsCopy, NotCopy)
            208..232 '(IsCop...test()': {unknown}
            209..215 'IsCopy': IsCopy
            217..224 'NotCopy': NotCopy
        "#]],
    );
}

#[test]
fn builtin_fn_def_copy() {
    check_infer_with_mismatches(
        r#"
//- minicore: copy
fn foo() {}
fn bar<T: Copy>(T) -> T {}
struct Struct(usize);
enum Enum { Variant(usize) }

trait Test { fn test(&self) -> bool; }
impl<T: Copy> Test for T {}

fn test() {
    foo.test();
    bar.test();
    Struct.test();
    Enum::Variant.test();
}"#,
        expect![[r#"
            9..11 '{}': ()
            28..29 'T': {unknown}
            36..38 '{}': T
            36..38: expected T, got ()
            113..117 'self': &Self
            169..249 '{     ...t(); }': ()
            175..178 'foo': fn foo()
            175..185 'foo.test()': bool
            191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown}
            191..201 'bar.test()': bool
            207..213 'Struct': Struct(usize) -> Struct
            207..220 'Struct.test()': bool
            226..239 'Enum::Variant': Variant(usize) -> Enum
            226..246 'Enum::...test()': bool
        "#]],
    );
}

#[test]
fn builtin_fn_ptr_copy() {
    check_infer_with_mismatches(
        r#"
//- minicore: copy
trait Test { fn test(&self) -> bool; }
impl<T: Copy> Test for T {}

fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
    f1.test();
    f2.test();
    f3.test();
}"#,
        expect![[r#"
            22..26 'self': &Self
            76..78 'f1': fn()
            86..88 'f2': fn(usize) -> u8
            107..109 'f3': fn(u8, u8) -> &u8
            130..178 '{     ...t(); }': ()
            136..138 'f1': fn()
            136..145 'f1.test()': bool
            151..153 'f2': fn(usize) -> u8
            151..160 'f2.test()': bool
            166..168 'f3': fn(u8, u8) -> &u8
            166..175 'f3.test()': bool
        "#]],
    );
}

#[test]
fn builtin_sized() {
    check_infer_with_mismatches(
        r#"
//- minicore: sized
trait Test { fn test(&self) -> bool; }
impl<T: Sized> Test for T {}

fn test() {
    1u8.test();
    (*"foo").test(); // not Sized
    (1u8, 1u8).test();
    (1u8, *"foo").test(); // not Sized
}"#,
        expect![[r#"
            22..26 'self': &Self
            79..194 '{     ...ized }': ()
            85..88 '1u8': u8
            85..95 '1u8.test()': bool
            101..116 '(*"foo").test()': {unknown}
            102..108 '*"foo"': str
            103..108 '"foo"': &str
            135..145 '(1u8, 1u8)': (u8, u8)
            135..152 '(1u8, ...test()': bool
            136..139 '1u8': u8
            141..144 '1u8': u8
            158..171 '(1u8, *"foo")': (u8, str)
            158..178 '(1u8, ...test()': {unknown}
            159..162 '1u8': u8
            164..170 '*"foo"': str
            165..170 '"foo"': &str
        "#]],
    );
}

#[test]
fn integer_range_iterate() {
    check_types(
        r#"
//- minicore: range, iterator
//- /main.rs crate:main
fn test() {
    for x in 0..100 { x; }
}                   //^ i32

trait Step {}
impl Step for i32 {}
impl Step for i64 {}

impl<A: Step> core::iter::Iterator for core::ops::Range<A> {
    type Item = A;
}
"#,
    );
}

#[test]
fn infer_closure_arg() {
    check_infer(
        r#"
//- /lib.rs

enum Option<T> {
    None,
    Some(T)
}

fn foo() {
    let s = Option::None;
    let f = |x: Option<i32>| {};
    (&f)(s)
}"#,
        expect![[r#"
            52..126 '{     ...)(s) }': ()
            62..63 's': Option<i32>
            66..78 'Option::None': Option<i32>
            88..89 'f': impl Fn(Option<i32>)
            92..111 '|x: Op...2>| {}': impl Fn(Option<i32>)
            93..94 'x': Option<i32>
            109..111 '{}': ()
            117..124 '(&f)(s)': ()
            118..120 '&f': &impl Fn(Option<i32>)
            119..120 'f': impl Fn(Option<i32>)
            122..123 's': Option<i32>
        "#]],
    );
}

#[test]
fn dyn_fn_param_informs_call_site_closure_signature() {
    cov_mark::check!(dyn_fn_param_informs_call_site_closure_signature);
    check_types(
        r#"
//- minicore: fn, coerce_unsized
struct S;
impl S {
    fn inherent(&self) -> u8 { 0 }
}
fn take_dyn_fn(f: &dyn Fn(S)) {}

fn f() {
    take_dyn_fn(&|x| { x.inherent(); });
                     //^^^^^^^^^^^^ u8
}
        "#,
    );
}

#[test]
fn infer_fn_trait_arg() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn, option
fn foo<F, T>(f: F) -> T
where
    F: Fn(Option<i32>) -> T,
{
    let s = None;
    f(s)
}
"#,
        expect![[r#"
            13..14 'f': F
            59..89 '{     ...f(s) }': T
            69..70 's': Option<i32>
            73..77 'None': Option<i32>
            83..84 'f': F
            83..87 'f(s)': T
            85..86 's': Option<i32>
        "#]],
    );
}

#[test]
fn infer_box_fn_arg() {
    // The type mismatch is because we don't define Unsize and CoerceUnsized
    check_infer_with_mismatches(
        r#"
//- minicore: fn, deref, option
#[lang = "owned_box"]
pub struct Box<T: ?Sized> {
    inner: *mut T,
}

impl<T: ?Sized> core::ops::Deref for Box<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.inner }
    }
}

fn foo() {
    let s = None;
    let f: Box<dyn FnOnce(&Option<i32>)> = Box { inner: &mut (|ps| {}) };
    f(&s);
}"#,
        expect![[r#"
            154..158 'self': &Box<T>
            166..205 '{     ...     }': &T
            176..199 'unsafe...nner }': &T
            185..197 '&*self.inner': &T
            186..197 '*self.inner': T
            187..191 'self': &Box<T>
            187..197 'self.inner': *mut T
            218..324 '{     ...&s); }': ()
            228..229 's': Option<i32>
            232..236 'None': Option<i32>
            246..247 'f': Box<dyn FnOnce(&Option<i32>)>
            281..310 'Box { ... {}) }': Box<dyn FnOnce(&Option<i32>)>
            294..308 '&mut (|ps| {})': &mut impl Fn(&Option<i32>)
            300..307 '|ps| {}': impl Fn(&Option<i32>)
            301..303 'ps': &Option<i32>
            305..307 '{}': ()
            316..317 'f': Box<dyn FnOnce(&Option<i32>)>
            316..321 'f(&s)': ()
            318..320 '&s': &Option<i32>
            319..320 's': Option<i32>
        "#]],
    );
}

#[test]
fn infer_dyn_fn_output() {
    check_types(
        r#"
//- minicore: fn
fn foo() {
    let f: &dyn Fn() -> i32;
    f();
  //^^^ i32
}"#,
    );
}

#[test]
fn infer_dyn_fn_once_output() {
    check_types(
        r#"
//- minicore: fn
fn foo() {
    let f: dyn FnOnce() -> i32;
    f();
  //^^^ i32
}"#,
    );
}

#[test]
fn variable_kinds_1() {
    check_types(
        r#"
trait Trait<T> { fn get(self, t: T) -> T; }
struct S;
impl Trait<u128> for S {}
impl Trait<f32> for S {}
fn test() {
    S.get(1);
  //^^^^^^^^ u128
    S.get(1.);
  //^^^^^^^^^ f32
}
        "#,
    );
}

#[test]
fn variable_kinds_2() {
    check_types(
        r#"
trait Trait { fn get(self) -> Self; }
impl Trait for u128 {}
impl Trait for f32 {}
fn test() {
    1.get();
  //^^^^^^^ u128
    (1.).get();
  //^^^^^^^^^^ f32
}
        "#,
    );
}

#[test]
fn underscore_import() {
    check_types(
        r#"
mod tr {
    pub trait Tr {
        fn method(&self) -> u8 { 0 }
    }
}

struct Tr;
impl crate::tr::Tr for Tr {}

use crate::tr::Tr as _;
fn test() {
    Tr.method();
  //^^^^^^^^^^^ u8
}
    "#,
    );
}

#[test]
fn inner_use() {
    check_types(
        r#"
mod m {
    pub trait Tr {
        fn method(&self) -> u8 { 0 }
    }

    impl Tr for () {}
}

fn f() {
    use m::Tr;

    ().method();
  //^^^^^^^^^^^ u8
}
        "#,
    );
}

#[test]
fn trait_in_scope_with_inner_item() {
    check_infer(
        r#"
mod m {
    pub trait Tr {
        fn method(&self) -> u8 { 0 }
    }

    impl Tr for () {}
}

use m::Tr;

fn f() {
    fn inner() {
        ().method();
      //^^^^^^^^^^^ u8
    }
}"#,
        expect![[r#"
            46..50 'self': &Self
            58..63 '{ 0 }': u8
            60..61 '0': u8
            115..185 '{     ...   } }': ()
            132..183 '{     ...     }': ()
            142..144 '()': ()
            142..153 '().method()': u8
        "#]],
    );
}

#[test]
fn inner_use_in_block() {
    check_types(
        r#"
mod m {
    pub trait Tr {
        fn method(&self) -> u8 { 0 }
    }

    impl Tr for () {}
}

fn f() {
    {
        use m::Tr;

        ().method();
      //^^^^^^^^^^^ u8
    }

    {
        ().method();
      //^^^^^^^^^^^ {unknown}
    }

    ().method();
  //^^^^^^^^^^^ {unknown}
}
        "#,
    );
}

#[test]
fn nested_inner_function_calling_self() {
    check_infer(
        r#"
struct S;
fn f() {
    fn inner() -> S {
        let s = inner();
    }
}"#,
        expect![[r#"
            17..73 '{     ...   } }': ()
            39..71 '{     ...     }': S
            53..54 's': S
            57..62 'inner': fn inner() -> S
            57..64 'inner()': S
        "#]],
    )
}

#[test]
fn infer_default_trait_type_parameter() {
    check_infer(
        r#"
struct A;

trait Op<RHS=Self> {
    type Output;

    fn do_op(self, rhs: RHS) -> Self::Output;
}

impl Op for A {
    type Output = bool;

    fn do_op(self, rhs: Self) -> Self::Output {
        true
    }
}

fn test() {
    let x = A;
    let y = A;
    let r = x.do_op(y);
}"#,
        expect![[r#"
            63..67 'self': Self
            69..72 'rhs': RHS
            153..157 'self': A
            159..162 'rhs': A
            186..206 '{     ...     }': bool
            196..200 'true': bool
            220..277 '{     ...(y); }': ()
            230..231 'x': A
            234..235 'A': A
            245..246 'y': A
            249..250 'A': A
            260..261 'r': bool
            264..265 'x': A
            264..274 'x.do_op(y)': bool
            272..273 'y': A
        "#]],
    )
}

#[test]
fn qualified_path_as_qualified_trait() {
    check_infer(
        r#"
mod foo {

    pub trait Foo {
        type Target;
    }
    pub trait Bar {
        type Output;
        fn boo() -> Self::Output {
            loop {}
        }
    }
}

struct F;
impl foo::Foo for F {
    type Target = ();
}
impl foo::Bar for F {
    type Output = <F as foo::Foo>::Target;
}

fn foo() {
    use foo::Bar;
    let x = <F as Bar>::boo();
}"#,
        expect![[r#"
            132..163 '{     ...     }': Bar::Output<Self>
            146..153 'loop {}': !
            151..153 '{}': ()
            306..358 '{     ...o(); }': ()
            334..335 'x': ()
            338..353 '<F as Bar>::boo': fn boo<F>() -> <F as Bar>::Output
            338..355 '<F as ...:boo()': ()
        "#]],
    );
}

#[test]
fn renamed_extern_crate_in_block() {
    check_types(
        r#"
//- /lib.rs crate:lib deps:serde
use serde::Deserialize;

struct Foo {}

const _ : () = {
    extern crate serde as _serde;
    impl _serde::Deserialize for Foo {
        fn deserialize() -> u8 { 0 }
    }
};

fn foo() {
    Foo::deserialize();
  //^^^^^^^^^^^^^^^^^^ u8
}

//- /serde.rs crate:serde

pub trait Deserialize {
    fn deserialize() -> u8;
}"#,
    );
}

#[test]
fn bin_op_with_rhs_is_self_for_assoc_bound() {
    check_no_mismatches(
        r#"//- minicore: eq
        fn repro<T>(t: T) -> bool
where
    T: Request,
    T::Output: Convertable,
{
    let a = execute(&t).convert();
    let b = execute(&t).convert();
    a.eq(&b);
    let a = execute(&t).convert2();
    let b = execute(&t).convert2();
    a.eq(&b)
}
fn execute<T>(t: &T) -> T::Output
where
    T: Request,
{
    <T as Request>::output()
}
trait Convertable {
    type TraitSelf: PartialEq<Self::TraitSelf>;
    type AssocAsDefaultSelf: PartialEq;
    fn convert(self) -> Self::AssocAsDefaultSelf;
    fn convert2(self) -> Self::TraitSelf;
}
trait Request {
    type Output;
    fn output() -> Self::Output;
}
     "#,
    );
}

#[test]
fn bin_op_adt_with_rhs_primitive() {
    check_infer_with_mismatches(
        r#"
//- minicore: add
struct Wrapper(u32);
impl core::ops::Add<u32> for Wrapper {
    type Output = Self;
    fn add(self, rhs: u32) -> Wrapper {
        Wrapper(rhs)
    }
}
fn main(){
    let wrapped = Wrapper(10);
    let num: u32 = 2;
    let res = wrapped + num;

}"#,
        expect![[r#"
            95..99 'self': Wrapper
            101..104 'rhs': u32
            122..150 '{     ...     }': Wrapper
            132..139 'Wrapper': Wrapper(u32) -> Wrapper
            132..144 'Wrapper(rhs)': Wrapper
            140..143 'rhs': u32
            162..248 '{     ...um;  }': ()
            172..179 'wrapped': Wrapper
            182..189 'Wrapper': Wrapper(u32) -> Wrapper
            182..193 'Wrapper(10)': Wrapper
            190..192 '10': u32
            203..206 'num': u32
            214..215 '2': u32
            225..228 'res': Wrapper
            231..238 'wrapped': Wrapper
            231..244 'wrapped + num': Wrapper
            241..244 'num': u32
        "#]],
    )
}

#[test]
fn builtin_binop_expectation_works_on_single_reference() {
    check_types(
        r#"
//- minicore: add
use core::ops::Add;
impl Add<i32> for i32 { type Output = i32 }
impl Add<&i32> for i32 { type Output = i32 }
impl Add<u32> for u32 { type Output = u32 }
impl Add<&u32> for u32 { type Output = u32 }

struct V<T>;
impl<T> V<T> {
    fn default() -> Self { loop {} }
    fn get(&self, _: &T) -> &T { loop {} }
}

fn take_u32(_: u32) {}
fn minimized() {
    let v = V::default();
    let p = v.get(&0);
      //^ &u32
    take_u32(42 + p);
}
"#,
    );
}

#[test]
fn no_builtin_binop_expectation_for_general_ty_var() {
    // FIXME: Ideally type mismatch should be reported on `take_u32(42 - p)`.
    check_types(
        r#"
//- minicore: add
use core::ops::Add;
impl Add<i32> for i32 { type Output = i32; }
impl Add<&i32> for i32 { type Output = i32; }
// This is needed to prevent chalk from giving unique solution to `i32: Add<&?0>` after applying
// fallback to integer type variable for `42`.
impl Add<&()> for i32 { type Output = (); }

struct V<T>;
impl<T> V<T> {
    fn default() -> Self { loop {} }
    fn get(&self) -> &T { loop {} }
}

fn take_u32(_: u32) {}
fn minimized() {
    let v = V::default();
    let p = v.get();
      //^ &{unknown}
    take_u32(42 + p);
}
"#,
    );
}

#[test]
fn no_builtin_binop_expectation_for_non_builtin_types() {
    check_no_mismatches(
        r#"
//- minicore: default, eq
struct S;
impl Default for S { fn default() -> Self { S } }
impl Default for i32 { fn default() -> Self { 0 } }
impl PartialEq<S> for i32 { fn eq(&self, _: &S) -> bool { true } }
impl PartialEq<i32> for i32 { fn eq(&self, _: &S) -> bool { true } }

fn take_s(_: S) {}
fn test() {
    let s = Default::default();
    let _eq = 0 == s;
    take_s(s);
}
"#,
    )
}

#[test]
fn array_length() {
    check_infer(
        r#"
trait T {
    type Output;
    fn do_thing(&self) -> Self::Output;
}

impl T for [u8; 4] {
    type Output = usize;
    fn do_thing(&self) -> Self::Output {
        2
    }
}

impl T for [u8; 2] {
    type Output = u8;
    fn do_thing(&self) -> Self::Output {
        2
    }
}

fn main() {
    let v = [0u8; 2];
    let v2 = v.do_thing();
    let v3 = [0u8; 4];
    let v4 = v3.do_thing();
}
"#,
        expect![[r#"
            44..48 'self': &Self
            133..137 'self': &[u8; 4]
            155..172 '{     ...     }': usize
            165..166 '2': usize
            236..240 'self': &[u8; 2]
            258..275 '{     ...     }': u8
            268..269 '2': u8
            289..392 '{     ...g(); }': ()
            299..300 'v': [u8; 2]
            303..311 '[0u8; 2]': [u8; 2]
            304..307 '0u8': u8
            309..310 '2': usize
            321..323 'v2': u8
            326..327 'v': [u8; 2]
            326..338 'v.do_thing()': u8
            348..350 'v3': [u8; 4]
            353..361 '[0u8; 4]': [u8; 4]
            354..357 '0u8': u8
            359..360 '4': usize
            371..373 'v4': usize
            376..378 'v3': [u8; 4]
            376..389 'v3.do_thing()': usize
        "#]],
    )
}

#[test]
fn const_generics() {
    check_infer(
        r#"
trait T {
    type Output;
    fn do_thing(&self) -> Self::Output;
}

impl<const L: usize> T for [u8; L] {
    type Output = [u8; L];
    fn do_thing(&self) -> Self::Output {
        *self
    }
}

fn main() {
    let v = [0u8; 2];
    let v2 = v.do_thing();
}
"#,
        expect![[r#"
            44..48 'self': &Self
            151..155 'self': &[u8; L]
            173..194 '{     ...     }': [u8; L]
            183..188 '*self': [u8; L]
            184..188 'self': &[u8; L]
            208..260 '{     ...g(); }': ()
            218..219 'v': [u8; 2]
            222..230 '[0u8; 2]': [u8; 2]
            223..226 '0u8': u8
            228..229 '2': usize
            240..242 'v2': [u8; 2]
            245..246 'v': [u8; 2]
            245..257 'v.do_thing()': [u8; 2]
        "#]],
    )
}

#[test]
fn fn_returning_unit() {
    check_infer_with_mismatches(
        r#"
//- minicore: fn
fn test<F: FnOnce()>(f: F) {
    let _: () = f();
}"#,
        expect![[r#"
            21..22 'f': F
            27..51 '{     ...f(); }': ()
            37..38 '_': ()
            45..46 'f': F
            45..48 'f()': ()
        "#]],
    );
}

#[test]
fn trait_in_scope_of_trait_impl() {
    check_infer(
        r#"
mod foo {
    pub trait Foo {
        fn foo(self);
        fn bar(self) -> usize { 0 }
    }
}
impl foo::Foo for u32 {
    fn foo(self) {
        let _x = self.bar();
    }
}
    "#,
        expect![[r#"
            45..49 'self': Self
            67..71 'self': Self
            82..87 '{ 0 }': usize
            84..85 '0': usize
            131..135 'self': u32
            137..173 '{     ...     }': ()
            151..153 '_x': usize
            156..160 'self': u32
            156..166 'self.bar()': usize
        "#]],
    );
}

#[test]
fn infer_async_ret_type() {
    check_types(
        r#"
//- minicore: future, result
struct Fooey;

impl Fooey {
    fn collect<B: Convert>(self) -> B {
        B::new()
    }
}

trait Convert {
    fn new() -> Self;
}
impl Convert for u32 {
    fn new() -> Self { 0 }
}

async fn get_accounts() -> Result<u32, ()> {
    let ret = Fooey.collect();
    //        ^^^^^^^^^^^^^^^ u32
    Ok(ret)
}
"#,
    );
}

#[test]
fn local_impl_1() {
    check_types(
        r#"
trait Trait<T> {
    fn foo(&self) -> T;
}

fn test() {
    struct S;
    impl Trait<u32> for S {
        fn foo(&self) -> u32 { 0 }
    }

    S.foo();
 // ^^^^^^^ u32
}
"#,
    );
}

#[test]
fn local_impl_2() {
    check_types(
        r#"
struct S;

fn test() {
    trait Trait<T> {
        fn foo(&self) -> T;
    }
    impl Trait<u32> for S {
        fn foo(&self) -> u32 { 0 }
    }

    S.foo();
 // ^^^^^^^ u32
}
"#,
    );
}

#[test]
fn local_impl_3() {
    check_types(
        r#"
trait Trait<T> {
    fn foo(&self) -> T;
}

fn test() {
    struct S1;
    {
        struct S2;

        impl Trait<S1> for S2 {
            fn foo(&self) -> S1 { S1 }
        }

        S2.foo();
     // ^^^^^^^^ S1
    }
}
"#,
    );
}

#[test]
fn foreign_trait_with_local_trait_impl() {
    check!(block_local_impls);
    check(
        r#"
mod module {
    pub trait T {
        const C: usize;
        fn f(&self);
    }
}

fn f() {
    use module::T;
    impl T for usize {
        const C: usize = 0;
        fn f(&self) {}
    }
    0usize.f();
  //^^^^^^^^^^ type: ()
    usize::C;
  //^^^^^^^^type: usize
}
"#,
    );
}

#[test]
fn regression_14443_trait_solve() {
    check_no_mismatches(
        r#"
trait T {
    fn f(&self) {}
}


fn main() {
    struct A;
    impl T for A {}

    let a = A;

    let b = {
        struct B;
        impl T for B {}

        B
    };

    a.f();
    b.f();
}
"#,
    )
}

#[test]
fn associated_type_sized_bounds() {
    check_infer(
        r#"
//- minicore: sized
struct Yes;
trait IsSized { const IS_SIZED: Yes; }
impl<T: Sized> IsSized for T { const IS_SIZED: Yes = Yes; }

trait Foo {
    type Explicit: Sized;
    type Implicit;
    type Relaxed: ?Sized;
}
fn f<F: Foo>() {
    F::Explicit::IS_SIZED;
    F::Implicit::IS_SIZED;
    F::Relaxed::IS_SIZED;
}
"#,
        expect![[r#"
            104..107 'Yes': Yes
            212..295 '{     ...ZED; }': ()
            218..239 'F::Exp..._SIZED': Yes
            245..266 'F::Imp..._SIZED': Yes
            272..292 'F::Rel..._SIZED': {unknown}
        "#]],
    );
}

#[test]
fn dyn_map() {
    check_types(
        r#"
pub struct Key<K, V, P = (K, V)> {}

pub trait Policy {
    type K;
    type V;
}

impl<K, V> Policy for (K, V) {
    type K = K;
    type V = V;
}

pub struct KeyMap<KEY> {}

impl<P: Policy> KeyMap<Key<P::K, P::V, P>> {
    pub fn get(&self, key: &P::K) -> P::V {
        loop {}
    }
}

struct Fn {}
struct FunctionId {}

fn test() {
    let key_map: &KeyMap<Key<Fn, FunctionId>> = loop {};
    let key;
    let result = key_map.get(key);
      //^^^^^^ FunctionId
}
"#,
    )
}

#[test]
fn dyn_multiple_auto_traits_in_different_order() {
    check_no_mismatches(
        r#"
auto trait Send {}
auto trait Sync {}

fn f(t: &(dyn Sync + Send)) {}
fn g(t: &(dyn Send + Sync)) {
    f(t);
}
        "#,
    );

    check_no_mismatches(
        r#"
auto trait Send {}
auto trait Sync {}
trait T {}

fn f(t: &(dyn T + Send + Sync)) {}
fn g(t: &(dyn Sync + T + Send)) {
    f(t);
}
        "#,
    );

    check_infer_with_mismatches(
        r#"
auto trait Send {}
auto trait Sync {}
trait T1 {}
trait T2 {}

fn f(t: &(dyn T1 + T2 + Send + Sync)) {}
fn g(t: &(dyn Sync + T2 + T1 + Send)) {
    f(t);
}
        "#,
        expect![[r#"
            68..69 't': &{unknown}
            101..103 '{}': ()
            109..110 't': &{unknown}
            142..155 '{     f(t); }': ()
            148..149 'f': fn f(&{unknown})
            148..152 'f(t)': ()
            150..151 't': &{unknown}
        "#]],
    );

    check_no_mismatches(
        r#"
auto trait Send {}
auto trait Sync {}
trait T {
    type Proj: Send + Sync;
}

fn f(t: &(dyn T<Proj = ()>  + Send + Sync)) {}
fn g(t: &(dyn Sync + T<Proj = ()> + Send)) {
    f(t);
}
        "#,
    );
}

#[test]
fn dyn_multiple_projection_bounds() {
    check_no_mismatches(
        r#"
trait Trait {
    type T;
    type U;
}

fn f(t: &dyn Trait<T = (), U = ()>) {}
fn g(t: &dyn Trait<U = (), T = ()>) {
    f(t);
}
        "#,
    );

    check_types(
        r#"
trait Trait {
    type T;
}

fn f(t: &dyn Trait<T = (), T = ()>) {}
   //^&{unknown}
        "#,
    );
}

#[test]
fn dyn_duplicate_auto_trait() {
    check_no_mismatches(
        r#"
auto trait Send {}

fn f(t: &(dyn Send + Send)) {}
fn g(t: &(dyn Send)) {
    f(t);
}
        "#,
    );

    check_no_mismatches(
        r#"
auto trait Send {}
trait T {}

fn f(t: &(dyn T + Send + Send)) {}
fn g(t: &(dyn T + Send)) {
    f(t);
}
        "#,
    );
}

#[test]
fn gats_in_path() {
    check_types(
        r#"
//- minicore: deref
use core::ops::Deref;
trait PointerFamily {
    type Pointer<T>: Deref<Target = T>;
}

fn f<P: PointerFamily>(p: P::Pointer<i32>) {
    let a = *p;
      //^ i32
}
fn g<P: PointerFamily>(p: <P as PointerFamily>::Pointer<i32>) {
    let a = *p;
      //^ i32
}
        "#,
    );
}

#[test]
fn gats_with_impl_trait() {
    // FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot
    // specify the same associated type multiple times even if their arguments are different (c.f.
    // `fn h()`, which is valid). Reconsider how to treat these invalid types.
    check_types(
        r#"
//- minicore: deref
use core::ops::Deref;

trait Trait {
    type Assoc<T>: Deref<Target = T>;
    fn get<U>(&self) -> Self::Assoc<U>;
}

fn f<T>(v: impl Trait) {
    let a = v.get::<i32>().deref();
      //^ &i32
    let a = v.get::<T>().deref();
      //^ &T
}
fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
    let a = v.get::<T>();
      //^ &T
    let a = v.get::<()>();
      //^ Trait::Assoc<(), impl Trait<Assoc<T> = &T>>
}
fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
    let a = v.get::<i32>();
      //^ &i32
    let a = v.get::<i64>();
      //^ &i64
}
fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
    let a = v.get::<i32>();
      //^ &i32
    let a = v.get::<i64>();
      //^ &i64
}
    "#,
    );
}

#[test]
fn gats_with_dyn() {
    // This test is here to keep track of how we infer things despite traits with GATs being not
    // object-safe currently.
    // FIXME: reconsider how to treat these invalid types.
    check_infer_with_mismatches(
        r#"
//- minicore: deref
use core::ops::Deref;

trait Trait {
    type Assoc<T>: Deref<Target = T>;
    fn get<U>(&self) -> Self::Assoc<U>;
}

fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
    v.get::<i32>().deref();
}
    "#,
        expect![[r#"
            90..94 'self': &Self
            127..128 'v': &(dyn Trait<Assoc<i32> = &i32>)
            164..195 '{     ...f(); }': ()
            170..171 'v': &(dyn Trait<Assoc<i32> = &i32>)
            170..184 'v.get::<i32>()': &i32
            170..192 'v.get:...eref()': &i32
        "#]],
    );
}

#[test]
fn gats_in_associated_type_binding() {
    check_types(
        r#"
trait Trait {
    type Assoc<T>;
    fn get<U>(&self) -> Self::Assoc<U>;
}

fn f<T>(t: T)
where
    T: Trait<Assoc<i32> = u32>,
    T: Trait<Assoc<isize> = usize>,
{
    let a = t.get::<i32>();
      //^ u32
    let a = t.get::<isize>();
      //^ usize
    let a = t.get::<()>();
      //^ Trait::Assoc<(), T>
}

    "#,
    );
}

#[test]
fn gats_in_bounds_for_assoc() {
    check_types(
        r#"
trait Trait {
    type Assoc: Another<Gat<i32> = usize>;
    type Assoc2<T>: Another<Gat<T> = T>;
}
trait Another {
    type Gat<T>;
    fn foo(&self) -> Self::Gat<i32>;
    fn bar<T>(&self) -> Self::Gat<T>;
}

fn test<T: Trait>(a: T::Assoc, b: T::Assoc2<isize>) {
    let v = a.foo();
      //^ usize
    let v = b.bar::<isize>();
      //^ isize
}
"#,
    );
}

#[test]
fn bin_op_with_scalar_fallback() {
    // Extra impls are significant so that chalk doesn't give us definite guidances.
    check_types(
        r#"
//- minicore: add
use core::ops::Add;

struct Vec2<T>(T, T);

impl Add for Vec2<i32> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output { loop {} }
}
impl Add for Vec2<u32> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output { loop {} }
}
impl Add for Vec2<f32> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output { loop {} }
}
impl Add for Vec2<f64> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output { loop {} }
}

fn test() {
    let a = Vec2(1, 2);
    let b = Vec2(3, 4);
    let c = a + b;
      //^ Vec2<i32>
    let a = Vec2(1., 2.);
    let b = Vec2(3., 4.);
    let c = a + b;
      //^ Vec2<f64>
}
"#,
    );
}

#[test]
fn trait_method_with_scalar_fallback() {
    check_types(
        r#"
trait Trait {
    type Output;
    fn foo(&self) -> Self::Output;
}
impl<T> Trait for T {
    type Output = T;
    fn foo(&self) -> Self::Output { loop {} }
}
fn test() {
    let a = 42;
    let b = a.foo();
      //^ i32
    let a = 3.14;
    let b = a.foo();
      //^ f64
}
"#,
    );
}

#[test]
fn associated_type_in_struct_expr_path() {
    // FIXME: All annotation should be resolvable.
    // For lines marked as unstable, see rust-lang/rust#86935.
    // FIXME: Remove the comments once stablized.
    check_types(
        r#"
trait Trait {
    type Assoc;
    fn f();
}

struct S { x: u32 }

impl Trait for () {
    type Assoc = S;

    fn f() {
        let x = 42;
        let a = Self::Assoc { x };
      //    ^ S
        let a = <Self>::Assoc { x }; // unstable
      //    ^ {unknown}

        // should be `Copy` but we don't track ownership anyway.
        let value = S { x };
        if let Self::Assoc { x } = value {}
      //                     ^ u32
        if let <Self>::Assoc { x } = value {} // unstable
      //                       ^ {unknown}
    }
}
    "#,
    );
}

#[test]
fn associated_type_in_struct_expr_path_enum() {
    // FIXME: All annotation should be resolvable.
    // For lines marked as unstable, see rust-lang/rust#86935.
    // FIXME: Remove the comments once stablized.
    check_types(
        r#"
trait Trait {
    type Assoc;
    fn f();
}

enum E {
    Unit,
    Struct { x: u32 },
}

impl Trait for () {
    type Assoc = E;

    fn f() {
        let a = Self::Assoc::Unit;
      //    ^ E
        let a = <Self>::Assoc::Unit;
      //    ^ E
        let a = <Self::Assoc>::Unit;
      //    ^ E
        let a = <<Self>::Assoc>::Unit;
      //    ^ E

        // should be `Copy` but we don't track ownership anyway.
        let value = E::Unit;
        if let Self::Assoc::Unit = value {}
      //       ^^^^^^^^^^^^^^^^^ E
        if let <Self>::Assoc::Unit = value {}
      //       ^^^^^^^^^^^^^^^^^^^ E
        if let <Self::Assoc>::Unit = value {}
      //       ^^^^^^^^^^^^^^^^^^^ E
        if let <<Self>::Assoc>::Unit = value {}
      //       ^^^^^^^^^^^^^^^^^^^^^ E

        let x = 42;
        let a = Self::Assoc::Struct { x };
      //    ^ E
        let a = <Self>::Assoc::Struct { x }; // unstable
      //    ^ {unknown}
        let a = <Self::Assoc>::Struct { x }; // unstable
      //    ^ {unknown}
        let a = <<Self>::Assoc>::Struct { x }; // unstable
      //    ^ {unknown}

        // should be `Copy` but we don't track ownership anyway.
        let value = E::Struct { x: 42 };
        if let Self::Assoc::Struct { x } = value {}
      //                             ^ u32
        if let <Self>::Assoc::Struct { x } = value {} // unstable
      //                               ^ {unknown}
        if let <Self::Assoc>::Struct { x } = value {} // unstable
      //                               ^ {unknown}
        if let <<Self>::Assoc>::Struct { x } = value {} // unstable
      //                                 ^ {unknown}
    }
}
    "#,
    );
}

#[test]
fn derive_macro_bounds() {
    check_types(
        r#"
        //- minicore: clone, derive
        #[derive(Clone)]
        struct Copy;
        struct NotCopy;
        #[derive(Clone)]
        struct Generic<T>(T);
        trait Tr {
            type Assoc;
        }
        impl Tr for Copy {
            type Assoc = NotCopy;
        }
        #[derive(Clone)]
        struct AssocGeneric<T: Tr>(T::Assoc);

        // Currently rustc does not accept this.
        // #[derive(Clone)]
        // struct AssocGeneric2<T: Tr>(<T as Tr>::Assoc);

        #[derive(Clone)]
        struct AssocGeneric3<T: Tr>(Generic<T::Assoc>);

        #[derive(Clone)]
        struct Vec<T>();

        #[derive(Clone)]
        struct R1(Vec<R2>);
        #[derive(Clone)]
        struct R2(R1);

        fn f() {
            let x = (&Copy).clone();
              //^ Copy
            let x = (&NotCopy).clone();
              //^ &NotCopy
            let x = (&Generic(Copy)).clone();
              //^ Generic<Copy>
            let x = (&Generic(NotCopy)).clone();
              //^ &Generic<NotCopy>
            let x: &AssocGeneric<Copy> = &AssocGeneric(NotCopy);
            let x = x.clone();
              //^ &AssocGeneric<Copy>
            // let x: &AssocGeneric2<Copy> = &AssocGeneric2(NotCopy);
            // let x = x.clone();
            let x: &AssocGeneric3<Copy> = &AssocGeneric3(Generic(NotCopy));
            let x = x.clone();
              //^ &AssocGeneric3<Copy>
            let x = (&R1(Vec())).clone();
              //^ R1
            let x = (&R2(R1(Vec()))).clone();
              //^ R2
        }
        "#,
    );
}

#[test]
fn trait_obligations_should_be_registered_during_path_inference() {
    check_types(
        r#"
//- minicore: fn, from
struct S<T>(T);
fn map<T, U, F: FnOnce(T) -> S<U>>(_: T, _: F) -> U { loop {} }

fn test(v: S<i32>) {
    let res = map(v, Into::into);
      //^^^ i32
}
"#,
    );
}

#[test]
fn fn_obligation_should_be_registered_during_path_inference() {
    check_types(
        r#"
//- minicore: fn, from
struct S<T>(T);
impl<T> S<T> {
    fn foo<U: Into<S<T>>>(_: U) -> Self { loop {} }
}
fn map<T, U, F: FnOnce(T) -> U>(_: T, _: F) -> U { loop {} }

fn test(v: S<i32>) {
    let res = map(v, S::foo);
      //^^^ S<i32>
}
"#,
    );
}

#[test]
fn associated_type_in_argument() {
    check(
        r#"
trait A {
    fn m(&self) -> i32;
}

fn x<T: B>(k: &<T as B>::Ty) {
    k.m();
}

struct X;
struct Y;

impl A for X {
    fn m(&self) -> i32 {
        8
    }
}

impl A for Y {
    fn m(&self) -> i32 {
        32
    }
}

trait B {
    type Ty: A;
}

impl B for u16 {
    type Ty = X;
}

fn ttt() {
    let inp = Y;
    x::<u16>(&inp);
           //^^^^ expected &X, got &Y
}
"#,
    );
}
