fn infer_await() {
check_types(
r#"
-//- /main.rs crate:main deps:core
+//- minicore: future
struct IntFuture;
-impl Future for IntFuture {
+impl core::future::Future for IntFuture {
type Output = u64;
}
let v = r.await;
v;
} //^ u64
-
-//- /core.rs crate:core
-#[prelude_import] use future::*;
-mod future {
- #[lang = "future_trait"]
- trait Future {
- type Output;
- }
-}
"#,
);
}
fn infer_async() {
check_types(
r#"
-//- /main.rs crate:main deps:core
-async fn foo() -> u64 {
- 128
-}
+//- minicore: future
+async fn foo() -> u64 { 128 }
fn test() {
let r = foo();
let v = r.await;
v;
} //^ u64
-
-//- /core.rs crate:core
-#[prelude_import] use future::*;
-mod future {
- #[lang = "future_trait"]
- trait Future {
- type Output;
- }
-}
"#,
);
}
fn infer_desugar_async() {
check_types(
r#"
-//- /main.rs crate:main deps:core
-async fn foo() -> u64 {
- 128
-}
+//- minicore: future
+async fn foo() -> u64 { 128 }
fn test() {
let r = foo();
r;
} //^ impl Future<Output = u64>
-
-//- /core.rs crate:core
-#[prelude_import] use future::*;
-mod future {
- trait Future {
- type Output;
- }
-}
-
"#,
);
}
fn infer_async_block() {
check_types(
r#"
-//- /main.rs crate:main deps:core
+//- minicore: future, option
async fn test() {
let a = async { 42 };
a;
b;
// ^ ()
let c = async {
- let y = Option::None;
+ let y = None;
y
// ^ Option<u64>
};
c;
// ^ impl Future<Output = Option<u64>>
}
+"#,
+ );
+}
-enum Option<T> { None, Some(T) }
+#[test]
+fn infer_try() {
+ check_types(
+ r#"
+//- /main.rs crate:main deps:core
+fn test() {
+ let r: Result<i32, u64> = Result::Ok(1);
+ let v = r?;
+ v;
+} //^ i32
//- /core.rs crate:core
-#[prelude_import] use future::*;
-mod future {
- #[lang = "future_trait"]
- trait Future {
- type Output;
+pub mod ops {
+ pub trait Try {
+ type Ok;
+ type Error;
+ }
+}
+
+pub mod result {
+ pub enum Result<O, E> {
+ Ok(O),
+ Err(E)
+ }
+
+ impl<O, E> crate::ops::Try for Result<O, E> {
+ type Ok = O;
+ type Error = E;
}
}
+pub mod prelude {
+ pub mod rust_2018 {
+ pub use crate::{result::*, ops::*};
+ }
+}
"#,
);
}
#[test]
-fn infer_try() {
+fn infer_try_trait_v2() {
check_types(
r#"
//- /main.rs crate:main deps:core
} //^ i32
//- /core.rs crate:core
-#[prelude_import] use ops::*;
mod ops {
- trait Try {
- type Ok;
- type Error;
+ mod try_trait {
+ pub trait Try: FromResidual {
+ type Output;
+ type Residual;
+ }
+ pub trait FromResidual<R = <Self as Try>::Residual> {}
}
+
+ pub use self::try_trait::FromResidual;
+ pub use self::try_trait::Try;
+}
+
+mov convert {
+ pub trait From<T> {}
+ impl<T> From<T> for T {}
}
-#[prelude_import] use result::*;
-mod result {
- enum Result<O, E> {
+pub mod result {
+ use crate::convert::From;
+ use crate::ops::{Try, FromResidual};
+
+ pub enum Infallible {}
+ pub enum Result<O, E> {
Ok(O),
Err(E)
}
- impl<O, E> crate::ops::Try for Result<O, E> {
- type Ok = O;
- type Error = E;
+ impl<O, E> Try for Result<O, E> {
+ type Output = O;
+ type Error = Result<Infallible, E>;
+ }
+
+ impl<T, E, F: From<E>> FromResidual<Result<Infallible, E>> for Result<T, F> {}
+}
+
+pub mod prelude {
+ pub mod rust_2018 {
+ pub use crate::result::*;
}
}
"#,
check_types(
r#"
//- /main.rs crate:main deps:core,alloc
+#![no_std]
use alloc::collections::Vec;
fn test() {
}
//- /core.rs crate:core
-#[prelude_import] use iter::*;
-mod iter {
- trait IntoIterator {
+pub mod iter {
+ pub trait IntoIterator {
type Item;
}
}
+pub mod prelude {
+ pub mod rust_2018 {
+ pub use crate::iter::*;
+ }
+}
//- /alloc.rs crate:alloc deps:core
+#![no_std]
mod collections {
struct Vec<T> {}
impl<T> Vec<T> {
fn infer_from_bound_1() {
check_infer(
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);
- foo(s);
- }
- "#,
+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);
+ foo(s);
+}"#,
expect![[r#"
85..86 't': T
91..93 '{}': ()
fn infer_from_bound_2() {
check_infer(
r#"
- trait Trait<T> {}
- struct S<T>(T);
- impl<U> Trait<U> for S<U> {}
- fn foo<U, T: Trait<U>>(t: T) -> U {}
- fn test() {
- let s = S(unknown);
- let x: u32 = foo(s);
- }
- "#,
+trait Trait<T> {}
+struct S<T>(T);
+impl<U> Trait<U> for S<U> {}
+fn foo<U, T: Trait<U>>(t: T) -> U {}
+fn test() {
+ let s = S(unknown);
+ let x: u32 = foo(s);
+}"#,
expect![[r#"
86..87 't': T
97..99 '{}': ()
cov_mark::check!(trait_self_implements_self);
check_infer(
r#"
- trait Trait {
- fn foo(&self) -> i64;
- fn bar(&self) -> {
- let x = self.foo();
- }
- }
- "#,
+trait Trait {
+ fn foo(&self) -> i64;
+ fn bar(&self) -> {
+ let x = self.foo();
+ }
+}"#,
expect![[r#"
26..30 'self': &Self
52..56 'self': &Self
fn trait_default_method_self_bound_implements_super_trait() {
check_infer(
r#"
- trait SuperTrait {
- fn foo(&self) -> i64;
- }
- trait Trait: SuperTrait {
- fn bar(&self) -> {
- let x = self.foo();
- }
- }
- "#,
+trait SuperTrait {
+ fn foo(&self) -> i64;
+}
+trait Trait: SuperTrait {
+ fn bar(&self) -> {
+ let x = self.foo();
+ }
+}"#,
expect![[r#"
31..35 'self': &Self
85..89 'self': &Self
fn infer_project_associated_type() {
check_infer(
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;
- let y: <T as Iterable>::Item = no_matter;
- let z: T::Item = no_matter;
- let a: <T>::Item = no_matter;
- }
- "#,
+trait Iterable {
+ type Item;
+}
+struct S;
+impl Iterable for S { type Item = u32; }
+fn test<T: Iterable>() {
+ let x: <S as Iterable>::Item = 1;
+ let y: <T as Iterable>::Item = no_matter;
+ let z: T::Item = no_matter;
+ let a: <T>::Item = no_matter;
+}"#,
expect![[r#"
108..261 '{ ...ter; }': ()
118..119 'x': u32
fn infer_return_associated_type() {
check_infer(
r#"
- trait Iterable {
- type Item;
- }
- struct S;
- impl Iterable for S { type Item = u32; }
- fn foo1<T: Iterable>(t: T) -> T::Item {}
- fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
- fn foo3<T: Iterable>(t: T) -> <T>::Item {}
- fn test() {
- let x = foo1(S);
- let y = foo2(S);
- let z = foo3(S);
- }
- "#,
+trait Iterable {
+ type Item;
+}
+struct S;
+impl Iterable for S { type Item = u32; }
+fn foo1<T: Iterable>(t: T) -> T::Item {}
+fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
+fn foo3<T: Iterable>(t: T) -> <T>::Item {}
+fn test() {
+ let x = foo1(S);
+ let y = foo2(S);
+ let z = foo3(S);
+}"#,
expect![[r#"
106..107 't': T
123..125 '{}': ()
fn infer_associated_type_bound() {
check_infer(
r#"
- trait Iterable {
- type Item;
- }
- fn test<T: Iterable<Item=u32>>() {
- let y: T::Item = unknown;
- }
- "#,
+trait Iterable {
+ type Item;
+}
+fn test<T: Iterable<Item=u32>>() {
+ let y: T::Item = unknown;
+}"#,
expect![[r#"
67..100 '{ ...own; }': ()
77..78 'y': u32
fn infer_const_body() {
check_infer(
r#"
- const A: u32 = 1 + 1;
- static B: u64 = { let x = 1; x };
- "#,
+const A: u32 = 1 + 1;
+static B: u64 = { let x = 1; x };"#,
expect![[r#"
15..16 '1': u32
15..20 '1 + 1': u32
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
- }
- "#,
+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
fn tuple_struct_with_fn() {
check_infer(
r#"
- struct S(fn(u32) -> u64);
- fn test() -> u64 {
- let a = S(|i| 2*i);
- let b = a.0(4);
- a.0(2)
- }
- "#,
+struct S(fn(u32) -> u64);
+fn test() -> u64 {
+ let a = S(|i| 2*i);
+ let b = a.0(4);
+ a.0(2)
+}"#,
expect![[r#"
43..101 '{ ...0(2) }': u64
53..54 'a': S
expect![[r#"
10..26 '{ &mut...[2]; }': ()
12..23 '&mut [9][2]': &mut {unknown}
- 17..20 '[9]': [i32; _]
+ 17..20 '[9]': [i32; 1]
17..23 '[9][2]': {unknown}
18..19 '9': i32
21..22 '2': i32
fn deref_trait() {
check_types(
r#"
-#[lang = "deref"]
-trait Deref {
- type Target;
- fn deref(&self) -> &Self::Target;
-}
-
+//- minicore: deref
struct Arc<T>;
-impl<T> Deref for Arc<T> {
+impl<T> core::ops::Deref for Arc<T> {
type Target = T;
}
fn deref_trait_with_inference_var() {
check_types(
r#"
-//- /main.rs
-#[lang = "deref"]
-trait Deref {
- type Target;
- fn deref(&self) -> &Self::Target;
-}
-
+//- minicore: deref
struct Arc<T>;
fn new_arc<T>() -> Arc<T> {}
-impl<T> Deref for Arc<T> {
+impl<T> core::ops::Deref for Arc<T> {
type Target = T;
}
fn deref_trait_infinite_recursion() {
check_types(
r#"
-#[lang = "deref"]
-trait Deref {
- type Target;
- fn deref(&self) -> &Self::Target;
-}
-
+//- minicore: deref
struct S;
-impl Deref for S {
+impl core::ops::Deref for S {
type Target = S;
}
fn deref_trait_with_question_mark_size() {
check_types(
r#"
-#[lang = "deref"]
-trait Deref {
- type Target;
- fn deref(&self) -> &Self::Target;
-}
-
+//- minicore: deref
struct Arc<T>;
-impl<T> Deref for Arc<T> {
+impl<T: ?Sized> core::ops::Deref for Arc<T> {
type Target = T;
}
fn argument_impl_trait() {
check_infer_with_mismatches(
r#"
- 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();
- }
- "#,
+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
fn argument_impl_trait_type_args_1() {
check_infer_with_mismatches(
r#"
- 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
- }
- "#,
+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
fn argument_impl_trait_type_args_2() {
check_infer_with_mismatches(
r#"
- 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 {} }
- }
+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
- }
- "#,
+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
fn argument_impl_trait_to_fn_pointer() {
check_infer_with_mismatches(
r#"
- trait Trait {}
- fn foo(x: impl Trait) { loop {} }
- struct S;
- impl Trait for S {}
+trait Trait {}
+fn foo(x: impl Trait) { loop {} }
+struct S;
+impl Trait for S {}
- fn test() {
- let f: fn(S) -> () = foo;
- }
- "#,
+fn test() {
+ let f: fn(S) -> () = foo;
+}"#,
expect![[r#"
22..23 'x': impl Trait
37..48 '{ loop {} }': ()
fn impl_trait() {
check_infer(
r#"
- trait Trait<T> {
- fn foo(&self) -> T;
- fn foo2(&self) -> i64;
- }
- fn bar() -> impl Trait<u64> {}
+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();
- }
- "#,
+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
cov_mark::check!(lower_rpit);
check_infer(
r#"
- trait Trait<T> {
- fn foo(&self) -> T;
- }
- fn bar() -> impl Trait<u64> { loop {} }
+trait Trait<T> {
+ fn foo(&self) -> T;
+}
+fn bar() -> impl Trait<u64> { loop {} }
- fn test() {
- let a = bar();
- a.foo();
- }
- "#,
+fn test() {
+ let a = bar();
+ a.foo();
+}"#,
expect![[r#"
29..33 'self': &Self
71..82 '{ loop {} }': !
fn more_return_pos_impl_trait() {
check_infer(
r#"
- 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();
- }
- "#,
+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
fn dyn_trait() {
check_infer(
r#"
- trait Trait<T> {
- fn foo(&self) -> T;
- fn foo2(&self) -> i64;
- }
- fn bar() -> dyn Trait<u64> {}
+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();
- }
- "#,
+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
fn dyn_trait_in_impl() {
check_infer(
r#"
- 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> { }
+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();
- }
- "#,
+fn test(s: S<u32, i32>) {
+ s.bar().baz();
+}"#,
expect![[r#"
32..36 'self': &Self
102..106 'self': &S<T, U>
fn dyn_trait_bare() {
check_infer(
r#"
- trait Trait {
- fn foo(&self) -> u64;
- }
- fn bar() -> Trait {}
+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();
- }
- "#,
+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 '{}': ()
fn weird_bounds() {
check_infer(
r#"
- trait Trait {}
- fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?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#"
- 23..24 'a': impl Trait
- 50..51 'b': impl
- 69..70 'c': impl Trait
- 86..87 'd': impl
- 107..108 'e': impl
- 123..124 'f': impl Trait
- 147..149 '{}': ()
+ 28..29 'a': impl Trait
+ 59..60 'b': impl
+ 82..83 'c': impl Trait
+ 103..104 'd': impl
+ 128..129 'e': impl
+ 148..149 'f': impl Trait
+ 173..175 '{}': ()
"#]],
);
}
#[test]
-#[ignore]
fn error_bound_chalk() {
check_types(
r#"
fn assoc_type_bindings() {
check_infer(
r#"
- trait Trait {
- type Type;
- }
+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>);
- }
- "#,
+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 '{}': ()
fn impl_trait_assoc_binding_projection_bug() {
check_types(
r#"
-//- /main.rs crate:main deps:std
+//- minicore: iterator
pub trait Language {
type Kind;
}
node.clone();
} //^ {unknown}
}
-
-//- /std.rs crate:std
-#[prelude_import] use iter::*;
-mod iter {
- trait IntoIterator {
- type Item;
- }
- trait Iterator {
- type Item;
- }
- impl<T: Iterator> IntoIterator for T {
- type Item = <T as Iterator>::Item;
- }
-}
"#,
);
}
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> {}
+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();
- }
- "#,
+fn test<T: Trait1<Type = u32>>(x: T) {
+ x.foo();
+}"#,
expect![[r#"
61..65 'self': Self
163..164 'x': T
fn super_trait_method_resolution() {
check_infer(
r#"
- mod foo {
- trait SuperTrait {
- fn foo(&self) -> u32 {}
- }
- }
- trait Trait1: foo::SuperTrait {}
- trait Trait2 where Self: foo::SuperTrait {}
+mod foo {
+ 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();
- }
- "#,
+fn test<T: Trait1, U: Trait2>(x: T, y: U) {
+ x.foo();
+ y.foo();
+}"#,
expect![[r#"
49..53 'self': &Self
62..64 '{}': ()
fn super_trait_impl_trait_method_resolution() {
check_infer(
r#"
- mod foo {
- trait SuperTrait {
- fn foo(&self) -> u32 {}
- }
- }
- trait Trait1: foo::SuperTrait {}
+mod foo {
+ trait SuperTrait {
+ fn foo(&self) -> u32 {}
+ }
+}
+trait Trait1: foo::SuperTrait {}
- fn test(x: &impl Trait1) {
- x.foo();
- }
- "#,
+fn test(x: &impl Trait1) {
+ x.foo();
+}"#,
expect![[r#"
49..53 'self': &Self
62..64 '{}': ()
fn super_trait_assoc_type_bounds() {
check_infer(
r#"
- trait SuperTrait { type Type; }
- trait Trait where Self: SuperTrait {}
+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}
+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> {}
+struct S<T>;
+impl<T> SuperTrait for S<T> { type Type = T; }
+impl<T> Trait for S<T> {}
- fn test() {
- get2(set(S));
- }
- "#,
+fn test() {
+ get2(set(S));
+}"#,
expect![[r#"
102..103 't': T
113..115 '{}': ()
fn fn_trait() {
check_infer_with_mismatches(
r#"
- trait FnOnce<Args> {
- type Output;
+trait FnOnce<Args> {
+ type Output;
- fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
- }
+ fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
+}
- fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
- f.call_once((1, 2));
- }
- "#,
+fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
+ f.call_once((1, 2));
+}"#,
expect![[r#"
56..60 'self': Self
62..66 'args': Args
fn fn_ptr_and_item() {
check_infer_with_mismatches(
r#"
- #[lang="fn_once"]
- trait FnOnce<Args> {
- type Output;
+#[lang="fn_once"]
+trait FnOnce<Args> {
+ type Output;
- fn call_once(self, args: Args) -> Self::Output;
- }
+ fn call_once(self, args: Args) -> Self::Output;
+}
- trait Foo<T> {
- fn foo(&self) -> T;
- }
+trait Foo<T> {
+ fn foo(&self) -> T;
+}
- struct Bar<T>(T);
+struct Bar<T>(T);
- impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
- fn foo(&self) -> (A1, R) { loop {} }
- }
+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 {} }
- }
+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();
+fn test() {
+ let bar: Bar<fn(u8) -> u32>;
+ bar.foo();
- let opt: Opt<u8>;
- let f: fn(u8) -> u32;
- opt.map(f);
- }
- "#,
+ let opt: Opt<u8>;
+ let f: fn(u8) -> u32;
+ opt.map(f);
+}"#,
expect![[r#"
74..78 'self': Self
80..84 'args': Args
fn fn_trait_deref_with_ty_default() {
check_infer(
r#"
- #[lang = "deref"]
- trait Deref {
- type Target;
+#[lang = "deref"]
+trait Deref {
+ type Target;
- fn deref(&self) -> &Self::Target;
- }
+ fn deref(&self) -> &Self::Target;
+}
- #[lang="fn_once"]
- trait FnOnce<Args> {
- type Output;
+#[lang="fn_once"]
+trait FnOnce<Args> {
+ type Output;
- fn call_once(self, args: Args) -> Self::Output;
- }
+ fn call_once(self, args: Args) -> Self::Output;
+}
- struct Foo;
+struct Foo;
- impl Foo {
- fn foo(&self) -> usize {}
- }
+impl Foo {
+ fn foo(&self) -> usize {}
+}
- struct Lazy<T, F = fn() -> T>(F);
+struct Lazy<T, F = fn() -> T>(F);
- impl<T, F> Lazy<T, F> {
- pub fn new(f: F) -> Lazy<T, F> {}
- }
+impl<T, F> Lazy<T, F> {
+ pub fn new(f: F) -> Lazy<T, F> {}
+}
- impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
- type Target = T;
- }
+impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
+ type Target = T;
+}
- fn test() {
- let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
- let r1 = lazy1.foo();
+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();
- }
- "#,
+ 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#"
64..68 'self': &Self
165..169 'self': Self
fn closure_1() {
check_infer_with_mismatches(
r#"
- #[lang = "fn_once"]
- trait FnOnce<Args> {
- type Output;
- }
-
- enum Option<T> { Some(T), None }
- impl<T> Option<T> {
- fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} }
- }
+//- 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);
- }
- "#,
+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#"
- 147..151 'self': Option<T>
- 153..154 'f': F
- 172..183 '{ loop {} }': Option<U>
- 174..181 'loop {}': !
- 179..181 '{}': ()
- 197..316 '{ ... 1); }': ()
- 207..208 'x': Option<u32>
- 211..223 'Option::Some': Some<u32>(u32) -> Option<u32>
- 211..229 'Option...(1u32)': Option<u32>
- 224..228 '1u32': u32
- 235..236 'x': Option<u32>
- 235..251 'x.map(...v + 1)': Option<u32>
- 241..250 '|v| v + 1': |u32| -> u32
- 242..243 'v': u32
- 245..246 'v': u32
- 245..250 'v + 1': u32
- 249..250 '1': u32
- 257..258 'x': Option<u32>
- 257..273 'x.map(... 1u64)': Option<u64>
- 263..272 '|_v| 1u64': |u32| -> u64
- 264..266 '_v': u32
- 268..272 '1u64': u64
- 283..284 'y': Option<i64>
- 300..301 'x': Option<u32>
- 300..313 'x.map(|_v| 1)': Option<i64>
- 306..312 '|_v| 1': |u32| -> i64
- 307..309 '_v': u32
- 311..312 '1': i64
+ 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': |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': |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': |u32| -> i64
+ 246..248 '_v': u32
+ 250..251 '1': i64
"#]],
);
}
fn closure_2() {
check_infer_with_mismatches(
r#"
- trait FnOnce<Args> {
- type Output;
- }
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+ type Output;
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
- fn test<F: FnOnce(u32) -> u64>(f: F) {
- f(1);
- let g = |v| v + 1;
- g(1u64);
- let h = |v| 1u128 + v;
- }
- "#,
+trait FnOnce<Args> {
+ type Output;
+}
+
+impl Add for u64 {
+ type Output = Self;
+ fn add(self, rhs: u64) -> Self::Output {0}
+}
+
+impl Add for u128 {
+ type Output = Self;
+ fn add(self, rhs: u128) -> Self::Output {0}
+}
+
+fn test<F: FnOnce(u32) -> u64>(f: F) {
+ f(1);
+ let g = |v| v + 1;
+ g(1u64);
+ let h = |v| 1u128 + v;
+}"#,
expect![[r#"
- 72..73 'f': F
- 78..154 '{ ...+ v; }': ()
- 84..85 'f': F
- 84..88 'f(1)': {unknown}
- 86..87 '1': i32
- 98..99 'g': |u64| -> i32
- 102..111 '|v| v + 1': |u64| -> i32
- 103..104 'v': u64
- 106..107 'v': u64
- 106..111 'v + 1': i32
- 110..111 '1': i32
- 117..118 'g': |u64| -> i32
- 117..124 'g(1u64)': i32
- 119..123 '1u64': u64
- 134..135 'h': |u128| -> u128
- 138..151 '|v| 1u128 + v': |u128| -> u128
- 139..140 'v': u128
- 142..147 '1u128': u128
- 142..151 '1u128 + v': u128
- 150..151 'v': u128
+ 72..76 'self': Self
+ 78..81 'rhs': Rhs
+ 203..207 'self': u64
+ 209..212 'rhs': u64
+ 235..238 '{0}': u64
+ 236..237 '0': u64
+ 297..301 'self': u128
+ 303..306 'rhs': u128
+ 330..333 '{0}': u128
+ 331..332 '0': u128
+ 368..369 'f': F
+ 374..450 '{ ...+ v; }': ()
+ 380..381 'f': F
+ 380..384 'f(1)': {unknown}
+ 382..383 '1': i32
+ 394..395 'g': |u64| -> u64
+ 398..407 '|v| v + 1': |u64| -> u64
+ 399..400 'v': u64
+ 402..403 'v': u64
+ 402..407 'v + 1': u64
+ 406..407 '1': u64
+ 413..414 'g': |u64| -> u64
+ 413..420 'g(1u64)': u64
+ 415..419 '1u64': u64
+ 430..431 'h': |u128| -> u128
+ 434..447 '|v| 1u128 + v': |u128| -> u128
+ 435..436 'v': u128
+ 438..443 '1u128': u128
+ 438..447 '1u128 + v': u128
+ 446..447 'v': u128
"#]],
);
}
fn closure_as_argument_inference_order() {
check_infer_with_mismatches(
r#"
- #[lang = "fn_once"]
- trait FnOnce<Args> {
- type Output;
- }
+//- 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 {} }
- 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;
+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 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);
- }
- "#,
+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#"
- 94..95 'x': T
- 100..101 'f': F
- 111..122 '{ loop {} }': U
- 113..120 'loop {}': !
- 118..120 '{}': ()
- 156..157 'f': F
- 162..163 'x': T
- 173..184 '{ loop {} }': U
- 175..182 'loop {}': !
- 180..182 '{}': ()
- 219..223 'self': S
- 271..275 'self': S
- 277..278 'x': T
- 283..284 'f': F
- 294..305 '{ loop {} }': U
- 296..303 'loop {}': !
- 301..303 '{}': ()
- 343..347 'self': S
- 349..350 'f': F
- 355..356 'x': T
- 366..377 '{ loop {} }': U
- 368..375 'loop {}': !
- 373..375 '{}': ()
- 391..550 '{ ... S); }': ()
- 401..403 'x1': u64
- 406..410 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64
- 406..429 'foo1(S...hod())': u64
- 411..412 'S': S
- 414..428 '|s| s.method()': |S| -> u64
- 415..416 's': S
- 418..419 's': S
- 418..428 's.method()': u64
- 439..441 'x2': u64
- 444..448 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64
- 444..467 'foo2(|...(), S)': u64
- 449..463 '|s| s.method()': |S| -> u64
- 450..451 's': S
- 453..454 's': S
- 453..463 's.method()': u64
- 465..466 'S': S
- 477..479 'x3': u64
- 482..483 'S': S
- 482..507 'S.foo1...hod())': u64
- 489..490 'S': S
- 492..506 '|s| s.method()': |S| -> u64
- 493..494 's': S
- 496..497 's': S
- 496..506 's.method()': u64
- 517..519 'x4': u64
- 522..523 'S': S
- 522..547 'S.foo2...(), S)': u64
- 529..543 '|s| s.method()': |S| -> u64
- 530..531 's': S
- 533..534 's': S
- 533..543 's.method()': u64
- 545..546 'S': S
+ 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, |S| -> u64>(S, |S| -> u64) -> u64
+ 345..368 'foo1(S...hod())': u64
+ 350..351 'S': S
+ 353..367 '|s| s.method()': |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, |S| -> u64>(|S| -> u64, S) -> u64
+ 383..406 'foo2(|...(), S)': u64
+ 388..402 '|s| s.method()': |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()': |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()': |S| -> u64
+ 469..470 's': S
+ 472..473 's': S
+ 472..482 's.method()': u64
+ 484..485 'S': S
"#]],
);
}
fn fn_item_fn_trait() {
check_types(
r#"
-#[lang = "fn_once"]
-trait FnOnce<Args> {
- type Output;
-}
-
+//- minicore: fn
struct S;
fn foo() -> S {}
fn unselected_projection_on_impl_self() {
check_infer(
r#"
- //- /main.rs
- trait Trait {
- type Item;
+//- /main.rs
+trait Trait {
+ type Item;
- fn f(&self, x: Self::Item);
- }
+ fn f(&self, x: Self::Item);
+}
- struct S;
+struct S;
- impl Trait for S {
- type Item = u32;
- fn f(&self, x: Self::Item) { let y = x; }
- }
+impl Trait for S {
+ type Item = u32;
+ fn f(&self, x: Self::Item) { let y = x; }
+}
- struct S2;
+struct S2;
- impl Trait for S2 {
- type Item = i32;
- fn f(&self, x: <Self>::Item) { let y = x; }
- }
- "#,
+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>
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! with_api {
+ ($S:ident, $self:ident, $m:ident) => {
+ $m! {
+ TokenStream {
+ fn new() -> $S::TokenStream;
+ },
+ Group {
+ },
}
- 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 {}
- }
+ };
+}
+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);)*
}
- with_api!(Self, self_, declare_server_traits);
- struct G {}
- struct T {}
- struct Rustc;
- impl Types for Rustc {
- type TokenStream = T;
- type Group = G;
- }
+ $(pub trait $name: Types {
+ $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
+ })*
- fn make<T>() -> T { loop {} }
- impl TokenStream for Rustc {
- fn new() -> Self::TokenStream {
- let group: Self::Group = make();
- make()
- }
- }
- "#,
+ pub trait Server: Types $(+ $name)* {}
+ impl<S: Types $(+ $name)*> Server for S {}
+ }
+}
+
+with_api!(Self, self_, declare_server_traits);
+struct G {}
+struct T {}
+struct Rustc;
+impl Types for Rustc {
+ type TokenStream = T;
+ type Group = G;
+}
+
+fn make<T>() -> T { loop {} }
+impl TokenStream for Rustc {
+ fn new() -> Self::TokenStream {
+ let group: Self::Group = make();
+ make()
+ }
+}"#,
expect![[r#"
1061..1072 '{ loop {} }': T
1063..1070 'loop {}': !
fn unify_impl_trait() {
check_infer_with_mismatches(
r#"
- trait Trait<T> {}
+trait Trait<T> {}
- fn foo(x: impl Trait<u32>) { loop {} }
- fn bar<T>(x: impl Trait<T>) -> T { loop {} }
+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> {}
+struct S<T>(T);
+impl<T> Trait<T> for S<T> {}
- fn default<T>() -> T { loop {} }
+fn default<T>() -> T { loop {} }
- fn test() -> impl Trait<i32> {
- let s1 = S(default());
- foo(s1);
- let x: i32 = bar(S(default()));
- S(default())
- }
- "#,
+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 {} }': ()
fn assoc_types_from_bounds() {
check_infer(
r#"
- //- /main.rs
- #[lang = "fn_once"]
- trait FnOnce<Args> {
- type Output;
- }
-
- trait T {
- type O;
- }
+//- minicore: fn
+trait T {
+ type O;
+}
- impl T for () {
- type O = ();
- }
+impl T for () {
+ type O = ();
+}
- fn f<X, F>(_v: F)
- where
- X: T,
- F: FnOnce(&X::O),
- { }
+fn f<X, F>(_v: F)
+where
+ X: T,
+ F: FnOnce(&X::O),
+{ }
- fn main() {
- f::<(), _>(|z| { z; });
- }
- "#,
+fn main() {
+ f::<(), _>(|z| { z; });
+}"#,
expect![[r#"
- 133..135 '_v': F
- 178..181 '{ }': ()
- 193..224 '{ ... }); }': ()
- 199..209 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ())
- 199..221 'f::<()... z; })': ()
- 210..220 '|z| { z; }': |&()| -> ()
- 211..212 'z': &()
- 214..220 '{ z; }': ()
- 216..217 'z': &()
+ 72..74 '_v': F
+ 117..120 '{ }': ()
+ 132..163 '{ ... }); }': ()
+ 138..148 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ())
+ 138..160 'f::<()... z; })': ()
+ 149..159 '|z| { z; }': |&()| -> ()
+ 150..151 'z': &()
+ 153..159 '{ z; }': ()
+ 155..156 'z': &()
"#]],
);
}
fn dyn_trait_through_chalk() {
check_types(
r#"
+//- minicore: deref
struct Box<T> {}
-#[lang = "deref"]
-trait Deref {
- type Target;
-}
-impl<T> Deref for Box<T> {
+impl<T> core::ops::Deref for Box<T> {
type Target = T;
}
trait Trait {
fn iterator_chain() {
check_infer_with_mismatches(
r#"
- //- /main.rs
- #[lang = "fn_once"]
- trait FnOnce<Args> {
- type Output;
- }
- #[lang = "fn_mut"]
- trait FnMut<Args>: FnOnce<Args> { }
-
- enum Option<T> { Some(T), None }
- use Option::*;
-
- pub trait Iterator {
- type Item;
+//- 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 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 {} }
- }
+ 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 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;
- }
+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;
+#[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
- }
- }
+ fn into_iter(self) -> I {
+ self
+ }
+}
- struct Vec<T> {}
- impl<T> Vec<T> {
- fn new() -> Self { loop {} }
- }
+struct Vec<T> {}
+impl<T> Vec<T> {
+ fn new() -> Self { loop {} }
+}
- impl<T> IntoIterator for Vec<T> {
- type Item = T;
- type IntoIter = IntoIter<T>;
- }
+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;
- }
+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; });
- }
- "#,
+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#"
- 226..230 'self': Self
- 232..233 'f': F
- 317..328 '{ loop {} }': FilterMap<Self, F>
- 319..326 'loop {}': !
- 324..326 '{}': ()
- 349..353 'self': Self
- 355..356 'f': F
- 405..416 '{ loop {} }': ()
- 407..414 'loop {}': !
- 412..414 '{}': ()
- 525..529 'self': Self
- 854..858 'self': I
- 865..885 '{ ... }': I
- 875..879 'self': I
- 944..955 '{ loop {} }': Vec<T>
- 946..953 'loop {}': !
- 951..953 '{}': ()
- 1142..1269 '{ ... }); }': ()
- 1148..1163 'Vec::<i32>::new': fn new<i32>() -> Vec<i32>
- 1148..1165 'Vec::<...:new()': Vec<i32>
- 1148..1177 'Vec::<...iter()': IntoIter<i32>
- 1148..1240 'Vec::<...one })': FilterMap<IntoIter<i32>, |i32| -> Option<u32>>
- 1148..1266 'Vec::<... y; })': ()
- 1194..1239 '|x| if...None }': |i32| -> Option<u32>
- 1195..1196 'x': i32
- 1198..1239 'if x >...None }': Option<u32>
- 1201..1202 'x': i32
- 1201..1206 'x > 0': bool
- 1205..1206 '0': i32
- 1207..1225 '{ Some...u32) }': Option<u32>
- 1209..1213 'Some': Some<u32>(u32) -> Option<u32>
- 1209..1223 'Some(x as u32)': Option<u32>
- 1214..1215 'x': i32
- 1214..1222 'x as u32': u32
- 1231..1239 '{ None }': Option<u32>
- 1233..1237 'None': Option<u32>
- 1255..1265 '|y| { y; }': |u32| -> ()
- 1256..1257 'y': u32
- 1259..1265 '{ y; }': ()
- 1261..1262 'y': u32
+ 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>, |i32| -> Option<u32>>
+ 983..1101 'Vec::<... y; })': ()
+ 1029..1074 '|x| if...None }': |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; }': |u32| -> ()
+ 1091..1092 'y': u32
+ 1094..1100 '{ y; }': ()
+ 1096..1097 'y': u32
"#]],
);
}
fn trait_object_no_coercion() {
check_infer_with_mismatches(
r#"
- trait Foo {}
+trait Foo {}
- fn foo(x: &dyn Foo) {}
+fn foo(x: &dyn Foo) {}
- fn test(x: &dyn Foo) {
- foo(x);
- }
- "#,
+fn test(x: &dyn Foo) {
+ foo(x);
+}"#,
expect![[r#"
21..22 'x': &dyn Foo
34..36 '{}': ()
fn builtin_copy() {
check_infer_with_mismatches(
r#"
- #[lang = "copy"]
- trait Copy {}
+#[lang = "copy"]
+trait Copy {}
- struct IsCopy;
- impl Copy for IsCopy {}
- struct NotCopy;
+struct IsCopy;
+impl Copy for IsCopy {}
+struct NotCopy;
- trait Test { fn test(&self) -> bool; }
- impl<T: Copy> Test for T {}
+trait Test { fn test(&self) -> bool; }
+impl<T: Copy> Test for T {}
- fn test() {
- IsCopy.test();
- NotCopy.test();
- (IsCopy, IsCopy).test();
- (IsCopy, NotCopy).test();
- }
- "#,
+fn test() {
+ IsCopy.test();
+ NotCopy.test();
+ (IsCopy, IsCopy).test();
+ (IsCopy, NotCopy).test();
+}"#,
expect![[r#"
110..114 'self': &Self
166..267 '{ ...t(); }': ()
fn builtin_fn_def_copy() {
check_infer_with_mismatches(
r#"
- #[lang = "copy"]
- trait Copy {}
+#[lang = "copy"]
+trait Copy {}
- fn foo() {}
- fn bar<T: Copy>(T) -> T {}
- struct Struct(usize);
- enum Enum { Variant(usize) }
+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 {}
+trait Test { fn test(&self) -> bool; }
+impl<T: Copy> Test for T {}
- fn test() {
- foo.test();
- bar.test();
- Struct.test();
- Enum::Variant.test();
- }
- "#,
+fn test() {
+ foo.test();
+ bar.test();
+ Struct.test();
+ Enum::Variant.test();
+}"#,
expect![[r#"
41..43 '{}': ()
60..61 'T': {unknown}
fn builtin_fn_ptr_copy() {
check_infer_with_mismatches(
r#"
- #[lang = "copy"]
- trait Copy {}
+#[lang = "copy"]
+trait Copy {}
- trait Test { fn test(&self) -> bool; }
- impl<T: Copy> Test for T {}
+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();
- }
- "#,
+fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
+ f1.test();
+ f2.test();
+ f3.test();
+}"#,
expect![[r#"
54..58 'self': &Self
108..110 'f1': fn()
fn builtin_sized() {
check_infer_with_mismatches(
r#"
- #[lang = "sized"]
- trait Sized {}
+#[lang = "sized"]
+trait Sized {}
- trait Test { fn test(&self) -> bool; }
- impl<T: Sized> Test for T {}
+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
- }
- "#,
+fn test() {
+ 1u8.test();
+ (*"foo").test(); // not Sized
+ (1u8, 1u8).test();
+ (1u8, *"foo").test(); // not Sized
+}"#,
expect![[r#"
56..60 'self': &Self
113..228 '{ ...ized }': ()
fn infer_closure_arg() {
check_infer(
r#"
- //- /lib.rs
+//- /lib.rs
- enum Option<T> {
- None,
- Some(T)
- }
+enum Option<T> {
+ None,
+ Some(T)
+}
- fn foo() {
- let s = Option::None;
- let f = |x: Option<i32>| {};
- (&f)(s)
- }
- "#,
+fn foo() {
+ let s = Option::None;
+ let f = |x: Option<i32>| {};
+ (&f)(s)
+}"#,
expect![[r#"
52..126 '{ ...)(s) }': ()
62..63 's': Option<i32>
fn infer_fn_trait_arg() {
check_infer_with_mismatches(
r#"
- //- /lib.rs deps:std
-
- #[lang = "fn_once"]
- pub trait FnOnce<Args> {
- type Output;
-
- extern "rust-call" fn call_once(&self, args: Args) -> Self::Output;
- }
-
- #[lang = "fn"]
- pub trait Fn<Args>:FnOnce<Args> {
- extern "rust-call" fn call(&self, args: Args) -> Self::Output;
- }
-
- enum Option<T> {
- None,
- Some(T)
- }
-
- fn foo<F, T>(f: F) -> T
- where
- F: Fn(Option<i32>) -> T,
- {
- let s = None;
- f(s)
- }
- "#,
+//- minicore: fn, option
+fn foo<F, T>(f: F) -> T
+where
+ F: Fn(Option<i32>) -> T,
+{
+ let s = None;
+ f(s)
+}
+"#,
expect![[r#"
- 101..105 'self': &Self
- 107..111 'args': Args
- 220..224 'self': &Self
- 226..230 'args': Args
- 313..314 'f': F
- 359..389 '{ ...f(s) }': T
- 369..370 's': Option<i32>
- 373..377 'None': Option<i32>
- 383..384 'f': F
- 383..387 'f(s)': T
- 385..386 's': Option<i32>
+ 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 a bug
+ // The type mismatch is because we don't define Unsize and CoerceUnsized
check_infer_with_mismatches(
r#"
- //- /lib.rs deps:std
+//- /lib.rs deps:std
- #[lang = "fn_once"]
- pub trait FnOnce<Args> {
- type Output;
+#[lang = "fn_once"]
+pub trait FnOnce<Args> {
+ type Output;
- extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
- }
+ extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
- #[lang = "deref"]
- pub trait Deref {
- type Target: ?Sized;
+#[lang = "deref"]
+pub trait Deref {
+ type Target: ?Sized;
- fn deref(&self) -> &Self::Target;
- }
+ fn deref(&self) -> &Self::Target;
+}
- #[lang = "owned_box"]
- pub struct Box<T: ?Sized> {
- inner: *mut T,
- }
+#[lang = "owned_box"]
+pub struct Box<T: ?Sized> {
+ inner: *mut T,
+}
- impl<T: ?Sized> Deref for Box<T> {
- type Target = T;
+impl<T: ?Sized> Deref for Box<T> {
+ type Target = T;
- fn deref(&self) -> &T {
- &self.inner
- }
- }
+ fn deref(&self) -> &T {
+ &self.inner
+ }
+}
- enum Option<T> {
- None,
- Some(T)
- }
+enum Option<T> {
+ None,
+ Some(T)
+}
- fn foo() {
- let s = Option::None;
- let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
- f(&s);
- }
- "#,
+fn foo() {
+ let s = Option::None;
+ let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
+ f(&s);
+}"#,
expect![[r#"
100..104 'self': Self
106..110 'args': Args
555..557 'ps': {unknown}
559..561 '{}': ()
568..569 'f': Box<dyn FnOnce(&Option<i32>)>
- 568..573 'f(&s)': FnOnce::Output<dyn FnOnce(&Option<i32>), (&Option<i32>,)>
+ 568..573 'f(&s)': ()
570..572 '&s': &Option<i32>
571..572 's': Option<i32>
- 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|_| -> ()>
+ 549..562: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|{unknown}| -> ()>
"#]],
);
}
fn infer_dyn_fn_output() {
check_types(
r#"
-#[lang = "fn_once"]
-pub trait FnOnce<Args> {
- type Output;
- extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-}
-
-#[lang = "fn"]
-pub trait Fn<Args>: FnOnce<Args> {
- extern "rust-call" fn call(&self, args: Args) -> Self::Output;
-}
-
+//- minicore: fn
fn foo() {
let f: &dyn Fn() -> i32;
f();
fn infer_dyn_fn_once_output() {
check_types(
r#"
-#[lang = "fn_once"]
-pub trait FnOnce<Args> {
- type Output;
- extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
-}
-
+//- minicore: fn
fn foo() {
let f: dyn FnOnce() -> i32;
f();
().method();
//^^^^^^^^^^^ u8
}
-}
- "#,
+}"#,
expect![[r#"
46..50 'self': &Self
58..63 '{ 0 }': u8
fn inner() -> S {
let s = inner();
}
-}
- "#,
+}"#,
expect![[r#"
17..73 '{ ... } }': ()
39..71 '{ ... }': ()
let x = A;
let y = A;
let r = x.do_op(y);
-}
- "#,
+}"#,
expect![[r#"
63..67 'self': Self
69..72 'rhs': RHS
"#]],
)
}
+
+#[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_adt_with_rhs_primitive() {
+ check_infer_with_mismatches(
+ r#"
+#[lang = "add"]
+pub trait Add<Rhs = Self> {
+ type Output;
+ fn add(self, rhs: Rhs) -> Self::Output;
+}
+
+struct Wrapper(u32);
+impl 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#"
+ 72..76 'self': Self
+ 78..81 'rhs': Rhs
+ 192..196 'self': Wrapper
+ 198..201 'rhs': u32
+ 219..247 '{ ... }': Wrapper
+ 229..236 'Wrapper': Wrapper(u32) -> Wrapper
+ 229..241 'Wrapper(rhs)': Wrapper
+ 237..240 'rhs': u32
+ 259..345 '{ ...um; }': ()
+ 269..276 'wrapped': Wrapper
+ 279..286 'Wrapper': Wrapper(u32) -> Wrapper
+ 279..290 'Wrapper(10)': Wrapper
+ 287..289 '10': u32
+ 300..303 'num': u32
+ 311..312 '2': u32
+ 322..325 'res': Wrapper
+ 328..335 'wrapped': Wrapper
+ 328..341 'wrapped + num': Wrapper
+ 338..341 'num': u32
+ "#]],
+ )
+}
+
+#[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
+ "#]],
+ )
+}
+
+// FIXME: We should infer the length of the returned array :)
+#[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; _]
+ 173..194 '{ ... }': [u8; _]
+ 183..188 '*self': [u8; _]
+ 184..188 'self': &[u8; _]
+ 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; _]
+ 245..246 'v': [u8; 2]
+ 245..257 'v.do_thing()': [u8; _]
+ "#]],
+ )
+}
+
+#[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) { 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) { 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 }
+ }
+
+ S2.foo();
+ // ^^^^^^^^ S1
+ }
+}
+"#,
+ );
+}