);
}
+#[test]
+fn infer_tryv2() {
+ 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 ops::*;
+mod ops {
+ trait Try {
+ type Output;
+ type Residual;
+ }
+}
+
+#[prelude_import] use result::*;
+mod result {
+ enum Infallible {}
+ enum Result<O, E> {
+ Ok(O),
+ Err(E)
+ }
+
+ impl<O, E> crate::ops::Try for Result<O, E> {
+ type Output = O;
+ type Error = Result<Infallible, E>;
+ }
+}
+"#,
+ );
+}
+
#[test]
fn infer_for_loop() {
check_types(
mod collections {
struct Vec<T> {}
impl<T> Vec<T> {
- fn new() -> Self { Vec {} }
- fn push(&mut self, t: T) { }
+ pub fn new() -> Self { Vec {} }
+ pub fn push(&mut self, t: T) { }
}
impl<T> IntoIterator for 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 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 '{}': ()
"#]],
);
}
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 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;
-
- fn deref(&self) -> &Self::Target;
- }
+#[lang = "deref"]
+trait Deref {
+ type Target;
- #[lang="fn_once"]
- trait FnOnce<Args> {
- type Output;
+ fn deref(&self) -> &Self::Target;
+}
- fn call_once(self, args: Args) -> Self::Output;
- }
+#[lang="fn_once"]
+trait FnOnce<Args> {
+ type Output;
- struct Foo;
+ fn call_once(self, args: Args) -> Self::Output;
+}
- impl Foo {
- fn foo(&self) -> usize {}
- }
+struct Foo;
- struct Lazy<T, F = fn() -> T>(F);
+impl Foo {
+ fn foo(&self) -> usize {}
+}
- impl<T, F> Lazy<T, F> {
- pub fn new(f: F) -> Lazy<T, F> {}
- }
+struct Lazy<T, F = fn() -> T>(F);
- impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
- type Target = T;
- }
+impl<T, F> Lazy<T, F> {
+ pub fn new(f: F) -> Lazy<T, F> {}
+}
- fn test() {
- let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
- let r1 = lazy1.foo();
+impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
+ type Target = T;
+}
- 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 test() {
+ let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
+ let r1 = lazy1.foo();
+
+ fn make_foo_fn() -> Foo {}
+ let make_foo_fn_ptr: fn() -> Foo = make_foo_fn;
+ let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr);
+ let r2 = lazy2.foo();
+}"#,
expect![[r#"
64..68 'self': &Self
165..169 'self': Self
fn closure_1() {
check_infer_with_mismatches(
r#"
- #[lang = "fn_once"]
- trait FnOnce<Args> {
- type Output;
- }
+#[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 {} }
- }
+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
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;
- }
+#[lang = "fn_once"]
+trait FnOnce<Args> {
+ type Output;
+}
- 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
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;
- }
+//- /main.rs
+#[lang = "fn_once"]
+trait FnOnce<Args> {
+ type Output;
+}
- trait T {
- type O;
- }
+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 '{ }': ()
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> { }
+//- /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::*;
+enum Option<T> { Some(T), None }
+use Option::*;
- pub trait Iterator {
- type Item;
+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
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>
#[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}| -> ()>
"#]],
);
}
().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#"
+#[lang = "fn_once"]
+trait FnOnce<Args> {
+ type Output;
+}
+
+fn test<F: FnOnce()>(f: F) {
+ let _: () = f();
+}"#,
+ expect![[r#"
+ 82..83 'f': F
+ 88..112 '{ ...f(); }': ()
+ 98..99 '_': ()
+ 106..107 'f': F
+ 106..109 '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
+ "#]],
+ );
+}