use expect_test::expect;

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

#[test]
fn bug_484() {
    check_infer(
        r#"
        fn test() {
            let x = if true {};
        }
        "#,
        expect![[r#"
            10..37 '{     ... {}; }': ()
            20..21 'x': ()
            24..34 'if true {}': ()
            27..31 'true': bool
            32..34 '{}': ()
        "#]],
    );
}

#[test]
fn no_panic_on_field_of_enum() {
    check_infer(
        r#"
        enum X {}

        fn test(x: X) {
            x.some_field;
        }
        "#,
        expect![[r#"
            19..20 'x': X
            25..46 '{     ...eld; }': ()
            31..32 'x': X
            31..43 'x.some_field': {unknown}
        "#]],
    );
}

#[test]
fn bug_585() {
    check_infer(
        r#"
        fn test() {
            X {};
            match x {
                A::B {} => (),
                A::Y() => (),
            }
        }
        "#,
        expect![[r#"
            10..88 '{     ...   } }': ()
            16..20 'X {}': {unknown}
            26..86 'match ...     }': ()
            32..33 'x': {unknown}
            44..51 'A::B {}': {unknown}
            55..57 '()': ()
            67..73 'A::Y()': {unknown}
            77..79 '()': ()
        "#]],
    );
}

#[test]
fn bug_651() {
    check_infer(
        r#"
        fn quux() {
            let y = 92;
            1 + y;
        }
        "#,
        expect![[r#"
            10..40 '{     ...+ y; }': ()
            20..21 'y': i32
            24..26 '92': i32
            32..33 '1': i32
            32..37 '1 + y': i32
            36..37 'y': i32
        "#]],
    );
}

#[test]
fn recursive_vars() {
    check_infer(
        r#"
        fn test() {
            let y = unknown;
            [y, &y];
        }
        "#,
        expect![[r#"
            10..47 '{     ...&y]; }': ()
            20..21 'y': {unknown}
            24..31 'unknown': {unknown}
            37..44 '[y, &y]': [{unknown}; 2]
            38..39 'y': {unknown}
            41..43 '&y': &'? {unknown}
            42..43 'y': {unknown}
        "#]],
    );
}

#[test]
fn recursive_vars_2() {
    check_infer(
        r#"
        fn test() {
            let x = unknown;
            let y = unknown;
            [(x, y), (&y, &x)];
        }
        "#,
        expect![[r#"
            10..79 '{     ...x)]; }': ()
            20..21 'x': &'? {unknown}
            24..31 'unknown': &'? {unknown}
            41..42 'y': {unknown}
            45..52 'unknown': {unknown}
            58..76 '[(x, y..., &x)]': [(&'? {unknown}, {unknown}); 2]
            59..65 '(x, y)': (&'? {unknown}, {unknown})
            60..61 'x': &'? {unknown}
            63..64 'y': {unknown}
            67..75 '(&y, &x)': (&'? {unknown}, {unknown})
            68..70 '&y': &'? {unknown}
            69..70 'y': {unknown}
            72..74 '&x': &'? &'? {unknown}
            73..74 'x': &'? {unknown}
        "#]],
    );
}

#[test]
fn array_elements_expected_type() {
    check_no_mismatches(
        r#"
        fn test() {
            let x: [[u32; 2]; 2] = [[1, 2], [3, 4]];
        }
        "#,
    );
}

#[test]
fn infer_std_crash_1() {
    // caused stack overflow, taken from std
    check_infer(
        r#"
        enum Maybe<T> {
            Real(T),
            Fake,
        }

        fn write() {
            match something_unknown {
                Maybe::Real(ref mut something) => (),
            }
        }
        "#,
        expect![[r#"
            53..138 '{     ...   } }': ()
            59..136 'match ...     }': ()
            65..82 'someth...nknown': Maybe<{unknown}>
            93..123 'Maybe:...thing)': Maybe<{unknown}>
            105..122 'ref mu...ething': &'? mut {unknown}
            127..129 '()': ()
        "#]],
    );
}

#[test]
fn infer_std_crash_2() {
    // caused "equating two type variables, ...", taken from std
    check_infer(
        r#"
        fn test_line_buffer() {
            &[0, b'\n', 1, b'\n'];
        }
        "#,
        expect![[r#"
            22..52 '{     ...n']; }': ()
            28..49 '&[0, b...b'\n']': &'? [u8; 4]
            29..49 '[0, b'...b'\n']': [u8; 4]
            30..31 '0': u8
            33..38 'b'\n'': u8
            40..41 '1': u8
            43..48 'b'\n'': u8
        "#]],
    );
}

#[test]
fn infer_std_crash_3() {
    // taken from rustc
    check_infer(
        r#"
        pub fn compute() {
            match nope!() {
                SizeSkeleton::Pointer { non_zero: true, tail } => {}
            }
        }
        "#,
        expect![[r#"
            17..107 '{     ...   } }': ()
            23..105 'match ...     }': ()
            29..36 'nope!()': {unknown}
            47..93 'SizeSk...tail }': {unknown}
            81..85 'true': bool
            81..85 'true': bool
            87..91 'tail': {unknown}
            97..99 '{}': ()
        "#]],
    );
}

#[test]
fn infer_std_crash_4() {
    // taken from rustc
    check_infer(
        r#"
        pub fn primitive_type() {
            match *self {
                BorrowedRef { type_: Primitive(p), ..} => {},
            }
        }
        "#,
        expect![[r#"
            24..105 '{     ...   } }': ()
            30..103 'match ...     }': ()
            36..41 '*self': {unknown}
            37..41 'self': {unknown}
            52..90 'Borrow...), ..}': {unknown}
            73..85 'Primitive(p)': {unknown}
            83..84 'p': {unknown}
            94..96 '{}': ()
        "#]],
    );
}

#[test]
fn infer_std_crash_5() {
    // taken from rustc
    check_infer(
        r#"
        //- minicore: iterator
        fn extra_compiler_flags() {
            for content in doesnt_matter {
                let name = if doesnt_matter {
                    first
                } else {
                    &content
                };

                let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
                    name
                } else {
                    content
                };
            }
        }
        "#,
        expect![[r#"
            26..322 '{     ...   } }': ()
            32..320 'for co...     }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
            32..320 'for co...     }': {unknown}
            32..320 'for co...     }': !
            32..320 'for co...     }': {unknown}
            32..320 'for co...     }': &'? mut {unknown}
            32..320 'for co...     }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
            32..320 'for co...     }': Option<{unknown}>
            32..320 'for co...     }': ()
            32..320 'for co...     }': ()
            32..320 'for co...     }': ()
            32..320 'for co...     }': ()
            36..43 'content': {unknown}
            47..60 'doesnt_matter': {unknown}
            61..320 '{     ...     }': ()
            75..79 'name': &'? {unknown}
            82..166 'if doe...     }': &'? {unknown}
            85..98 'doesnt_matter': bool
            99..128 '{     ...     }': &'? {unknown}
            113..118 'first': &'? {unknown}
            134..166 '{     ...     }': &'? {unknown}
            148..156 '&content': &'? {unknown}
            149..156 'content': {unknown}
            181..188 'content': &'? {unknown}
            191..313 'if ICE...     }': &'? {unknown}
            194..231 'ICE_RE..._VALUE': {unknown}
            194..247 'ICE_RE...&name)': bool
            241..246 '&name': &'? &'? {unknown}
            242..246 'name': &'? {unknown}
            248..276 '{     ...     }': &'? {unknown}
            262..266 'name': &'? {unknown}
            282..313 '{     ...     }': {unknown}
            296..303 'content': {unknown}
        "#]],
    );
}

#[test]
fn infer_nested_generics_crash() {
    // another crash found typechecking rustc
    check_infer(
        r#"
        struct Canonical<V> {
            value: V,
        }
        struct QueryResponse<V> {
            value: V,
        }
        fn test<R>(query_response: Canonical<QueryResponse<R>>) {
            &query_response.value;
        }
        "#,
        expect![[r#"
            91..105 'query_response': Canonical<QueryResponse<R>>
            136..166 '{     ...lue; }': ()
            142..163 '&query....value': &'? QueryResponse<R>
            143..157 'query_response': Canonical<QueryResponse<R>>
            143..163 'query_....value': QueryResponse<R>
        "#]],
    );
}

#[test]
fn infer_paren_macro_call() {
    check_infer(
        r#"
        macro_rules! bar { () => {0u32} }
        fn test() {
            let a = (bar!());
        }
        "#,
        expect![[r#"
            !0..4 '0u32': u32
            44..69 '{     ...()); }': ()
            54..55 'a': u32
        "#]],
    );
}

#[test]
fn infer_array_macro_call() {
    check_infer(
        r#"
        macro_rules! bar { () => {0u32} }
        fn test() {
            let a = [bar!()];
        }
        "#,
        expect![[r#"
            !0..4 '0u32': u32
            44..69 '{     ...()]; }': ()
            54..55 'a': [u32; 1]
            58..66 '[bar!()]': [u32; 1]
        "#]],
    );
}

#[test]
fn bug_1030() {
    check_infer(
        r#"
        struct HashSet<T, H>;
        struct FxHasher;
        type FxHashSet<T> = HashSet<T, FxHasher>;

        impl<T, H> HashSet<T, H> {
            fn default() -> HashSet<T, H> {}
        }

        pub fn main_loop() {
            FxHashSet::default();
        }
        "#,
        expect![[r#"
            143..145 '{}': HashSet<T, H>
            168..197 '{     ...t(); }': ()
            174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher>
            174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher>
        "#]],
    );
}

#[test]
fn issue_2669() {
    check_infer(
        r#"
        trait A {}
        trait Write {}
        struct Response<T> {}

        trait D {
            fn foo();
        }

        impl<T:A> D for Response<T> {
            fn foo() {
                end();
                fn end<W: Write>() {
                    let _x: T =  loop {};
                }
            }
        }
        "#,
        expect![[r#"
            119..214 '{     ...     }': ()
            129..132 'end': fn end<{unknown}>()
            129..134 'end()': ()
            163..208 '{     ...     }': ()
            181..183 '_x': !
            190..197 'loop {}': !
            195..197 '{}': ()
        "#]],
    )
}

#[test]
fn issue_2705() {
    check_infer(
        r#"
        trait Trait {}
        fn test() {
            <Trait<u32>>::foo()
        }
        "#,
        expect![[r#"
            25..52 '{     ...oo() }': ()
            31..48 '<Trait...>::foo': {unknown}
            31..50 '<Trait...:foo()': ()
        "#]],
    );
}

#[test]
fn issue_2683_chars_impl() {
    check_types(
        r#"
//- minicore: iterator
pub struct Chars<'a> {}
impl<'a> Iterator for Chars<'a> {
    type Item = char;
    fn next(&mut self) -> Option<char> { loop {} }
}

fn test() {
    let chars: Chars<'_>;
    (chars.next(), chars.nth(1));
} //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (Option<char>, Option<char>)
"#,
    );
}

#[test]
fn issue_3999_slice() {
    check_infer(
        r#"
        fn foo(params: &[usize]) {
            match params {
                [ps @ .., _] => {}
            }
        }
        "#,
        expect![[r#"
            7..13 'params': &'? [usize]
            25..80 '{     ...   } }': ()
            31..78 'match ...     }': ()
            37..43 'params': &'? [usize]
            54..66 '[ps @ .., _]': [usize]
            55..62 'ps @ ..': &'? [usize]
            60..62 '..': [usize]
            64..65 '_': usize
            70..72 '{}': ()
        "#]],
    );
}

#[test]
fn issue_3999_struct() {
    // rust-analyzer should not panic on seeing this malformed
    // record pattern.
    check_infer(
        r#"
        struct Bar {
            a: bool,
        }
        fn foo(b: Bar) {
            match b {
                Bar { a: .. } => {},
            }
        }
        "#,
        expect![[r#"
            35..36 'b': Bar
            43..95 '{     ...   } }': ()
            49..93 'match ...     }': ()
            55..56 'b': Bar
            67..80 'Bar { a: .. }': Bar
            76..78 '..': bool
            84..86 '{}': ()
        "#]],
    );
}

#[test]
fn issue_4235_name_conflicts() {
    check_infer(
        r#"
        struct FOO {}
        static FOO:FOO = FOO {};

        impl FOO {
            fn foo(&self) {}
        }

        fn main() {
            let a = &FOO;
            a.foo();
        }
        "#,
        expect![[r#"
            31..37 'FOO {}': FOO
            63..67 'self': &'? FOO
            69..71 '{}': ()
            85..119 '{     ...o(); }': ()
            95..96 'a': &'? FOO
            99..103 '&FOO': &'? FOO
            100..103 'FOO': FOO
            109..110 'a': &'? FOO
            109..116 'a.foo()': ()
        "#]],
    );
}

#[test]
fn issue_4465_dollar_crate_at_type() {
    check_infer(
        r#"
        pub struct Foo {}
        pub fn anything<T>() -> T {
            loop {}
        }
        macro_rules! foo {
            () => {{
                let r: $crate::Foo = anything();
                r
            }};
        }
        fn main() {
            let _a = foo!();
        }
        "#,
        expect![[r#"
            44..59 '{     loop {} }': T
            50..57 'loop {}': !
            55..57 '{}': ()
            !0..31 '{letr:...g();r}': Foo
            !4..5 'r': Foo
            !18..26 'anything': fn anything<Foo>() -> Foo
            !18..28 'anything()': Foo
            !29..30 'r': Foo
            163..187 '{     ...!(); }': ()
            173..175 '_a': Foo
        "#]],
    );
}

#[test]
fn issue_6811() {
    check_infer(
        r#"
        macro_rules! profile_function {
            () => {
                let _a = 1;
                let _b = 1;
            };
        }
        fn main() {
            profile_function!();
        }
        "#,
        expect![[r#"
            !3..5 '_a': i32
            !6..7 '1': i32
            !11..13 '_b': i32
            !14..15 '1': i32
            103..131 '{     ...!(); }': ()
        "#]],
    );
}

#[test]
fn issue_4053_diesel_where_clauses() {
    check_infer(
        r#"
        trait BoxedDsl<DB> {
            type Output;
            fn internal_into_boxed(self) -> Self::Output;
        }

        struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> {
            order: Order,
        }

        trait QueryFragment<DB: Backend> {}

        trait Into<T> { fn into(self) -> T; }

        impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB>
            for SelectStatement<F, S, D, W, O, LOf, G>
        where
            O: Into<dyn QueryFragment<DB>>,
        {
            type Output = XXX;

            fn internal_into_boxed(self) -> Self::Output {
                self.order.into();
            }
        }
        "#,
        expect![[r#"
            65..69 'self': Self
            267..271 'self': Self
            466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
            488..522 '{     ...     }': ()
            498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
            498..508 'self.order': O
            498..515 'self.o...into()': dyn QueryFragment<DB>
        "#]],
    );
}

#[test]
fn issue_4953() {
    check_infer(
        r#"
        pub struct Foo(pub i64);
        impl Foo {
            fn test() -> Self { Self(0i64) }
        }
        "#,
        expect![[r#"
            58..72 '{ Self(0i64) }': Foo
            60..64 'Self': fn Foo(i64) -> Foo
            60..70 'Self(0i64)': Foo
            65..69 '0i64': i64
        "#]],
    );
    check_infer(
        r#"
        pub struct Foo<T>(pub T);
        impl Foo<i64> {
            fn test() -> Self { Self(0i64) }
        }
        "#,
        expect![[r#"
            64..78 '{ Self(0i64) }': Foo<i64>
            66..70 'Self': fn Foo<i64>(i64) -> Foo<i64>
            66..76 'Self(0i64)': Foo<i64>
            71..75 '0i64': i64
        "#]],
    );
}

#[test]
fn issue_4931() {
    check_infer(
        r#"
        trait Div<T> {
            type Output;
        }

        trait CheckedDiv: Div<()> {}

        trait PrimInt: CheckedDiv<Output = ()> {
            fn pow(self);
        }

        fn check<T: PrimInt>(i: T) {
            i.pow();
        }
        "#,
        expect![[r#"
            117..121 'self': Self
            148..149 'i': T
            154..170 '{     ...w(); }': ()
            160..161 'i': T
            160..167 'i.pow()': ()
        "#]],
    );
}

#[test]
fn issue_4885() {
    check_infer(
        r#"
        //- minicore: coerce_unsized, future
        use core::future::Future;
        trait Foo<R> {
            type Bar;
        }
        fn foo<R, K>(key: &K) -> impl Future<Output = K::Bar>
        where
            K: Foo<R>,
        {
            bar(key)
        }
        fn bar<R, K>(key: &K) -> impl Future<Output = K::Bar>
        where
            K: Foo<R>,
        {
        }
        "#,
        expect![[r#"
            70..73 'key': &'? K
            132..148 '{     ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
            138..141 'bar': fn bar<R, K>(&'? K) -> impl Future<Output = <K as Foo<R>>::Bar>
            138..146 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
            142..145 'key': &'? K
            162..165 'key': &'? K
            224..227 '{ }': ()
        "#]],
    );
}

#[test]
fn issue_4800() {
    check_infer(
        r#"
        trait Debug {}

        struct Foo<T>;

        type E1<T> = (T, T, T);
        type E2<T> = E1<E1<E1<(T, T, T)>>>;

        impl Debug for Foo<E2<()>> {}

        struct Request;

        pub trait Future {
            type Output;
        }

        pub struct PeerSet<D>;

        impl<D> Service<Request> for PeerSet<D>
        where
            D: Discover,
            D::Key: Debug,
        {
            type Error = ();
            type Future = dyn Future<Output = Self::Error>;

            fn call(&mut self) -> Self::Future {
                loop {}
            }
        }

        pub trait Discover {
            type Key;
        }

        pub trait Service<Request> {
            type Error;
            type Future: Future<Output = Self::Error>;
            fn call(&mut self) -> Self::Future;
        }
        "#,
        expect![[r#"
            379..383 'self': &'? mut PeerSet<D>
            401..424 '{     ...     }': dyn Future<Output = ()>
            411..418 'loop {}': !
            416..418 '{}': ()
            575..579 'self': &'? mut Self
        "#]],
    );
}

#[test]
fn issue_4966() {
    check_infer(
        r#"
        //- minicore: deref
        pub trait IntoIterator {
            type Item;
        }

        struct Repeat<A> { element: A }

        struct Map<F> { f: F }

        struct Vec<T> {}

        impl<T> core::ops::Deref for Vec<T> {
            type Target = [T];
        }

        fn from_iter<A, T: IntoIterator<Item = A>>(iter: T) -> Vec<A> {}

        fn main() {
            let inner = Map { f: |_: &f64| 0.0 };

            let repeat = Repeat { element: inner };

            let vec = from_iter(repeat);

            vec.foo_bar();
        }
        "#,
        expect![[r#"
            225..229 'iter': T
            244..246 '{}': Vec<A>
            258..402 '{     ...r(); }': ()
            268..273 'inner': Map<impl Fn(&'? f64) -> f64>
            276..300 'Map { ... 0.0 }': Map<impl Fn(&'? f64) -> f64>
            285..298 '|_: &f64| 0.0': impl Fn(&'? f64) -> f64
            286..287 '_': &'? f64
            295..298 '0.0': f64
            311..317 'repeat': Repeat<Map<impl Fn(&'? f64) -> f64>>
            320..345 'Repeat...nner }': Repeat<Map<impl Fn(&'? f64) -> f64>>
            338..343 'inner': Map<impl Fn(&'? f64) -> f64>
            356..359 'vec': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
            362..371 'from_iter': fn from_iter<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>, Repeat<Map<impl Fn(&'? f64) -> f64>>>(Repeat<Map<impl Fn(&'? f64) -> f64>>) -> Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
            362..379 'from_i...epeat)': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
            372..378 'repeat': Repeat<Map<impl Fn(&'? f64) -> f64>>
            386..389 'vec': Vec<IntoIterator::Item<Repeat<Map<impl Fn(&'? f64) -> f64>>>>
            386..399 'vec.foo_bar()': {unknown}
        "#]],
    );
}

#[test]
fn issue_6628() {
    check_infer(
        r#"
//- minicore: fn
struct S<T>();
impl<T> S<T> {
    fn f(&self, _t: T) {}
    fn g<F: FnOnce(&T)>(&self, _f: F) {}
}
fn main() {
    let s = S();
    s.g(|_x| {});
    s.f(10);
}
"#,
        expect![[r#"
            40..44 'self': &'? S<T>
            46..48 '_t': T
            53..55 '{}': ()
            81..85 'self': &'? S<T>
            87..89 '_f': F
            94..96 '{}': ()
            109..160 '{     ...10); }': ()
            119..120 's': S<i32>
            123..124 'S': fn S<i32>() -> S<i32>
            123..126 'S()': S<i32>
            132..133 's': S<i32>
            132..144 's.g(|_x| {})': ()
            136..143 '|_x| {}': impl FnOnce(&'? i32)
            137..139 '_x': &'? i32
            141..143 '{}': ()
            150..151 's': S<i32>
            150..157 's.f(10)': ()
            154..156 '10': i32
        "#]],
    );
}

#[test]
fn issue_6852() {
    check_infer(
        r#"
//- minicore: deref
use core::ops::Deref;

struct BufWriter {}

struct Mutex<T> {}
struct MutexGuard<'a, T> {}
impl<T> Mutex<T> {
    fn lock(&self) -> MutexGuard<'_, T> {}
}
impl<'a, T: 'a> Deref for MutexGuard<'a, T> {
    type Target = T;
}
fn flush(&self) {
    let w: &Mutex<BufWriter>;
    *(w.lock());
}
"#,
        expect![[r#"
            123..127 'self': &'? Mutex<T>
            150..152 '{}': MutexGuard<'?, T>
            234..238 'self': &'? {unknown}
            240..290 '{     ...()); }': ()
            250..251 'w': &'? Mutex<BufWriter>
            276..287 '*(w.lock())': BufWriter
            278..279 'w': &'? Mutex<BufWriter>
            278..286 'w.lock()': MutexGuard<'?, BufWriter>
        "#]],
    );
}

#[test]
fn param_overrides_fn() {
    check_types(
        r#"
        fn example(example: i32) {
            fn f() {}
            example;
          //^^^^^^^ i32
        }
        "#,
    )
}

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

    fn deref(&self) -> &Self::Target {
        loop {}
    }
}

trait Iterator {
    type Item;
}

pub struct Iter<'a, T: 'a> {
    inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
}

trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
    fn clone_box(&self);
}

fn clone_iter<T>(s: Iter<T>) {
    s.inner.clone_box();
  //^^^^^^^^^^^^^^^^^^^ ()
}
"#,
    )
}

#[test]
fn issue_8686() {
    check_infer(
        r#"
pub trait Try: FromResidual {
    type Output;
    type Residual;
}
pub trait FromResidual<R = <Self as Try>::Residual> {
     fn from_residual(residual: R) -> Self;
}

struct ControlFlow<B, C>;
impl<B, C> Try for ControlFlow<B, C> {
    type Output = C;
    type Residual = ControlFlow<B, !>;
}
impl<B, C> FromResidual for ControlFlow<B, C> {
    fn from_residual(r: ControlFlow<B, !>) -> Self { ControlFlow }
}

fn test() {
    ControlFlow::from_residual(ControlFlow::<u32, !>);
}
        "#,
        expect![[r#"
            144..152 'residual': R
            365..366 'r': ControlFlow<B, !>
            395..410 '{ ControlFlow }': ControlFlow<B, C>
            397..408 'ControlFlow': ControlFlow<B, C>
            424..482 '{     ...!>); }': ()
            430..456 'Contro...sidual': fn from_residual<ControlFlow<u32, {unknown}>, ControlFlow<u32, !>>(ControlFlow<u32, !>) -> ControlFlow<u32, {unknown}>
            430..479 'Contro...2, !>)': ControlFlow<u32, {unknown}>
            457..478 'Contro...32, !>': ControlFlow<u32, !>
        "#]],
    );
}

#[test]
fn cfg_tail() {
    // https://github.com/rust-lang/rust-analyzer/issues/8378
    check_infer(
        r#"
        fn fake_tail(){
            { "first" }
            #[cfg(never)] 9
        }
        fn multiple_fake(){
            { "fake" }
            { "fake" }
            { "second" }
            #[cfg(never)] { 11 }
            #[cfg(never)] 12;
            #[cfg(never)] 13
        }
        fn no_normal_tail(){
            { "third" }
            #[cfg(never)] 14;
            #[cfg(never)] 15;
        }
        fn no_actual_tail(){
            { "fourth" };
            #[cfg(never)] 14;
            #[cfg(never)] 15
        }
        "#,
        expect![[r#"
            14..53 '{     ...)] 9 }': ()
            20..31 '{ "first" }': ()
            22..29 '"first"': &'static str
            72..190 '{     ...] 13 }': ()
            78..88 '{ "fake" }': ()
            80..86 '"fake"': &'static str
            93..103 '{ "fake" }': ()
            95..101 '"fake"': &'static str
            108..120 '{ "second" }': ()
            110..118 '"second"': &'static str
            210..273 '{     ... 15; }': ()
            216..227 '{ "third" }': ()
            218..225 '"third"': &'static str
            293..357 '{     ...] 15 }': ()
            299..311 '{ "fourth" }': &'static str
            301..309 '"fourth"': &'static str
        "#]],
    )
}

#[test]
fn impl_trait_in_option_9530() {
    check_types(
        r#"
//- minicore: sized
struct Option<T>;
impl<T> Option<T> {
    fn unwrap(self) -> T { loop {} }
}
fn make() -> Option<impl Copy> { Option }
trait Copy {}
fn test() {
    let o = make();
    o.unwrap();
  //^^^^^^^^^^ impl Copy
}
        "#,
    )
}

#[test]
fn bare_dyn_trait_binders_9639() {
    check_no_mismatches(
        r#"
//- minicore: fn, coerce_unsized, dispatch_from_dyn
fn infix_parse<T, S>(_state: S, _level_code: &Fn(S)) -> T {
    loop {}
}

fn parse_a_rule() {
    infix_parse((), &(|_recurse| ()))
}
        "#,
    )
}

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

fn map<T, U>(o: Option<T>, f: impl FnOnce(T) -> U) -> Option<U> { loop {} }

fn test() {
    let o = Some(Some(2));
    map(o, |s| map(s, |x| x));
                    // ^ i32
}
        "#,
    );
}

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

fn map<T, U>(o: Option<T>, f: impl FnOnce(T) -> U) -> Option<U> { loop {} }
struct S {
    field: u32
}

fn test() {
    let o = Some(S { field: 2 });
    let _: Option<()> = map(o, |s| { s.field; });
                                  // ^^^^^^^ u32
}
        "#,
    );
}

#[test]
fn coerce_diesel_panic() {
    check_no_mismatches(
        r#"
//- minicore: option

trait TypeMetadata {
    type MetadataLookup;
}

pub struct Output<'a, T, DB>
where
    DB: TypeMetadata,
    DB::MetadataLookup: 'a,
{
    out: T,
    metadata_lookup: Option<&'a DB::MetadataLookup>,
}

impl<'a, T, DB: TypeMetadata> Output<'a, T, DB> {
    pub fn new(out: T, metadata_lookup: &'a DB::MetadataLookup) -> Self {
        Output {
            out,
            metadata_lookup: Some(metadata_lookup),
        }
    }
}
        "#,
    );
}

#[test]
fn bitslice_panic() {
    check_no_mismatches(
        r#"
//- minicore: option, deref

pub trait BitView {
    type Store;
}

pub struct Lsb0;

pub struct BitArray<V: BitView> { }

pub struct BitSlice<T> { }

impl<V: BitView> core::ops::Deref for BitArray<V> {
    type Target = BitSlice<V::Store>;
}

impl<T> BitSlice<T> {
    pub fn split_first(&self) -> Option<(T, &Self)> { loop {} }
}

fn multiexp_inner() {
    let exp: &BitArray<Foo>;
    exp.split_first();
}
        "#,
    );
}

#[test]
fn macro_expands_to_impl_trait() {
    check_no_mismatches(
        r#"
trait Foo {}

macro_rules! ty {
    () => {
        impl Foo
    }
}

fn foo(_: ty!()) {}

fn bar() {
    foo(());
}
    "#,
    )
}

#[test]
fn nested_macro_in_fn_params() {
    check_no_mismatches(
        r#"
macro_rules! U32Inner {
    () => {
        u32
    };
}

macro_rules! U32 {
    () => {
        U32Inner!()
    };
}

fn mamba(a: U32!(), p: u32) -> u32 {
    a
}
    "#,
    )
}

#[test]
fn for_loop_block_expr_iterable() {
    check_infer(
        r#"
//- minicore: iterator
fn test() {
    for _ in { let x = 0; } {
        let y = 0;
    }
}
        "#,
        expect![[r#"
            10..68 '{     ...   } }': ()
            16..66 'for _ ...     }': fn into_iter<()>(()) -> <() as IntoIterator>::IntoIter
            16..66 'for _ ...     }': IntoIterator::IntoIter<()>
            16..66 'for _ ...     }': !
            16..66 'for _ ...     }': IntoIterator::IntoIter<()>
            16..66 'for _ ...     }': &'? mut IntoIterator::IntoIter<()>
            16..66 'for _ ...     }': fn next<IntoIterator::IntoIter<()>>(&'? mut IntoIterator::IntoIter<()>) -> Option<<IntoIterator::IntoIter<()> as Iterator>::Item>
            16..66 'for _ ...     }': Option<IntoIterator::Item<()>>
            16..66 'for _ ...     }': ()
            16..66 'for _ ...     }': ()
            16..66 'for _ ...     }': ()
            16..66 'for _ ...     }': ()
            20..21 '_': IntoIterator::Item<()>
            25..39 '{ let x = 0; }': ()
            31..32 'x': i32
            35..36 '0': i32
            40..66 '{     ...     }': ()
            54..55 'y': i32
            58..59 '0': i32
        "#]],
    );
}

#[test]
fn while_loop_block_expr_iterable() {
    check_infer(
        r#"
fn test() {
    while { true } {
        let y = 0;
    }
}
        "#,
        expect![[r#"
            10..59 '{     ...   } }': ()
            16..57 'while ...     }': !
            16..57 'while ...     }': ()
            16..57 'while ...     }': ()
            22..30 '{ true }': bool
            24..28 'true': bool
            31..57 '{     ...     }': ()
            45..46 'y': i32
            49..50 '0': i32
        "#]],
    );
}

#[test]
fn bug_11242() {
    // FIXME: wrong, should be u32
    check_types(
        r#"
fn foo<A, B>()
where
    A: IntoIterator<Item = u32>,
    B: IntoIterator<Item = usize>,
{
    let _x: <A as IntoIterator>::Item;
     // ^^ {unknown}
}

pub trait Iterator {
    type Item;
}

pub trait IntoIterator {
    type Item;
    type IntoIter: Iterator<Item = Self::Item>;
}

impl<I: Iterator> IntoIterator for I {
    type Item = I::Item;
    type IntoIter = I;
}
"#,
    );
}

#[test]
fn bug_11659() {
    check_no_mismatches(
        r#"
struct LinkArray<const N: usize, LD>(LD);
fn f<const N: usize, LD>(x: LD) -> LinkArray<N, LD> {
    let r = LinkArray::<N, LD>(x);
    r
}

fn test() {
    let x = f::<2, i32>(5);
    let y = LinkArray::<52, LinkArray<2, i32>>(x);
}
        "#,
    );
    check_no_mismatches(
        r#"
struct LinkArray<LD, const N: usize>(LD);
fn f<const N: usize, LD>(x: LD) -> LinkArray<LD, N> {
    let r = LinkArray::<LD, N>(x);
    r
}

fn test() {
    let x = f::<i32, 2>(5);
    let y = LinkArray::<LinkArray<i32, 2>, 52>(x);
}
        "#,
    );
}

#[test]
fn const_generic_error_tolerance() {
    check_no_mismatches(
        r#"
#[lang = "sized"]
pub trait Sized {}

struct CT<const N: usize, T>(T);
struct TC<T, const N: usize>(T);
fn f<const N: usize, T>(x: T) -> (CT<N, T>, TC<T, N>) {
    let l = CT::<N, T>(x);
    let r = TC::<N, T>(x);
    (l, r)
}

trait TR1<const N: usize>;
trait TR2<const N: usize>;

impl<const N: usize, T> TR1<N> for CT<N, T>;
impl<const N: usize, T> TR1<5> for TC<T, N>;
impl<const N: usize, T> TR2<N> for CT<T, N>;

trait TR3<const N: usize> {
    fn tr3(&self) -> &Self;
}

impl<const N: usize, T> TR3<5> for TC<T, N> {
    fn tr3(&self) -> &Self {
        self
    }
}

impl<const N: usize, T> TR3<Item = 5> for TC<T, N> {}
impl<const N: usize, T> TR3<T> for TC<T, N> {}

fn impl_trait<const N: usize>(inp: impl TR1<N>) {}
fn dyn_trait<const N: usize>(inp: &dyn TR2<N>) {}
fn impl_trait_bad<'a, const N: usize>(inp: impl TR1<i32>) -> impl TR1<'a, i32> {}
fn impl_trait_very_bad<const N: usize>(inp: impl TR1<Item = i32>) -> impl TR1<'a, Item = i32, 5, Foo = N> {}

fn test() {
    f::<2, i32>(5);
    f::<2, 2>(5);
    f(5);
    f::<i32>(5);
    CT::<52, CT<2, i32>>(x);
    CT::<CT<2, i32>>(x);
    impl_trait_bad(5);
    impl_trait_bad(12);
    TR3<5>::tr3();
    TR3<{ 2+3 }>::tr3();
    TC::<i32, 10>(5).tr3();
    TC::<i32, 20>(5).tr3();
    TC::<i32, i32>(5).tr3();
    TC::<i32, { 7 + 3 }>(5).tr3();
}
        "#,
    );
}

#[test]
fn const_generic_impl_trait() {
    check_no_mismatches(
        r#"
        //- minicore: from

        struct Foo<T, const M: usize>;

        trait Tr<T> {
            fn f(T) -> Self;
        }

        impl<T, const M: usize> Tr<[T; M]> for Foo<T, M> {
            fn f(_: [T; M]) -> Self {
                Self
            }
        }

        fn test() {
            Foo::f([1, 2, 7, 10]);
        }
        "#,
    );
}

#[test]
fn nalgebra_factorial() {
    check_no_mismatches(
        r#"
        const FACTORIAL: [u128; 4] = [1, 1, 2, 6];

        fn factorial(n: usize) -> u128 {
            match FACTORIAL.get(n) {
                Some(f) => *f,
                None => panic!("{}! is greater than u128::MAX", n),
            }
        }
        "#,
    )
}

#[test]
fn regression_11688_1() {
    check_no_mismatches(
        r#"
        pub struct Buffer<T>(T);
        type Writer = Buffer<u8>;
        impl<T> Buffer<T> {
            fn extend_from_array<const N: usize>(&mut self, xs: &[T; N]) {
                loop {}
            }
        }
        trait Encode<S> {
            fn encode(self, w: &mut Writer, s: &mut S);
        }
        impl<S> Encode<S> for u8 {
            fn encode(self, w: &mut Writer, _: &mut S) {
                w.extend_from_array(&self.to_le_bytes());
            }
        }
        "#,
    );
}

#[test]
fn regression_11688_2() {
    check_types(
        r#"
        union MaybeUninit<T> {
            uninit: (),
            value: T,
        }

        impl<T> MaybeUninit<T> {
            fn uninit_array<const LEN: usize>() -> [Self; LEN] {
                loop {}
            }
        }

        fn main() {
            let x = MaybeUninit::<i32>::uninit_array::<1>();
              //^ [MaybeUninit<i32>; 1]
        }
        "#,
    );
}

#[test]
fn regression_11688_3() {
    check_types(
        r#"
        //- minicore: iterator
        struct Ar<T, const N: u8>(T);
        fn f<const LEN: usize, T, const BASE: u8>(
            num_zeros: usize,
        ) -> &dyn Iterator<Item = [Ar<T, BASE>; LEN]> {
            loop {}
        }
        fn dynamic_programming() {
            let board = f::<9, u8, 7>(1).next();
              //^^^^^ Option<[Ar<u8, 7>; 9]>
        }
        "#,
    );
}

#[test]
fn regression_11688_4() {
    check_types(
        r#"
        trait Bar<const C: usize> {
            fn baz(&self) -> [i32; C];
        }

        fn foo(x: &dyn Bar<2>) {
            x.baz();
          //^^^^^^^ [i32; 2]
        }
        "#,
    )
}

#[test]
fn gat_crash_1() {
    check_no_mismatches(
        r#"
trait ATrait {}

trait Crash {
    type Member<const N: usize>: ATrait;
    fn new<const N: usize>() -> Self::Member<N>;
}

fn test<T: Crash>() {
    T::new();
}
"#,
    );
}

#[test]
fn gat_crash_2() {
    check_no_mismatches(
        r#"
pub struct InlineStorage {}

pub struct InlineStorageHandle<T: ?Sized> {}

pub unsafe trait Storage {
    type Handle<T: ?Sized>;
    fn create<T: ?Sized>() -> Self::Handle<T>;
}

unsafe impl Storage for InlineStorage {
    type Handle<T: ?Sized> = InlineStorageHandle<T>;
}
"#,
    );
}

#[test]
fn gat_crash_3() {
    check_no_mismatches(
        r#"
trait Collection {
type Item;
type Member<T>: Collection<Item = T>;
fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>;
}
struct ConstGen<T, const N: usize> {
data: [T; N],
}
impl<T, const N: usize> Collection for ConstGen<T, N> {
type Item = T;
type Member<U> = ConstGen<U, N>;
}
    "#,
    );
}

#[test]
fn cfgd_out_self_param() {
    cov_mark::check!(cfgd_out_self_param);
    check_no_mismatches(
        r#"
struct S;
impl S {
    fn f(#[cfg(never)] &self) {}
}

fn f(s: S) {
    s.f();
}
"#,
    );
}

#[test]
fn tuple_struct_pattern_with_unmatched_args_crash() {
    check_infer(
        r#"
struct S(usize);
fn main() {
    let S(.., a, b) = S(1);
    let (.., a, b) = (1,);
}
        "#,
        expect![[r#"
            27..85 '{     ...1,); }': ()
            37..48 'S(.., a, b)': S
            43..44 'a': usize
            46..47 'b': {unknown}
            51..52 'S': fn S(usize) -> S
            51..55 'S(1)': S
            53..54 '1': usize
            65..75 '(.., a, b)': (i32, {unknown})
            70..71 'a': i32
            73..74 'b': {unknown}
            78..82 '(1,)': (i32,)
            79..80 '1': i32
        "#]],
    );
}

#[test]
fn trailing_empty_macro() {
    check_no_mismatches(
        r#"
macro_rules! m2 {
    ($($t:tt)*) => {$($t)*};
}

fn macrostmts() -> u8 {
    m2! { 0 }
    m2! {}
}
    "#,
    );
}

#[test]
fn dyn_with_unresolved_trait() {
    check_types(
        r#"
fn foo(a: &dyn DoesNotExist) {
    a.bar();
  //^&'? {unknown}
}
        "#,
    );
}

#[test]
fn self_assoc_with_const_generics_crash() {
    check_no_mismatches(
        r#"
trait Trait { type Item; }
impl<T, const N: usize> Trait for [T; N] {
    type Item = ();
    fn f<U>(_: Self::Item) {}
}
        "#,
    );
}

#[test]
fn unsize_array_with_inference_variable() {
    check_types(
        r#"
//- minicore: try, slice
use core::ops::ControlFlow;
fn foo() -> ControlFlow<(), [usize; 1]> { loop {} }
fn bar() -> ControlFlow<(), ()> {
    let a = foo()?.len();
      //^ usize
    ControlFlow::Continue(())
}
"#,
    );
}

#[test]
fn assoc_type_shorthand_with_gats_in_binders() {
    // c.f. test `issue_4885()`
    check_no_mismatches(
        r#"
trait Gats {
    type Assoc<T>;
}
trait Foo<T> {}

struct Bar<'a, B: Gats, A> {
    field: &'a dyn Foo<B::Assoc<A>>,
}

fn foo(b: Bar) {
    let _ = b.field;
}
"#,
    );
}

#[test]
fn regression_14305() {
    check_no_mismatches(
        r#"
//- minicore: add
trait Tr {}
impl Tr for [u8; C] {}
const C: usize = 2 + 2;
"#,
    );
}

#[test]
fn regression_14456() {
    check_types(
        r#"
//- minicore: future
async fn x() {}
fn f() {
    let fut = x();
    let t = [0u8; { let a = 2 + 2; a }];
      //^ [u8; 4]
}
"#,
    );
}

#[test]
fn regression_14164() {
    check_types(
        r#"
trait Rec {
    type K;
    type Rebind<Tok>: Rec<K = Tok>;
}

trait Expr<K> {
    type Part: Rec<K = K>;
    fn foo(_: <Self::Part as Rec>::Rebind<i32>) {}
}

struct Head<K>(K);
impl<K> Rec for Head<K> {
    type K = K;
    type Rebind<Tok> = Head<Tok>;
}

fn test<E>()
where
    E: Expr<usize, Part = Head<usize>>,
{
    let head;
      //^^^^ Head<i32>
    E::foo(head);
}
"#,
    );
}

#[test]
fn match_ergonomics_with_binding_modes_interaction() {
    check_types(
        r"
enum E { A }
fn foo() {
    match &E::A {
        b @ (x @ E::A | x) => {
            b;
          //^ &'? E
            x;
          //^ &'? E
        }
    }
}",
    );
}

#[test]
fn regression_14844() {
    check_no_mismatches(
        r#"
pub type Ty = Unknown;

pub struct Inner<T>();

pub struct Outer {
    pub inner: Inner<Ty>,
}

fn main() {
    _ = Outer {
        inner: Inner::<i32>(),
    };
}
        "#,
    );
    check_no_mismatches(
        r#"
pub const ONE: usize = 1;

pub struct Inner<const P: usize>();

pub struct Outer {
    pub inner: Inner<ONE>,
}

fn main() {
    _ = Outer {
        inner: Inner::<1>(),
    };
}
        "#,
    );
    check_no_mismatches(
        r#"
pub const ONE: usize = unknown();

pub struct Inner<const P: usize>();

pub struct Outer {
    pub inner: Inner<ONE>,
}

fn main() {
    _ = Outer {
        inner: Inner::<1>(),
    };
}
        "#,
    );
    check_no_mismatches(
        r#"
pub const N: usize = 2 + 2;

fn f(t: [u8; N]) {}

fn main() {
    let a = [1, 2, 3, 4];
    f(a);
    let b = [1; 4];
    let c: [u8; N] = b;
    let d = [1; N];
    let e: [u8; N] = d;
    let f = [1; N];
    let g = match f {
        [a, b, c, d] => a + b + c + d,
    };
}
        "#,
    );
}

#[test]
fn regression_14844_2() {
    check_no_mismatches(
        r#"
//- minicore: fn
pub const ONE: usize = 1;

pub type MyInner = Inner<ONE>;

pub struct Inner<const P: usize>();

impl Inner<1> {
    fn map<F>(&self, func: F) -> bool
    where
        F: Fn(&MyInner) -> bool,
    {
        func(self)
    }
}
        "#,
    );
}

#[test]
fn dont_crash_on_slice_unsizing() {
    check_no_mismatches(
        r#"
//- minicore: slice, unsize, coerce_unsized
trait Tr {
    fn f(self);
}

impl Tr for [i32] {
    fn f(self) {
        let t;
        x(t);
    }
}

fn x(a: [i32; 4]) {
    let b = a.f();
}
        "#,
    );
}

#[test]
fn dont_unify_on_casts() {
    // #15246
    check_types(
        r#"
//- minicore: sized
fn unify(_: [bool; 1]) {}
fn casted(_: *const bool) {}
fn default<T>() -> T { loop {} }

fn test() {
    let foo = default();
      //^^^ [bool; 1]

    casted(&foo as *const _);
    unify(foo);
}
"#,
    );
}

#[test]
fn rustc_test_issue_52437() {
    check_types(
        r#"
    //- minicore: sized
    fn main() {
        let x = [(); &(&'static: loop { |x| {}; }) as *const _ as usize]
          //^ [(); _]
    }
    "#,
    );
}

#[test]
fn incorrect_variant_form_through_alias_caught() {
    check_types(
        r#"
enum Enum { Braced {}, Unit, Tuple() }
type Alias = Enum;

fn main() {
    Alias::Braced;
  //^^^^^^^^^^^^^ {unknown}
    let Alias::Braced = loop {};
      //^^^^^^^^^^^^^ !
  let Alias::Braced(..) = loop {};
    //^^^^^^^^^^^^^^^^^ Enum

    Alias::Unit();
  //^^^^^^^^^^^^^ {unknown}
    Alias::Unit{};
  //^^^^^^^^^^^^^ Enum
    let Alias::Unit() = loop {};
      //^^^^^^^^^^^^^ Enum
    let Alias::Unit{} = loop {};
      //^^^^^^^^^^^^^ Enum
}
"#,
    )
}

#[test]
fn cfg_first_trait_param_16141() {
    check_no_mismatches(
        r#"
//- minicore: sized, coerce_unsized
trait Bar {
    fn bar(&self) {}
}

impl<#[cfg(feature = "a-feature")] A> Bar for (){}
"#,
    )
}

#[test]
fn nested_anon_generics_and_where_bounds_17173() {
    check_types(
        r#"
//- minicore: sized, fn
pub trait Lookup {
    type Data;
    fn lookup(&self) -> Self::Data;
}
pub trait ItemTreeLoc {
    type Id;
}
fn id_to_generics(id: impl Lookup<Data = impl ItemTreeLoc<Id = ()>>,
                //^^ impl Lookup<Data = impl ItemTreeLoc<Id = ()>>
                enabled_params: impl Fn(),
              //^^^^^^^^^^^^^^  impl Fn()
                )
where
    (): Sized,
{}
"#,
    );
}

#[test]
fn tait_async_stack_overflow_17199() {
    check_types(
        r#"
    //- minicore: fmt, future
    type Foo = impl core::fmt::Debug;

    async fn foo() -> Foo {
        ()
    }

    async fn test() {
        let t = foo().await;
         // ^ impl Debug
    }
"#,
    );
}

#[test]
fn lifetime_params_move_param_defaults() {
    check_types(
        r#"
pub struct Thing<'s, T = u32>;

impl <'s> Thing<'s> {
    pub fn new() -> Thing<'s> {
        Thing
      //^^^^^ Thing<'?, u32>
    }
}

fn main() {
    let scope =
      //^^^^^ &'? Thing<'?, u32>
                &Thing::new();
               //^^^^^^^^^^^^ Thing<'?, u32>
}
"#,
    );
}

#[test]
fn issue_17734() {
    check_types(
        r#"
fn test() {
    let x = S::foo::<'static, &()>(&S);
     // ^ Wrap<'?, ()>
    let x = S::foo::<&()>(&S);
     // ^ Wrap<'?, ()>
    let x = S.foo::<'static, &()>();
     // ^ Wrap<'?, ()>
    let x = S.foo::<&()>();
     // ^ Wrap<'?, ()>
}

struct S;

impl S {
    pub fn foo<'a, T: Trait<'a>>(&'a self) -> T::Proj {
        loop {}
    }
}

struct Wrap<'a, T>(T);
trait Trait<'a> {
    type Proj;
}
impl<'a, T> Trait<'a> for &'a T {
    type Proj = Wrap<'a, T>;
}
"#,
    )
}

#[test]
fn issue_17738() {
    check_types(
        r#"
//- minicore: index
use core::ops::{Index, IndexMut};

struct Foo<K, V>(K, V);

struct Bar;

impl Bar {
    fn bar(&mut self) {}
}

impl<K, V> Foo<K, V> {
    fn new(_v: V) -> Self {
        loop {}
    }
}

impl<K, B, V> Index<B> for Foo<K, V> {
    type Output = V;
    fn index(&self, _index: B) -> &Self::Output {
        loop {}
    }
}

impl<K, V> IndexMut<K> for Foo<K, V> {
    fn index_mut(&mut self, _index: K) -> &mut Self::Output {
        loop {}
    }
}

fn test() {
    let mut t1 = Foo::new(Bar);
     // ^^^^^^ Foo<&'? (), Bar>
    t1[&()] = Bar;

    let mut t2 = Foo::new(Bar);
     // ^^^^^^ Foo<&'? (), Bar>
    t2[&()].bar();
}
"#,
    )
}

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

trait B<T> {}

fn foo<T: B<impl A>>() {}

fn test() {
    let f = foo;
      //^ fn foo<{unknown}>()
}"#,
    );
}

#[test]
fn issue_17866() {
    check_infer(
        r#"
trait T {
    type A;
}

type Foo = <S as T>::A;

fn main() {
    Foo {};
}
"#,
        expect![[r#"
            60..75 '{     Foo {}; }': ()
            66..72 'Foo {}': {unknown}
        "#]],
    );
}

#[test]
fn issue_17711() {
    check_infer(
        r#"
//- minicore: deref
use core::ops::Deref;

struct Struct<'a, T>(&'a T);

trait Trait {}

impl<'a, T: Deref<Target = impl Trait>> Struct<'a, T> {
    fn foo(&self) -> &Self { self }

    fn bar(&self) {
        let _ = self.foo();
    }

}
"#,
        expect![[r#"
            137..141 'self': &'? Struct<'a, T>
            152..160 '{ self }': &'? Struct<'a, T>
            154..158 'self': &'? Struct<'a, T>
            174..178 'self': &'? Struct<'a, T>
            180..215 '{     ...     }': ()
            194..195 '_': &'? Struct<'?, T>
            198..202 'self': &'? Struct<'a, T>
            198..208 'self.foo()': &'? Struct<'?, T>
        "#]],
    );
}

#[test]
fn issue_17767() {
    check_infer(
        r#"
extern "C" {
    type Foo<T>;
}

fn f() -> Foo {}
"#,
        expect![[r#"
            47..49 '{}': Foo
        "#]],
    );
}

#[test]
fn issue_17921() {
    check_infer(
        r#"
//- minicore: future
trait Foo {}
type Bar = impl Foo;

async fn f<A, B, C>() -> Bar {}
"#,
        expect![[r#"
            64..66 '{}': ()
            64..66 '{}': impl Future<Output = ()>
        "#]],
    );
}

#[test]
fn issue_18109() {
    check_infer(
        r#"
//- minicore: option
struct Map<T, U>(T, U);

impl<T, U> Map<T, U> {
    fn new() -> Self { loop {} }
    fn get(&self, _: &T) -> Option<&U> { loop {} }
}

fn test(x: bool) {
    let map = Map::new();
    let _ = match x {
        true => {
            let Some(val) = map.get(&8) else { return };
            *val
        }
        false => return,
        _ => 42,
    };
}
"#,
        expect![[r#"
            69..80 '{ loop {} }': Map<T, U>
            71..78 'loop {}': !
            76..78 '{}': ()
            93..97 'self': &'? Map<T, U>
            99..100 '_': &'? T
            120..131 '{ loop {} }': Option<&'? U>
            122..129 'loop {}': !
            127..129 '{}': ()
            143..144 'x': bool
            152..354 '{     ...  }; }': ()
            162..165 'map': Map<i32, i32>
            168..176 'Map::new': fn new<i32, i32>() -> Map<i32, i32>
            168..178 'Map::new()': Map<i32, i32>
            188..189 '_': i32
            192..351 'match ...     }': i32
            198..199 'x': bool
            210..214 'true': bool
            210..214 'true': bool
            218..303 '{     ...     }': i32
            236..245 'Some(val)': Option<&'? i32>
            241..244 'val': &'? i32
            248..251 'map': Map<i32, i32>
            248..259 'map.get(&8)': Option<&'? i32>
            256..258 '&8': &'? i32
            257..258 '8': i32
            265..275 '{ return }': !
            267..273 'return': !
            289..293 '*val': i32
            290..293 'val': &'? i32
            312..317 'false': bool
            312..317 'false': bool
            321..327 'return': !
            337..338 '_': bool
            342..344 '42': i32
        "#]],
    );
}
