use insta::assert_snapshot; use ra_db::fixture::WithFixture; use test_utils::mark; use crate::test_db::TestDB; use super::{infer, infer_with_mismatches, type_at, type_at_pos}; #[test] fn infer_await() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:core struct IntFuture; impl Future for IntFuture { type Output = u64; } fn test() { let r = IntFuture; let v = r.await; v<|>; } //- /core.rs crate:core #[prelude_import] use future::*; mod future { #[lang = "future_trait"] trait Future { type Output; } } "#, ); assert_eq!("u64", type_at_pos(&db, pos)); } #[test] fn infer_async() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:core async fn foo() -> u64 { 128 } fn test() { let r = foo(); let v = r.await; v<|>; } //- /core.rs crate:core #[prelude_import] use future::*; mod future { #[lang = "future_trait"] trait Future { type Output; } } "#, ); assert_eq!("u64", type_at_pos(&db, pos)); } #[test] fn infer_desugar_async() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:core async fn foo() -> u64 { 128 } fn test() { let r = foo(); r<|>; } //- /core.rs crate:core #[prelude_import] use future::*; mod future { trait Future { type Output; } } "#, ); assert_eq!("impl Future", type_at_pos(&db, pos)); } #[test] fn infer_try() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:core fn test() { let r: Result = Result::Ok(1); let v = r?; v<|>; } //- /core.rs crate:core #[prelude_import] use ops::*; mod ops { trait Try { type Ok; type Error; } } #[prelude_import] use result::*; mod result { enum Result { Ok(O), Err(E) } impl crate::ops::Try for Result { type Ok = O; type Error = E; } } "#, ); assert_eq!("i32", type_at_pos(&db, pos)); } #[test] fn infer_for_loop() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:core,alloc use alloc::collections::Vec; fn test() { let v = Vec::new(); v.push("foo"); for x in v { x<|>; } } //- /core.rs crate:core #[prelude_import] use iter::*; mod iter { trait IntoIterator { type Item; } } //- /alloc.rs crate:alloc deps:core mod collections { struct Vec {} impl Vec { fn new() -> Self { Vec {} } fn push(&mut self, t: T) { } } impl IntoIterator for Vec { type Item=T; } } "#, ); assert_eq!("&str", type_at_pos(&db, pos)); } #[test] fn infer_ops_neg() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std struct Bar; struct Foo; impl std::ops::Neg for Bar { type Output = Foo; } fn test() { let a = Bar; let b = -a; b<|>; } //- /std.rs crate:std #[prelude_import] use ops::*; mod ops { #[lang = "neg"] pub trait Neg { type Output; } } "#, ); assert_eq!("Foo", type_at_pos(&db, pos)); } #[test] fn infer_ops_not() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std struct Bar; struct Foo; impl std::ops::Not for Bar { type Output = Foo; } fn test() { let a = Bar; let b = !a; b<|>; } //- /std.rs crate:std #[prelude_import] use ops::*; mod ops { #[lang = "not"] pub trait Not { type Output; } } "#, ); assert_eq!("Foo", type_at_pos(&db, pos)); } #[test] fn infer_from_bound_1() { assert_snapshot!( infer(r#" trait Trait {} struct S(T); impl Trait for S {} fn foo>(t: T) {} fn test() { let s = S(unknown); foo(s); } "#), @r###" 85..86 't': T 91..93 '{}': () 104..143 '{ ...(s); }': () 114..115 's': S 118..119 'S': S(u32) -> S 118..128 'S(unknown)': S 120..127 'unknown': u32 134..137 'foo': fn foo>(S) 134..140 'foo(s)': () 138..139 's': S "### ); } #[test] fn infer_from_bound_2() { assert_snapshot!( infer(r#" trait Trait {} struct S(T); impl Trait for S {} fn foo>(t: T) -> U {} fn test() { let s = S(unknown); let x: u32 = foo(s); } "#), @r###" 86..87 't': T 97..99 '{}': () 110..162 '{ ...(s); }': () 120..121 's': S 124..125 'S': S(u32) -> S 124..134 'S(unknown)': S 126..133 'unknown': u32 144..145 'x': u32 153..156 'foo': fn foo>(S) -> u32 153..159 'foo(s)': u32 157..158 's': S "### ); } #[test] fn trait_default_method_self_bound_implements_trait() { mark::check!(trait_self_implements_self); assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> i64; fn bar(&self) -> { let x = self.foo(); } } "#), @r###" 26..30 'self': &Self 52..56 'self': &Self 61..96 '{ ... }': () 75..76 'x': i64 79..83 'self': &Self 79..89 'self.foo()': i64 "### ); } #[test] fn trait_default_method_self_bound_implements_super_trait() { assert_snapshot!( infer(r#" trait SuperTrait { fn foo(&self) -> i64; } trait Trait: SuperTrait { fn bar(&self) -> { let x = self.foo(); } } "#), @r###" 31..35 'self': &Self 85..89 'self': &Self 94..129 '{ ... }': () 108..109 'x': i64 112..116 'self': &Self 112..122 'self.foo()': i64 "### ); } #[test] fn infer_project_associated_type() { assert_snapshot!( infer(r#" trait Iterable { type Item; } struct S; impl Iterable for S { type Item = u32; } fn test() { let x: ::Item = 1; let y: ::Item = no_matter; let z: T::Item = no_matter; let a: ::Item = no_matter; } "#), @r###" 107..260 '{ ...ter; }': () 117..118 'x': u32 144..145 '1': u32 155..156 'y': Iterable::Item 182..191 'no_matter': Iterable::Item 201..202 'z': Iterable::Item 214..223 'no_matter': Iterable::Item 233..234 'a': Iterable::Item 248..257 'no_matter': Iterable::Item "### ); } #[test] fn infer_return_associated_type() { assert_snapshot!( infer(r#" trait Iterable { type Item; } struct S; impl Iterable for S { type Item = u32; } fn foo1(t: T) -> T::Item {} fn foo2(t: T) -> ::Item {} fn foo3(t: T) -> ::Item {} fn test() { let x = foo1(S); let y = foo2(S); let z = foo3(S); } "#), @r###" 105..106 't': T 122..124 '{}': () 146..147 't': T 177..179 '{}': () 201..202 't': T 220..222 '{}': () 233..299 '{ ...(S); }': () 243..244 'x': u32 247..251 'foo1': fn foo1(S) -> ::Item 247..254 'foo1(S)': u32 252..253 'S': S 264..265 'y': u32 268..272 'foo2': fn foo2(S) -> ::Item 268..275 'foo2(S)': u32 273..274 'S': S 285..286 'z': u32 289..293 'foo3': fn foo3(S) -> ::Item 289..296 'foo3(S)': u32 294..295 'S': S "### ); } #[test] fn infer_associated_type_bound() { assert_snapshot!( infer(r#" trait Iterable { type Item; } fn test>() { let y: T::Item = unknown; } "#), @r###" 66..99 '{ ...own; }': () 76..77 'y': u32 89..96 'unknown': u32 "### ); } #[test] fn infer_const_body() { assert_snapshot!( infer(r#" const A: u32 = 1 + 1; static B: u64 = { let x = 1; x }; "#), @r###" 15..16 '1': u32 15..20 '1 + 1': u32 19..20 '1': u32 38..54 '{ let ...1; x }': u64 44..45 'x': u64 48..49 '1': u64 51..52 'x': u64 "### ); } #[test] fn tuple_struct_fields() { assert_snapshot!( infer(r#" struct S(i32, u64); fn test() -> u64 { let a = S(4, 6); let b = a.0; a.1 } "#), @r###" 37..86 '{ ... a.1 }': u64 47..48 'a': S 51..52 'S': S(i32, u64) -> S 51..58 'S(4, 6)': S 53..54 '4': i32 56..57 '6': u64 68..69 'b': i32 72..73 'a': S 72..75 'a.0': i32 81..82 'a': S 81..84 'a.1': u64 "### ); } #[test] fn tuple_struct_with_fn() { assert_snapshot!( infer(r#" struct S(fn(u32) -> u64); fn test() -> u64 { let a = S(|i| 2*i); let b = a.0(4); a.0(2) } "#), @r###" 43..101 '{ ...0(2) }': u64 53..54 'a': S 57..58 'S': S(fn(u32) -> u64) -> S 57..67 'S(|i| 2*i)': S 59..66 '|i| 2*i': |u32| -> u64 60..61 'i': u32 63..64 '2': u32 63..66 '2*i': u32 65..66 'i': u32 77..78 'b': u64 81..82 'a': S 81..84 'a.0': fn(u32) -> u64 81..87 'a.0(4)': u64 85..86 '4': u32 93..94 'a': S 93..96 'a.0': fn(u32) -> u64 93..99 'a.0(2)': u64 97..98 '2': u32 "### ); } #[test] fn indexing_arrays() { assert_snapshot!( infer("fn main() { &mut [9][2]; }"), @r###" 10..26 '{ &mut...[2]; }': () 12..23 '&mut [9][2]': &mut {unknown} 17..20 '[9]': [i32; _] 17..23 '[9][2]': {unknown} 18..19 '9': i32 21..22 '2': i32 "### ) } #[test] fn infer_ops_index() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std struct Bar; struct Foo; impl std::ops::Index for Bar { type Output = Foo; } fn test() { let a = Bar; let b = a[1u32]; b<|>; } //- /std.rs crate:std #[prelude_import] use ops::*; mod ops { #[lang = "index"] pub trait Index { type Output; } } "#, ); assert_eq!("Foo", type_at_pos(&db, pos)); } #[test] fn infer_ops_index_autoderef() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std fn test() { let a = &[1u32, 2, 3]; let b = a[1u32]; b<|>; } //- /std.rs crate:std impl ops::Index for [T] { type Output = T; } #[prelude_import] use ops::*; mod ops { #[lang = "index"] pub trait Index { type Output; } } "#, ); assert_eq!("u32", type_at_pos(&db, pos)); } #[test] fn deref_trait() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct Arc; impl Deref for Arc { type Target = T; } struct S; impl S { fn foo(&self) -> u128 {} } fn test(s: Arc) { (*s, s.foo())<|>; } "#, ); assert_eq!(t, "(S, u128)"); } #[test] fn deref_trait_with_inference_var() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct Arc; fn new_arc() -> Arc {} impl Deref for Arc { type Target = T; } struct S; fn foo(a: Arc) {} fn test() { let a = new_arc(); let b = (*a)<|>; foo(a); } "#, ); assert_eq!(t, "S"); } #[test] fn deref_trait_infinite_recursion() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct S; impl Deref for S { type Target = S; } fn test(s: S) { s.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn deref_trait_with_question_mark_size() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } struct Arc; impl Deref for Arc { type Target = T; } struct S; impl S { fn foo(&self) -> u128 {} } fn test(s: Arc) { (*s, s.foo())<|>; } "#, ); assert_eq!(t, "(S, u128)"); } #[test] fn obligation_from_function_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait for S {} fn foo, U>(t: T) -> U {} fn test(s: S) { foo(s)<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn obligation_from_method_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait for S {} struct O; impl O { fn foo, U>(&self, t: T) -> U {} } fn test() { O.foo(S)<|>; } "#, ); assert_eq!(t, "isize"); } #[test] fn obligation_from_self_method_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait for S {} impl S { fn foo(&self) -> U where Self: Trait {} } fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "i64"); } #[test] fn obligation_from_impl_clause() { let t = type_at( r#" //- /main.rs struct S; trait Trait {} impl Trait<&str> for S {} struct O; impl> O { fn foo(&self) -> U {} } fn test(o: O) { o.foo()<|>; } "#, ); assert_eq!(t, "&str"); } #[test] fn generic_param_env_1() { let t = type_at( r#" //- /main.rs trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Clone for S {} impl Trait for T where T: Clone {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn generic_param_env_1_not_met() { let t = type_at( r#" //- /main.rs trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Clone for S {} impl Trait for T where T: Clone {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn generic_param_env_2() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl Trait for S {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn generic_param_env_2_not_met() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl Trait for S {} fn test(t: T) { t.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn generic_param_env_deref() { let t = type_at( r#" //- /main.rs #[lang = "deref"] trait Deref { type Target; } trait Trait {} impl Deref for T where T: Trait { type Target = i128; } fn test(t: T) { (*t)<|>; } "#, ); assert_eq!(t, "i128"); } #[test] fn associated_type_placeholder() { let t = type_at( r#" //- /main.rs pub trait ApplyL { type Out; } pub struct RefMutL; impl ApplyL for RefMutL { type Out = ::Out; } fn test() { let y: as ApplyL>::Out = no_matter; y<|>; } "#, ); // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. assert_eq!(t, "ApplyL::Out"); } #[test] fn associated_type_placeholder_2() { let t = type_at( r#" //- /main.rs pub trait ApplyL { type Out; } fn foo(t: T) -> ::Out; fn test(t: T) { let y = foo(t); y<|>; } "#, ); assert_eq!(t, "ApplyL::Out"); } #[test] fn argument_impl_trait() { assert_snapshot!( infer_with_mismatches(r#" trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } fn bar(x: impl Trait) {} struct S(T); impl Trait for S {} fn test(x: impl Trait, y: &impl Trait) { x; y; let z = S(1); bar(z); x.foo(); y.foo(); z.foo(); x.foo2(); y.foo2(); z.foo2(); } "#, true), @r###" 29..33 'self': &Self 54..58 'self': &Self 77..78 'x': impl Trait 97..99 '{}': () 154..155 'x': impl Trait 174..175 'y': &impl Trait 195..323 '{ ...2(); }': () 201..202 'x': impl Trait 208..209 'y': &impl Trait 219..220 'z': S 223..224 'S': S(u16) -> S 223..227 'S(1)': S 225..226 '1': u16 233..236 'bar': fn bar(S) 233..239 'bar(z)': () 237..238 'z': S 245..246 'x': impl Trait 245..252 'x.foo()': u64 258..259 'y': &impl Trait 258..265 'y.foo()': u32 271..272 'z': S 271..278 'z.foo()': u16 284..285 'x': impl Trait 284..292 'x.foo2()': i64 298..299 'y': &impl Trait 298..306 'y.foo2()': i64 312..313 'z': S 312..320 'z.foo2()': i64 "### ); } #[test] fn argument_impl_trait_type_args_1() { assert_snapshot!( 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(x: impl Trait) -> T { loop {} } } fn foo(x: impl Trait) -> T { loop {} } struct S; impl Trait for S {} struct F; impl Foo for F {} fn test() { Foo::bar(S); ::bar(S); F::bar(S); Foo::bar::(S); ::bar::(S); foo(S); foo::(S); foo::(S); // we should ignore the extraneous i32 } "#, true), @r###" 155..156 'x': impl Trait 175..186 '{ loop {} }': T 177..184 'loop {}': ! 182..184 '{}': () 199..200 'x': impl Trait 219..230 '{ loop {} }': T 221..228 'loop {}': ! 226..228 '{}': () 300..509 '{ ... i32 }': () 306..314 'Foo::bar': fn bar<{unknown}, {unknown}>(S) -> {unknown} 306..317 'Foo::bar(S)': {unknown} 315..316 'S': S 323..338 '::bar': fn bar(S) -> {unknown} 323..341 '(S) -> {unknown} 347..356 'F::bar(S)': {unknown} 354..355 'S': S 362..377 'Foo::bar::': fn bar<{unknown}, u32>(S) -> u32 362..380 'Foo::b...32>(S)': u32 378..379 'S': S 386..408 '': fn bar(S) -> u32 386..411 '(S)': u32 409..410 'S': S 418..421 'foo': fn foo<{unknown}>(S) -> {unknown} 418..424 'foo(S)': {unknown} 422..423 'S': S 430..440 'foo::': fn foo(S) -> u32 430..443 'foo::(S)': u32 441..442 'S': S 449..464 'foo::': fn foo(S) -> u32 449..467 'foo::<...32>(S)': u32 465..466 'S': S "### ); } #[test] fn argument_impl_trait_type_args_2() { assert_snapshot!( infer_with_mismatches(r#" trait Trait {} struct S; impl Trait for S {} struct F; impl F { fn foo(self, x: impl Trait) -> (T, U) { loop {} } } fn test() { F.foo(S); F::.foo(S); F::.foo::(S); F::.foo::(S); // extraneous argument should be ignored } "#, true), @r###" 87..91 'self': F 93..94 'x': impl Trait 118..129 '{ loop {} }': (T, U) 120..127 'loop {}': ! 125..127 '{}': () 143..283 '{ ...ored }': () 149..150 'F': F<{unknown}> 149..157 'F.foo(S)': ({unknown}, {unknown}) 155..156 'S': S 163..171 'F::': F 163..178 'F::.foo(S)': (u32, {unknown}) 176..177 'S': S 184..192 'F::': F 184..206 'F::(S)': (u32, i32) 204..205 'S': S 212..220 'F::': F 212..239 'F::(S)': (u32, i32) 237..238 'S': S "### ); } #[test] fn argument_impl_trait_to_fn_pointer() { assert_snapshot!( infer_with_mismatches(r#" trait Trait {} fn foo(x: impl Trait) { loop {} } struct S; impl Trait for S {} fn test() { let f: fn(S) -> () = foo; } "#, true), @r###" 22..23 'x': impl Trait 37..48 '{ loop {} }': () 39..46 'loop {}': ! 44..46 '{}': () 90..123 '{ ...foo; }': () 100..101 'f': fn(S) 117..120 'foo': fn foo(S) "### ); } #[test] fn impl_trait() { assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } fn bar() -> impl Trait {} fn test(x: impl Trait, y: &impl Trait) { x; y; let z = bar(); x.foo(); y.foo(); z.foo(); x.foo2(); y.foo2(); z.foo2(); } "#), @r###" 29..33 'self': &Self 54..58 'self': &Self 98..100 '{}': () 110..111 'x': impl Trait 130..131 'y': &impl Trait 151..268 '{ ...2(); }': () 157..158 'x': impl Trait 164..165 'y': &impl Trait 175..176 'z': impl Trait 179..182 'bar': fn bar() -> impl Trait 179..184 'bar()': impl Trait 190..191 'x': impl Trait 190..197 'x.foo()': u64 203..204 'y': &impl Trait 203..210 'y.foo()': u64 216..217 'z': impl Trait 216..223 'z.foo()': u64 229..230 'x': impl Trait 229..237 'x.foo2()': i64 243..244 'y': &impl Trait 243..251 'y.foo2()': i64 257..258 'z': impl Trait 257..265 'z.foo2()': i64 "### ); } #[test] fn simple_return_pos_impl_trait() { mark::check!(lower_rpit); assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> T; } fn bar() -> impl Trait { loop {} } fn test() { let a = bar(); a.foo(); } "#), @r###" 29..33 'self': &Self 71..82 '{ loop {} }': ! 73..80 'loop {}': ! 78..80 '{}': () 94..129 '{ ...o(); }': () 104..105 'a': impl Trait 108..111 'bar': fn bar() -> impl Trait 108..113 'bar()': impl Trait 119..120 'a': impl Trait 119..126 'a.foo()': u64 "### ); } #[test] fn more_return_pos_impl_trait() { assert_snapshot!( infer(r#" trait Iterator { type Item; fn next(&mut self) -> Self::Item; } trait Trait { fn foo(&self) -> T; } fn bar() -> (impl Iterator>, impl Trait) { loop {} } fn baz(t: T) -> (impl Iterator>, impl Trait) { loop {} } fn test() { let (a, b) = bar(); a.next().foo(); b.foo(); let (c, d) = baz(1u128); c.next().foo(); d.foo(); } "#), @r###" 49..53 'self': &mut Self 101..105 'self': &Self 184..195 '{ loop {} }': ({unknown}, {unknown}) 186..193 'loop {}': ! 191..193 '{}': () 206..207 't': T 268..279 '{ loop {} }': ({unknown}, {unknown}) 270..277 'loop {}': ! 275..277 '{}': () 291..413 '{ ...o(); }': () 301..307 '(a, b)': (impl Iterator>, impl Trait) 302..303 'a': impl Iterator> 305..306 'b': impl Trait 310..313 'bar': fn bar() -> (impl Iterator>, impl Trait) 310..315 'bar()': (impl Iterator>, impl Trait) 321..322 'a': impl Iterator> 321..329 'a.next()': impl Trait 321..335 'a.next().foo()': u32 341..342 'b': impl Trait 341..348 'b.foo()': u64 358..364 '(c, d)': (impl Iterator>, impl Trait) 359..360 'c': impl Iterator> 362..363 'd': impl Trait 367..370 'baz': fn baz(u128) -> (impl Iterator>, impl Trait) 367..377 'baz(1u128)': (impl Iterator>, impl Trait) 371..376 '1u128': u128 383..384 'c': impl Iterator> 383..391 'c.next()': impl Trait 383..397 'c.next().foo()': u128 403..404 'd': impl Trait 403..410 'd.foo()': u128 "### ); } #[test] fn dyn_trait() { assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> T; fn foo2(&self) -> i64; } fn bar() -> dyn Trait {} fn test(x: dyn Trait, y: &dyn Trait) { x; y; let z = bar(); x.foo(); y.foo(); z.foo(); x.foo2(); y.foo2(); z.foo2(); } "#), @r###" 29..33 'self': &Self 54..58 'self': &Self 97..99 '{}': () 109..110 'x': dyn Trait 128..129 'y': &dyn Trait 148..265 '{ ...2(); }': () 154..155 'x': dyn Trait 161..162 'y': &dyn Trait 172..173 'z': dyn Trait 176..179 'bar': fn bar() -> dyn Trait 176..181 'bar()': dyn Trait 187..188 'x': dyn Trait 187..194 'x.foo()': u64 200..201 'y': &dyn Trait 200..207 'y.foo()': u64 213..214 'z': dyn Trait 213..220 'z.foo()': u64 226..227 'x': dyn Trait 226..234 'x.foo2()': i64 240..241 'y': &dyn Trait 240..248 'y.foo2()': i64 254..255 'z': dyn Trait 254..262 'z.foo2()': i64 "### ); } #[test] fn dyn_trait_in_impl() { assert_snapshot!( infer(r#" trait Trait { fn foo(&self) -> (T, U); } struct S {} impl S { fn bar(&self) -> &dyn Trait { loop {} } } trait Trait2 { fn baz(&self) -> (T, U); } impl Trait2 for dyn Trait { } fn test(s: S) { s.bar().baz(); } "#), @r###" 32..36 'self': &Self 102..106 'self': &S 128..139 '{ loop {} }': &dyn Trait 130..137 'loop {}': ! 135..137 '{}': () 175..179 'self': &Self 251..252 's': S 267..289 '{ ...z(); }': () 273..274 's': S 273..280 's.bar()': &dyn Trait 273..286 's.bar().baz()': (u32, i32) "### ); } #[test] fn dyn_trait_bare() { assert_snapshot!( infer(r#" 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(); } "#), @r###" 26..30 'self': &Self 60..62 '{}': () 72..73 'x': dyn Trait 82..83 'y': &dyn Trait 100..175 '{ ...o(); }': () 106..107 'x': dyn Trait 113..114 'y': &dyn Trait 124..125 'z': dyn Trait 128..131 'bar': fn bar() -> dyn Trait 128..133 'bar()': dyn Trait 139..140 'x': dyn Trait 139..146 'x.foo()': u64 152..153 'y': &dyn Trait 152..159 'y.foo()': u64 165..166 'z': dyn Trait 165..172 'z.foo()': u64 "### ); } #[test] fn weird_bounds() { assert_snapshot!( 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) { } "#), @r###" 23..24 'a': impl Trait + {error} 50..51 'b': impl {error} 69..70 'c': impl Trait 86..87 'd': impl {error} 107..108 'e': impl {error} 123..124 'f': impl Trait + {error} 147..150 '{ }': () "### ); } #[test] #[ignore] fn error_bound_chalk() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(&self) -> u32 {} } fn test(x: (impl Trait + UnknownTrait)) { x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn assoc_type_bindings() { assert_snapshot!( infer(r#" trait Trait { type Type; } fn get(t: T) -> ::Type {} fn get2>(t: T) -> U {} fn set>(t: T) -> T {t} struct S; impl Trait for S { type Type = T; } fn test>(x: T, y: impl Trait) { get(x); get2(x); get(y); get2(y); get(set(S)); get2(set(S)); get2(S::); } "#), @r###" 49..50 't': T 77..79 '{}': () 111..112 't': T 122..124 '{}': () 154..155 't': T 165..168 '{t}': T 166..167 't': T 256..257 'x': T 262..263 'y': impl Trait 289..397 '{ ...r>); }': () 295..298 'get': fn get(T) -> ::Type 295..301 'get(x)': u32 299..300 'x': T 307..311 'get2': fn get2(T) -> u32 307..314 'get2(x)': u32 312..313 'x': T 320..323 'get': fn get>(impl Trait) -> as Trait>::Type 320..326 'get(y)': i64 324..325 'y': impl Trait 332..336 'get2': fn get2>(impl Trait) -> i64 332..339 'get2(y)': i64 337..338 'y': impl Trait 345..348 'get': fn get>(S) -> as Trait>::Type 345..356 'get(set(S))': u64 349..352 'set': fn set>(S) -> S 349..355 'set(S)': S 353..354 'S': S 362..366 'get2': fn get2>(S) -> u64 362..374 'get2(set(S))': u64 367..370 'set': fn set>(S) -> S 367..373 'set(S)': S 371..372 'S': S 380..384 'get2': fn get2>(S) -> str 380..394 'get2(S::)': str 385..393 'S::': S "### ); } #[test] fn impl_trait_assoc_binding_projection_bug() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:std pub trait Language { type Kind; } pub enum RustLanguage {} impl Language for RustLanguage { type Kind = SyntaxKind; } struct SyntaxNode {} fn foo() -> impl Iterator> {} trait Clone { fn clone(&self) -> Self; } fn api_walkthrough() { for node in foo() { node.clone()<|>; } } //- /std.rs crate:std #[prelude_import] use iter::*; mod iter { trait IntoIterator { type Item; } trait Iterator { type Item; } impl IntoIterator for T { type Item = ::Item; } } "#, ); assert_eq!("{unknown}", type_at_pos(&db, pos)); } #[test] fn projection_eq_within_chalk() { assert_snapshot!( infer(r#" trait Trait1 { type Type; } trait Trait2 { fn foo(self) -> T; } impl Trait2 for U where U: Trait1 {} fn test>(x: T) { x.foo(); } "#), @r###" 61..65 'self': Self 163..164 'x': T 169..185 '{ ...o(); }': () 175..176 'x': T 175..182 'x.foo()': u32 "### ); } #[test] fn where_clause_trait_in_scope_for_method_resolution() { let t = type_at( r#" //- /main.rs mod foo { trait Trait { fn foo(&self) -> u32 {} } } fn test(x: T) { x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn super_trait_method_resolution() { assert_snapshot!( infer(r#" mod foo { trait SuperTrait { fn foo(&self) -> u32 {} } } trait Trait1: foo::SuperTrait {} trait Trait2 where Self: foo::SuperTrait {} fn test(x: T, y: U) { x.foo(); y.foo(); } "#), @r###" 49..53 'self': &Self 62..64 '{}': () 181..182 'x': T 187..188 'y': U 193..222 '{ ...o(); }': () 199..200 'x': T 199..206 'x.foo()': u32 212..213 'y': U 212..219 'y.foo()': u32 "### ); } #[test] fn super_trait_impl_trait_method_resolution() { assert_snapshot!( infer(r#" mod foo { trait SuperTrait { fn foo(&self) -> u32 {} } } trait Trait1: foo::SuperTrait {} fn test(x: &impl Trait1) { x.foo(); } "#), @r###" 49..53 'self': &Self 62..64 '{}': () 115..116 'x': &impl Trait1 132..148 '{ ...o(); }': () 138..139 'x': &impl Trait1 138..145 'x.foo()': u32 "### ); } #[test] fn super_trait_cycle() { // This just needs to not crash assert_snapshot!( infer(r#" trait A: B {} trait B: A {} fn test(x: T) { x.foo(); } "#), @r###" 43..44 'x': T 49..65 '{ ...o(); }': () 55..56 'x': T 55..62 'x.foo()': {unknown} "### ); } #[test] fn super_trait_assoc_type_bounds() { assert_snapshot!( infer(r#" trait SuperTrait { type Type; } trait Trait where Self: SuperTrait {} fn get2>(t: T) -> U {} fn set>(t: T) -> T {t} struct S; impl SuperTrait for S { type Type = T; } impl Trait for S {} fn test() { get2(set(S)); } "#), @r###" 102..103 't': T 113..115 '{}': () 145..146 't': T 156..159 '{t}': T 157..158 't': T 258..279 '{ ...S)); }': () 264..268 'get2': fn get2>(S) -> u64 264..276 'get2(set(S))': u64 269..272 'set': fn set>(S) -> S 269..275 'set(S)': S 273..274 'S': S "### ); } #[test] fn fn_trait() { assert_snapshot!( infer(r#" trait FnOnce { type Output; fn call_once(self, args: Args) -> >::Output; } fn test u128>(f: F) { f.call_once((1, 2)); } "#), @r###" 56..60 'self': Self 62..66 'args': Args 149..150 'f': F 155..183 '{ ...2)); }': () 161..162 'f': F 161..180 'f.call...1, 2))': u128 173..179 '(1, 2)': (u32, u64) 174..175 '1': u32 177..178 '2': u64 "### ); } #[test] fn fn_ptr_and_item() { assert_snapshot!( infer(r#" #[lang="fn_once"] trait FnOnce { type Output; fn call_once(self, args: Args) -> Self::Output; } trait Foo { fn foo(&self) -> T; } struct Bar(T); impl R> Foo<(A1, R)> for Bar { fn foo(&self) -> (A1, R) {} } enum Opt { None, Some(T) } impl Opt { fn map U>(self, f: F) -> Opt {} } fn test() { let bar: Bar u32>; bar.foo(); let opt: Opt; let f: fn(u8) -> u32; opt.map(f); } "#), @r###" 74..78 'self': Self 80..84 'args': Args 139..143 'self': &Self 243..247 'self': &Bar 260..262 '{}': () 346..350 'self': Opt 352..353 'f': F 368..370 '{}': () 384..500 '{ ...(f); }': () 394..397 'bar': Bar u32> 423..426 'bar': Bar u32> 423..432 'bar.foo()': (u8, u32) 443..446 'opt': Opt 465..466 'f': fn(u8) -> u32 487..490 'opt': Opt 487..497 'opt.map(f)': Opt 495..496 'f': fn(u8) -> u32 "### ); } #[test] fn fn_trait_deref_with_ty_default() { assert_snapshot!( infer(r#" #[lang = "deref"] trait Deref { type Target; fn deref(&self) -> &Self::Target; } #[lang="fn_once"] trait FnOnce { type Output; fn call_once(self, args: Args) -> Self::Output; } struct Foo; impl Foo { fn foo(&self) -> usize {} } struct Lazy T>(F); impl Lazy { pub fn new(f: F) -> Lazy {} } impl T> Deref for Lazy { type Target = T; } fn test() { let lazy1: Lazy = 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 = Lazy::new(make_foo_fn_ptr); let r2 = lazy2.foo(); } "#), @r###" 64..68 'self': &Self 165..169 'self': Self 171..175 'args': Args 239..243 'self': &Foo 254..256 '{}': () 334..335 'f': F 354..356 '{}': () 443..689 '{ ...o(); }': () 453..458 'lazy1': Lazy Foo> 475..484 'Lazy::new': fn new Foo>(|| -> Foo) -> Lazy Foo> 475..492 'Lazy::...| Foo)': Lazy Foo> 485..491 '|| Foo': || -> Foo 488..491 'Foo': Foo 502..504 'r1': usize 507..512 'lazy1': Lazy Foo> 507..518 'lazy1.foo()': usize 560..575 'make_foo_fn_ptr': fn() -> Foo 591..602 'make_foo_fn': fn make_foo_fn() -> Foo 612..617 'lazy2': Lazy Foo> 634..643 'Lazy::new': fn new Foo>(fn() -> Foo) -> Lazy Foo> 634..660 'Lazy::...n_ptr)': Lazy Foo> 644..659 'make_foo_fn_ptr': fn() -> Foo 670..672 'r2': usize 675..680 'lazy2': Lazy Foo> 675..686 'lazy2.foo()': usize 549..551 '{}': () "### ); } #[test] fn closure_1() { assert_snapshot!( infer(r#" #[lang = "fn_once"] trait FnOnce { type Output; } enum Option { Some(T), None } impl Option { fn map U>(self, f: F) -> Option {} } fn test() { let x = Option::Some(1u32); x.map(|v| v + 1); x.map(|_v| 1u64); let y: Option = x.map(|_v| 1); } "#), @r###" 147..151 'self': Option 153..154 'f': F 172..174 '{}': () 188..307 '{ ... 1); }': () 198..199 'x': Option 202..214 'Option::Some': Some(u32) -> Option 202..220 'Option...(1u32)': Option 215..219 '1u32': u32 226..227 'x': Option 226..242 'x.map(...v + 1)': Option 232..241 '|v| v + 1': |u32| -> u32 233..234 'v': u32 236..237 'v': u32 236..241 'v + 1': u32 240..241 '1': u32 248..249 'x': Option 248..264 'x.map(... 1u64)': Option 254..263 '|_v| 1u64': |u32| -> u64 255..257 '_v': u32 259..263 '1u64': u64 274..275 'y': Option 291..292 'x': Option 291..304 'x.map(|_v| 1)': Option 297..303 '|_v| 1': |u32| -> i64 298..300 '_v': u32 302..303 '1': i64 "### ); } #[test] fn closure_2() { assert_snapshot!( infer(r#" trait FnOnce { type Output; } fn test u64>(f: F) { f(1); let g = |v| v + 1; g(1u64); let h = |v| 1u128 + v; } "#), @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 "### ); } #[test] fn closure_as_argument_inference_order() { assert_snapshot!( infer(r#" #[lang = "fn_once"] trait FnOnce { type Output; } fn foo1 U>(x: T, f: F) -> U {} fn foo2 U>(f: F, x: T) -> U {} struct S; impl S { fn method(self) -> u64; fn foo1 U>(self, x: T, f: F) -> U {} fn foo2 U>(self, f: F, x: T) -> U {} } 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); } "#), @r###" 94..95 'x': T 100..101 'f': F 111..113 '{}': () 147..148 'f': F 153..154 'x': T 164..166 '{}': () 201..205 'self': S 253..257 'self': S 259..260 'x': T 265..266 'f': F 276..278 '{}': () 316..320 'self': S 322..323 'f': F 328..329 'x': T 339..341 '{}': () 355..514 '{ ... S); }': () 365..367 'x1': u64 370..374 'foo1': fn foo1 u64>(S, |S| -> u64) -> u64 370..393 'foo1(S...hod())': u64 375..376 'S': S 378..392 '|s| s.method()': |S| -> u64 379..380 's': S 382..383 's': S 382..392 's.method()': u64 403..405 'x2': u64 408..412 'foo2': fn foo2 u64>(|S| -> u64, S) -> u64 408..431 'foo2(|...(), S)': u64 413..427 '|s| s.method()': |S| -> u64 414..415 's': S 417..418 's': S 417..427 's.method()': u64 429..430 'S': S 441..443 'x3': u64 446..447 'S': S 446..471 'S.foo1...hod())': u64 453..454 'S': S 456..470 '|s| s.method()': |S| -> u64 457..458 's': S 460..461 's': S 460..470 's.method()': u64 481..483 'x4': u64 486..487 'S': S 486..511 'S.foo2...(), S)': u64 493..507 '|s| s.method()': |S| -> u64 494..495 's': S 497..498 's': S 497..507 's.method()': u64 509..510 'S': S "### ); } #[test] fn unselected_projection_in_trait_env_1() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } trait Trait2 { fn foo(&self) -> u32; } fn test() where T::Item: Trait2 { let x: T::Item = no_matter; x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn unselected_projection_in_trait_env_2() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } trait Trait2 { fn foo(&self) -> u32; } fn test() where T::Item: Trait2, T: Trait, U: Trait<()> { let x: T::Item = no_matter; x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn unselected_projection_on_impl_self() { assert_snapshot!(infer( r#" //- /main.rs trait Trait { type Item; fn f(&self, x: Self::Item); } struct S; impl Trait for S { type Item = u32; fn f(&self, x: Self::Item) { let y = x; } } struct S2; impl Trait for S2 { type Item = i32; fn f(&self, x: ::Item) { let y = x; } } "#, ), @r###" 40..44 'self': &Self 46..47 'x': Trait::Item 126..130 'self': &S 132..133 'x': u32 147..161 '{ let y = x; }': () 153..154 'y': u32 157..158 'x': u32 228..232 'self': &S2 234..235 'x': i32 251..265 '{ let y = x; }': () 257..258 'y': i32 261..262 'x': i32 "###); } #[test] fn unselected_projection_on_trait_self() { let t = type_at( r#" //- /main.rs trait Trait { type Item; fn f(&self) -> Self::Item { loop {} } } struct S; impl Trait for S { type Item = u32; } fn test() { S.f()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn unselected_projection_chalk_fold() { let t = type_at( r#" //- /main.rs trait Interner {} trait Fold { type Result; } struct Ty {} impl Fold for Ty { type Result = Ty; } fn fold(interner: &I, t: T) -> T::Result where T: Fold, { loop {} } fn foo(interner: &I, t: Ty) { fold(interner, t)<|>; } "#, ); assert_eq!(t, "Ty"); } #[test] fn trait_impl_self_ty() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(&self); } struct S; impl Trait for S {} fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "()"); } #[test] fn trait_impl_self_ty_cycle() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(&self); } struct S; impl Trait for S {} fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn unselected_projection_in_trait_env_cycle_1() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } trait Trait2 {} fn test() where T: Trait2 { let x: T::Item = no_matter<|>; } "#, ); // this is a legitimate cycle assert_eq!(t, "{unknown}"); } #[test] fn unselected_projection_in_trait_env_cycle_2() { let t = type_at( r#" //- /main.rs trait Trait { type Item; } fn test() where T: Trait, U: Trait { let x: T::Item = no_matter<|>; } "#, ); // this is a legitimate cycle assert_eq!(t, "{unknown}"); } #[test] fn inline_assoc_type_bounds_1() { let t = type_at( r#" //- /main.rs trait Iterator { type Item; } trait OtherTrait { fn foo(&self) -> T; } // workaround for Chalk assoc type normalization problems pub struct S; impl Iterator for S { type Item = ::Item; } fn test>>() { let x: as Iterator>::Item; x.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn inline_assoc_type_bounds_2() { let t = type_at( r#" //- /main.rs trait Iterator { type Item; } fn test>>() { let x: <::Item as Iterator>::Item; x<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn proc_macro_server_types() { assert_snapshot!( infer(r#" macro_rules! with_api { ($S:ident, $self:ident, $m:ident) => { $m! { TokenStream { fn new() -> $S::TokenStream; }, Group { }, } }; } macro_rules! associated_item { (type TokenStream) => (type TokenStream: 'static;); (type Group) => (type Group: 'static;); ($($item:tt)*) => ($($item)*;) } macro_rules! declare_server_traits { ($($name:ident { $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* }),* $(,)?) => { pub trait Types { $(associated_item!(type $name);)* } $(pub trait $name: Types { $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)* })* pub trait Server: Types $(+ $name)* {} impl 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 { loop {} } impl TokenStream for Rustc { fn new() -> Self::TokenStream { let group: Self::Group = make(); make() } } "#), @r###" 1061..1072 '{ loop {} }': T 1063..1070 'loop {}': ! 1068..1070 '{}': () 1136..1199 '{ ... }': T 1150..1155 'group': G 1171..1175 'make': fn make() -> G 1171..1177 'make()': G 1187..1191 'make': fn make() -> T 1187..1193 'make()': T "### ); } #[test] fn unify_impl_trait() { assert_snapshot!( infer_with_mismatches(r#" trait Trait {} fn foo(x: impl Trait) { loop {} } fn bar(x: impl Trait) -> T { loop {} } struct S(T); impl Trait for S {} fn default() -> T { loop {} } fn test() -> impl Trait { let s1 = S(default()); foo(s1); let x: i32 = bar(S(default())); S(default()) } "#, true), @r###" 26..27 'x': impl Trait 46..57 '{ loop {} }': () 48..55 'loop {}': ! 53..55 '{}': () 68..69 'x': impl Trait 91..102 '{ loop {} }': T 93..100 'loop {}': ! 98..100 '{}': () 171..182 '{ loop {} }': T 173..180 'loop {}': ! 178..180 '{}': () 213..309 '{ ...t()) }': S<{unknown}> 223..225 's1': S 228..229 'S': S(u32) -> S 228..240 'S(default())': S 230..237 'default': fn default() -> u32 230..239 'default()': u32 246..249 'foo': fn foo(S) 246..253 'foo(s1)': () 250..252 's1': S 263..264 'x': i32 272..275 'bar': fn bar(S) -> i32 272..289 'bar(S(...lt()))': i32 276..277 'S': S(i32) -> S 276..288 'S(default())': S 278..285 'default': fn default() -> i32 278..287 'default()': i32 295..296 'S': S<{unknown}>({unknown}) -> S<{unknown}> 295..307 'S(default())': S<{unknown}> 297..304 'default': fn default<{unknown}>() -> {unknown} 297..306 'default()': {unknown} "### ); } #[test] fn assoc_types_from_bounds() { assert_snapshot!( infer(r#" //- /main.rs #[lang = "fn_once"] trait FnOnce { type Output; } trait T { type O; } impl T for () { type O = (); } fn f(_v: F) where X: T, F: FnOnce(&X::O), { } fn main() { f::<(), _>(|z| { z; }); } "#), @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': &() "### ); } #[test] fn associated_type_bound() { let t = type_at( r#" //- /main.rs pub trait Trait { type Item: OtherTrait; } pub trait OtherTrait { fn foo(&self) -> T; } // this is just a workaround for chalk#234 pub struct S; impl Trait for S { type Item = ::Item; } fn test() { let y: as Trait>::Item = no_matter; y.foo()<|>; } "#, ); assert_eq!(t, "u32"); } #[test] fn dyn_trait_through_chalk() { let t = type_at( r#" //- /main.rs struct Box {} #[lang = "deref"] trait Deref { type Target; } impl Deref for Box { type Target = T; } trait Trait { fn foo(&self); } fn test(x: Box) { x.foo()<|>; } "#, ); assert_eq!(t, "()"); } #[test] fn string_to_owned() { let t = type_at( r#" //- /main.rs struct String {} pub trait ToOwned { type Owned; fn to_owned(&self) -> Self::Owned; } impl ToOwned for str { type Owned = String; } fn test() { "foo".to_owned()<|>; } "#, ); assert_eq!(t, "String"); } #[test] fn iterator_chain() { assert_snapshot!( infer(r#" //- /main.rs #[lang = "fn_once"] trait FnOnce { type Output; } #[lang = "fn_mut"] trait FnMut: FnOnce { } enum Option { Some(T), None } use Option::*; pub trait Iterator { type Item; fn filter_map(self, f: F) -> FilterMap where F: FnMut(Self::Item) -> Option, { loop {} } fn for_each(self, f: F) where F: FnMut(Self::Item), { loop {} } } pub trait IntoIterator { type Item; type IntoIter: Iterator; fn into_iter(self) -> Self::IntoIter; } pub struct FilterMap { } impl Iterator for FilterMap where F: FnMut(I::Item) -> Option, { type Item = B; } #[stable(feature = "rust1", since = "1.0.0")] impl IntoIterator for I { type Item = I::Item; type IntoIter = I; fn into_iter(self) -> I { self } } struct Vec {} impl Vec { fn new() -> Self { loop {} } } impl IntoIterator for Vec { type Item = T; type IntoIter = IntoIter; } pub struct IntoIter { } impl Iterator for IntoIter { type Item = T; } fn main() { Vec::::new().into_iter() .filter_map(|x| if x > 0 { Some(x as u32) } else { None }) .for_each(|y| { y; }); } "#), @r###" 226..230 'self': Self 232..233 'f': F 317..328 '{ loop {} }': FilterMap 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 946..953 'loop {}': ! 951..953 '{}': () 1142..1273 '{ ... }); }': () 1148..1163 'Vec::::new': fn new() -> Vec 1148..1165 'Vec::<...:new()': Vec 1148..1177 'Vec::<...iter()': IntoIter 1148..1242 'Vec::<...one })': FilterMap, |i32| -> Option> 1148..1270 'Vec::<... y; })': () 1196..1241 '|x| if...None }': |i32| -> Option 1197..1198 'x': i32 1200..1241 'if x >...None }': Option 1203..1204 'x': i32 1203..1208 'x > 0': bool 1207..1208 '0': i32 1209..1227 '{ Some...u32) }': Option 1211..1215 'Some': Some(u32) -> Option 1211..1225 'Some(x as u32)': Option 1216..1217 'x': i32 1216..1224 'x as u32': u32 1233..1241 '{ None }': Option 1235..1239 'None': Option 1259..1269 '|y| { y; }': |u32| -> () 1260..1261 'y': u32 1263..1269 '{ y; }': () 1265..1266 'y': u32 "### ); } #[test] fn nested_assoc() { let t = type_at( r#" //- /main.rs struct Bar; struct Foo; trait A { type OutputA; } impl A for Bar { type OutputA = Foo; } trait B { type Output; fn foo() -> Self::Output; } impl B for T { type Output = T::OutputA; fn foo() -> Self::Output { loop {} } } fn main() { Bar::foo()<|>; } "#, ); assert_eq!(t, "Foo"); } #[test] fn trait_object_no_coercion() { assert_snapshot!( infer_with_mismatches(r#" trait Foo {} fn foo(x: &dyn Foo) {} fn test(x: &dyn Foo) { foo(x); } "#, true), @r###" 21..22 'x': &dyn Foo 34..36 '{}': () 46..47 'x': &dyn Foo 59..74 '{ foo(x); }': () 65..68 'foo': fn foo(&dyn Foo) 65..71 'foo(x)': () 69..70 'x': &dyn Foo "### ); } #[test] fn builtin_copy() { assert_snapshot!( infer_with_mismatches(r#" #[lang = "copy"] trait Copy {} struct IsCopy; impl Copy for IsCopy {} struct NotCopy; trait Test { fn test(&self) -> bool; } impl Test for T {} fn test() { IsCopy.test(); NotCopy.test(); (IsCopy, IsCopy).test(); (IsCopy, NotCopy).test(); } "#, true), @r###" 110..114 'self': &Self 166..267 '{ ...t(); }': () 172..178 'IsCopy': IsCopy 172..185 'IsCopy.test()': bool 191..198 'NotCopy': NotCopy 191..205 'NotCopy.test()': {unknown} 211..227 '(IsCop...sCopy)': (IsCopy, IsCopy) 211..234 '(IsCop...test()': bool 212..218 'IsCopy': IsCopy 220..226 'IsCopy': IsCopy 240..257 '(IsCop...tCopy)': (IsCopy, NotCopy) 240..264 '(IsCop...test()': {unknown} 241..247 'IsCopy': IsCopy 249..256 'NotCopy': NotCopy "### ); } #[test] fn builtin_fn_def_copy() { assert_snapshot!( infer_with_mismatches(r#" #[lang = "copy"] trait Copy {} fn foo() {} fn bar(T) -> T {} struct Struct(usize); enum Enum { Variant(usize) } trait Test { fn test(&self) -> bool; } impl Test for T {} fn test() { foo.test(); bar.test(); Struct.test(); Enum::Variant.test(); } "#, true), @r###" 41..43 '{}': () 60..61 'T': {unknown} 68..70 '{}': () 68..70: expected T, got () 145..149 'self': &Self 201..281 '{ ...t(); }': () 207..210 'foo': fn foo() 207..217 'foo.test()': bool 223..226 'bar': fn bar<{unknown}>({unknown}) -> {unknown} 223..233 'bar.test()': bool 239..245 'Struct': Struct(usize) -> Struct 239..252 'Struct.test()': bool 258..271 'Enum::Variant': Variant(usize) -> Enum 258..278 'Enum::...test()': bool "### ); } #[test] fn builtin_fn_ptr_copy() { assert_snapshot!( infer_with_mismatches(r#" #[lang = "copy"] trait Copy {} trait Test { fn test(&self) -> bool; } impl Test for T {} fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { f1.test(); f2.test(); f3.test(); } "#, true), @r###" 54..58 'self': &Self 108..110 'f1': fn() 118..120 'f2': fn(usize) -> u8 139..141 'f3': fn(u8, u8) -> &u8 162..210 '{ ...t(); }': () 168..170 'f1': fn() 168..177 'f1.test()': bool 183..185 'f2': fn(usize) -> u8 183..192 'f2.test()': bool 198..200 'f3': fn(u8, u8) -> &u8 198..207 'f3.test()': bool "### ); } #[test] fn builtin_sized() { assert_snapshot!( infer_with_mismatches(r#" #[lang = "sized"] trait Sized {} trait Test { fn test(&self) -> bool; } impl Test for T {} fn test() { 1u8.test(); (*"foo").test(); // not Sized (1u8, 1u8).test(); (1u8, *"foo").test(); // not Sized } "#, true), @r###" 56..60 'self': &Self 113..228 '{ ...ized }': () 119..122 '1u8': u8 119..129 '1u8.test()': bool 135..150 '(*"foo").test()': {unknown} 136..142 '*"foo"': str 137..142 '"foo"': &str 169..179 '(1u8, 1u8)': (u8, u8) 169..186 '(1u8, ...test()': bool 170..173 '1u8': u8 175..178 '1u8': u8 192..205 '(1u8, *"foo")': (u8, str) 192..212 '(1u8, ...test()': {unknown} 193..196 '1u8': u8 198..204 '*"foo"': str 199..204 '"foo"': &str "### ); } #[test] fn integer_range_iterate() { let t = type_at( r#" //- /main.rs crate:main deps:core fn test() { for x in 0..100 { x<|>; } } //- /core.rs crate:core pub mod ops { pub struct Range { pub start: Idx, pub end: Idx, } } pub mod iter { pub trait Iterator { type Item; } pub trait IntoIterator { type Item; type IntoIter: Iterator; } impl IntoIterator for T where T: Iterator { type Item = ::Item; type IntoIter = Self; } } trait Step {} impl Step for i32 {} impl Step for i64 {} impl iter::Iterator for ops::Range { type Item = A; } "#, ); assert_eq!(t, "i32"); } #[test] fn infer_closure_arg() { assert_snapshot!( infer( r#" //- /lib.rs enum Option { None, Some(T) } fn foo() { let s = Option::None; let f = |x: Option| {}; (&f)(s) } "# ), @r###" 52..126 '{ ...)(s) }': () 62..63 's': Option 66..78 'Option::None': Option 88..89 'f': |Option| -> () 92..111 '|x: Op...2>| {}': |Option| -> () 93..94 'x': Option 109..111 '{}': () 117..124 '(&f)(s)': () 118..120 '&f': &|Option| -> () 119..120 'f': |Option| -> () 122..123 's': Option "### ); } #[test] fn infer_fn_trait_arg() { assert_snapshot!( infer( r#" //- /lib.rs deps:std #[lang = "fn_once"] pub trait FnOnce { type Output; extern "rust-call" fn call_once(&self, args: Args) -> Self::Output; } #[lang = "fn"] pub trait Fn:FnOnce { extern "rust-call" fn call(&self, args: Args) -> Self::Output; } enum Option { None, Some(T) } fn foo(f: F) -> T where F: Fn(Option) -> T, { let s = None; f(s) } "# ), @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 373..377 'None': Option 383..384 'f': F 383..387 'f(s)': T 385..386 's': Option "### ); } #[test] fn infer_box_fn_arg() { assert_snapshot!( infer( r#" //- /lib.rs deps:std #[lang = "fn_once"] pub trait FnOnce { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } #[lang = "deref"] pub trait Deref { type Target: ?Sized; fn deref(&self) -> &Self::Target; } #[lang = "owned_box"] pub struct Box { inner: *mut T, } impl Deref for Box { type Target = T; fn deref(&self) -> &T { &self.inner } } enum Option { None, Some(T) } fn foo() { let s = Option::None; let f: Box)> = box (|ps| {}); f(&s) } "# ), @r###" 100..104 'self': Self 106..110 'args': Args 214..218 'self': &Self 384..388 'self': &Box 396..423 '{ ... }': &T 406..417 '&self.inner': &*mut T 407..411 'self': &Box 407..417 'self.inner': *mut T 478..575 '{ ...(&s) }': FnOnce::Output,)>, (&Option,)> 488..489 's': Option 492..504 'Option::None': Option 514..515 'f': Box,)>> 549..562 'box (|ps| {})': Box<|{unknown}| -> ()> 554..561 '|ps| {}': |{unknown}| -> () 555..557 'ps': {unknown} 559..561 '{}': () 568..569 'f': Box,)>> 568..573 'f(&s)': FnOnce::Output,)>, (&Option,)> 570..572 '&s': &Option 571..572 's': Option "### ); } #[test] fn infer_dyn_fn_output() { assert_snapshot!( infer( r#" //- /lib.rs deps:std #[lang = "fn_once"] pub trait FnOnce { type Output; extern "rust-call" fn call_once(self, args: Args) -> Self::Output; } #[lang = "fn"] pub trait Fn:FnOnce { extern "rust-call" fn call(&self, args: Args) -> Self::Output; } #[lang = "deref"] pub trait Deref { type Target: ?Sized; fn deref(&self) -> &Self::Target; } #[lang = "owned_box"] pub struct Box { inner: *mut T, } impl Deref for Box { type Target = T; fn deref(&self) -> &T { &self.inner } } fn foo() { let f: Box i32> = box(|| 5); let x = f(); } "# ), @r###" 100..104 'self': Self 106..110 'args': Args 219..223 'self': &Self 225..229 'args': Args 333..337 'self': &Self 503..507 'self': &Box 515..542 '{ ... }': &T 525..536 '&self.inner': &*mut T 526..530 'self': &Box 526..536 'self.inner': *mut T 555..620 '{ ...f(); }': () 565..566 'f': Box> 591..600 'box(|| 5)': Box<|| -> i32> 595..599 '|| 5': || -> i32 598..599 '5': i32 610..611 'x': FnOnce::Output, ()> 614..615 'f': Box> 614..617 'f()': FnOnce::Output, ()> "### ); }