use super::{infer, type_at, type_at_pos}; use crate::test_db::TestDB; use insta::assert_snapshot; use ra_db::fixture::WithFixture; #[test] fn infer_slice_method() { assert_snapshot!( infer(r#" #[lang = "slice"] impl [T] { fn foo(&self) -> T { loop {} } } #[lang = "slice_alloc"] impl [T] {} fn test() { <[_]>::foo(b"foo"); } "#), @r###" [45; 49) 'self': &[T] [56; 79) '{ ... }': T [66; 73) 'loop {}': ! [71; 73) '{}': () [133; 160) '{ ...o"); }': () [139; 149) '<[_]>::foo': fn foo(&[u8]) -> u8 [139; 157) '<[_]>:..."foo")': u8 [150; 156) 'b"foo"': &[u8] "### ); } #[test] fn infer_associated_method_struct() { assert_snapshot!( infer(r#" struct A { x: u32 } impl A { fn new() -> A { A { x: 0 } } } fn test() { let a = A::new(); a.x; } "#), @r###" [49; 75) '{ ... }': A [59; 69) 'A { x: 0 }': A [66; 67) '0': u32 [88; 122) '{ ...a.x; }': () [98; 99) 'a': A [102; 108) 'A::new': fn new() -> A [102; 110) 'A::new()': A [116; 117) 'a': A [116; 119) 'a.x': u32 "### ); } #[test] fn infer_associated_method_enum() { assert_snapshot!( infer(r#" enum A { B, C } impl A { pub fn b() -> A { A::B } pub fn c() -> A { A::C } } fn test() { let a = A::b(); a; let c = A::c(); c; } "#), @r###" [47; 67) '{ ... }': A [57; 61) 'A::B': A [88; 108) '{ ... }': A [98; 102) 'A::C': A [121; 178) '{ ... c; }': () [131; 132) 'a': A [135; 139) 'A::b': fn b() -> A [135; 141) 'A::b()': A [147; 148) 'a': A [158; 159) 'c': A [162; 166) 'A::c': fn c() -> A [162; 168) 'A::c()': A [174; 175) 'c': A "### ); } #[test] fn infer_associated_method_with_modules() { assert_snapshot!( infer(r#" mod a { struct A; impl A { pub fn thing() -> A { A {} }} } mod b { struct B; impl B { pub fn thing() -> u32 { 99 }} mod c { struct C; impl C { pub fn thing() -> C { C {} }} } } use b::c; fn test() { let x = a::A::thing(); let y = b::B::thing(); let z = c::C::thing(); } "#), @r###" [56; 64) '{ A {} }': A [58; 62) 'A {}': A [126; 132) '{ 99 }': u32 [128; 130) '99': u32 [202; 210) '{ C {} }': C [204; 208) 'C {}': C [241; 325) '{ ...g(); }': () [251; 252) 'x': A [255; 266) 'a::A::thing': fn thing() -> A [255; 268) 'a::A::thing()': A [278; 279) 'y': u32 [282; 293) 'b::B::thing': fn thing() -> u32 [282; 295) 'b::B::thing()': u32 [305; 306) 'z': C [309; 320) 'c::C::thing': fn thing() -> C [309; 322) 'c::C::thing()': C "### ); } #[test] fn infer_associated_method_generics() { assert_snapshot!( infer(r#" struct Gen { val: T } impl Gen { pub fn make(val: T) -> Gen { Gen { val } } } fn test() { let a = Gen::make(0u32); } "#), @r###" [64; 67) 'val': T [82; 109) '{ ... }': Gen [92; 103) 'Gen { val }': Gen [98; 101) 'val': T [123; 155) '{ ...32); }': () [133; 134) 'a': Gen [137; 146) 'Gen::make': fn make(u32) -> Gen [137; 152) 'Gen::make(0u32)': Gen [147; 151) '0u32': u32 "### ); } #[test] fn infer_associated_method_generics_with_default_param() { assert_snapshot!( infer(r#" struct Gen { val: T } impl Gen { pub fn make() -> Gen { loop { } } } fn test() { let a = Gen::make(); } "#), @r###" [80; 104) '{ ... }': Gen [90; 98) 'loop { }': ! [95; 98) '{ }': () [118; 146) '{ ...e(); }': () [128; 129) 'a': Gen [132; 141) 'Gen::make': fn make() -> Gen [132; 143) 'Gen::make()': Gen "### ); } #[test] fn infer_associated_method_generics_with_default_tuple_param() { let t = type_at( r#" //- /main.rs struct Gen { val: T } impl Gen { pub fn make() -> Gen { loop { } } } fn test() { let a = Gen::make(); a.val<|>; } "#, ); assert_eq!(t, "()"); } #[test] fn infer_associated_method_generics_without_args() { assert_snapshot!( infer(r#" struct Gen { val: T } impl Gen { pub fn make() -> Gen { loop { } } } fn test() { let a = Gen::::make(); } "#), @r###" [76; 100) '{ ... }': Gen [86; 94) 'loop { }': ! [91; 94) '{ }': () [114; 149) '{ ...e(); }': () [124; 125) 'a': Gen [128; 144) 'Gen::<...::make': fn make() -> Gen [128; 146) 'Gen::<...make()': Gen "### ); } #[test] fn infer_associated_method_generics_2_type_params_without_args() { assert_snapshot!( infer(r#" struct Gen { val: T, val2: U, } impl Gen { pub fn make() -> Gen { loop { } } } fn test() { let a = Gen::::make(); } "#), @r###" [102; 126) '{ ... }': Gen [112; 120) 'loop { }': ! [117; 120) '{ }': () [140; 180) '{ ...e(); }': () [150; 151) 'a': Gen [154; 175) 'Gen::<...::make': fn make() -> Gen [154; 177) 'Gen::<...make()': Gen "### ); } #[test] fn cross_crate_associated_method_call() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:other_crate fn test() { let x = other_crate::foo::S::thing(); x<|>; } //- /lib.rs crate:other_crate mod foo { struct S; impl S { fn thing() -> i128 {} } } "#, ); assert_eq!("i128", type_at_pos(&db, pos)); } #[test] fn infer_trait_method_simple() { // the trait implementation is intentionally incomplete -- it shouldn't matter assert_snapshot!( infer(r#" trait Trait1 { fn method(&self) -> u32; } struct S1; impl Trait1 for S1 {} trait Trait2 { fn method(&self) -> i128; } struct S2; impl Trait2 for S2 {} fn test() { S1.method(); // -> u32 S2.method(); // -> i128 } "#), @r###" [31; 35) 'self': &Self [110; 114) 'self': &Self [170; 228) '{ ...i128 }': () [176; 178) 'S1': S1 [176; 187) 'S1.method()': u32 [203; 205) 'S2': S2 [203; 214) 'S2.method()': i128 "### ); } #[test] fn infer_trait_method_scoped() { // the trait implementation is intentionally incomplete -- it shouldn't matter assert_snapshot!( infer(r#" struct S; mod foo { pub trait Trait1 { fn method(&self) -> u32; } impl Trait1 for super::S {} } mod bar { pub trait Trait2 { fn method(&self) -> i128; } impl Trait2 for super::S {} } mod foo_test { use super::S; use super::foo::Trait1; fn test() { S.method(); // -> u32 } } mod bar_test { use super::S; use super::bar::Trait2; fn test() { S.method(); // -> i128 } } "#), @r###" [63; 67) 'self': &Self [169; 173) 'self': &Self [300; 337) '{ ... }': () [310; 311) 'S': S [310; 320) 'S.method()': u32 [416; 454) '{ ... }': () [426; 427) 'S': S [426; 436) 'S.method()': i128 "### ); } #[test] fn infer_trait_method_generic_1() { // the trait implementation is intentionally incomplete -- it shouldn't matter assert_snapshot!( infer(r#" trait Trait { fn method(&self) -> T; } struct S; impl Trait for S {} fn test() { S.method(); } "#), @r###" [33; 37) 'self': &Self [92; 111) '{ ...d(); }': () [98; 99) 'S': S [98; 108) 'S.method()': u32 "### ); } #[test] fn infer_trait_method_generic_more_params() { // the trait implementation is intentionally incomplete -- it shouldn't matter assert_snapshot!( infer(r#" trait Trait { fn method1(&self) -> (T1, T2, T3); fn method2(&self) -> (T3, T2, T1); } struct S1; impl Trait for S1 {} struct S2; impl Trait for S2 {} fn test() { S1.method1(); // u8, u16, u32 S1.method2(); // u32, u16, u8 S2.method1(); // i8, i16, {unknown} S2.method2(); // {unknown}, i16, i8 } "#), @r###" [43; 47) 'self': &Self [82; 86) 'self': &Self [210; 361) '{ ..., i8 }': () [216; 218) 'S1': S1 [216; 228) 'S1.method1()': (u8, u16, u32) [250; 252) 'S1': S1 [250; 262) 'S1.method2()': (u32, u16, u8) [284; 286) 'S2': S2 [284; 296) 'S2.method1()': (i8, i16, {unknown}) [324; 326) 'S2': S2 [324; 336) 'S2.method2()': ({unknown}, i16, i8) "### ); } #[test] fn infer_trait_method_generic_2() { // the trait implementation is intentionally incomplete -- it shouldn't matter assert_snapshot!( infer(r#" trait Trait { fn method(&self) -> T; } struct S(T); impl Trait for S {} fn test() { S(1u32).method(); } "#), @r###" [33; 37) 'self': &Self [102; 127) '{ ...d(); }': () [108; 109) 'S': S(u32) -> S [108; 115) 'S(1u32)': S [108; 124) 'S(1u32...thod()': u32 [110; 114) '1u32': u32 "### ); } #[test] fn infer_trait_assoc_method() { assert_snapshot!( infer(r#" trait Default { fn default() -> Self; } struct S; impl Default for S {} fn test() { let s1: S = Default::default(); let s2 = S::default(); let s3 = ::default(); } "#), @r###" [87; 193) '{ ...t(); }': () [97; 99) 's1': S [105; 121) 'Defaul...efault': fn default() -> S [105; 123) 'Defaul...ault()': S [133; 135) 's2': S [138; 148) 'S::default': fn default() -> S [138; 150) 'S::default()': S [160; 162) 's3': S [165; 188) '() -> S [165; 190) ' { fn make() -> T; } struct S; impl Trait for S {} struct G; impl Trait for G {} fn test() { let a = S::make(); let b = G::::make(); let c: f64 = G::make(); } "#), @r###" [127; 211) '{ ...e(); }': () [137; 138) 'a': u32 [141; 148) 'S::make': fn make() -> u32 [141; 150) 'S::make()': u32 [160; 161) 'b': u64 [164; 178) 'G::::make': fn make, u64>() -> u64 [164; 180) 'G::, f64>() -> f64 [199; 208) 'G::make()': f64 "### ); } #[test] fn infer_trait_assoc_method_generics_2() { assert_snapshot!( infer(r#" trait Trait { fn make() -> (T, U); } struct S; impl Trait for S {} struct G; impl Trait for G {} fn test() { let a = S::make::(); let b: (_, i64) = S::make(); let c = G::::make::(); let d: (u32, _) = G::make::(); let e: (u32, i64) = G::make(); } "#), @r###" [135; 313) '{ ...e(); }': () [145; 146) 'a': (u32, i64) [149; 163) 'S::make::': fn make() -> (u32, i64) [149; 165) 'S::mak...i64>()': (u32, i64) [175; 176) 'b': (u32, i64) [189; 196) 'S::make': fn make() -> (u32, i64) [189; 198) 'S::make()': (u32, i64) [208; 209) 'c': (u32, i64) [212; 233) 'G::': fn make, u32, i64>() -> (u32, i64) [212; 235) 'G::()': (u32, i64) [245; 246) 'd': (u32, i64) [259; 273) 'G::make::': fn make, u32, i64>() -> (u32, i64) [259; 275) 'G::mak...i64>()': (u32, i64) [285; 286) 'e': (u32, i64) [301; 308) 'G::make': fn make, u32, i64>() -> (u32, i64) [301; 310) 'G::make()': (u32, i64) "### ); } #[test] fn infer_trait_assoc_method_generics_3() { assert_snapshot!( infer(r#" trait Trait { fn make() -> (Self, T); } struct S; impl Trait for S {} fn test() { let a = S::make(); } "#), @r###" [101; 127) '{ ...e(); }': () [111; 112) 'a': (S, i64) [115; 122) 'S::make': fn make, i64>() -> (S, i64) [115; 124) 'S::make()': (S, i64) "### ); } #[test] fn infer_trait_assoc_method_generics_4() { assert_snapshot!( infer(r#" trait Trait { fn make() -> (Self, T); } struct S; impl Trait for S {} impl Trait for S {} fn test() { let a: (S, _) = S::make(); let b: (_, i32) = S::make(); } "#), @r###" [131; 203) '{ ...e(); }': () [141; 142) 'a': (S, i64) [158; 165) 'S::make': fn make, i64>() -> (S, i64) [158; 167) 'S::make()': (S, i64) [177; 178) 'b': (S, i32) [191; 198) 'S::make': fn make, i32>() -> (S, i32) [191; 200) 'S::make()': (S, i32) "### ); } #[test] fn infer_trait_assoc_method_generics_5() { assert_snapshot!( infer(r#" trait Trait { fn make() -> (Self, T, U); } struct S; impl Trait for S {} fn test() { let a = >::make::(); let b: (S, _, _) = Trait::::make::(); } "#), @r###" [107; 211) '{ ...>(); }': () [117; 118) 'a': (S, i64, u8) [121; 150) '': fn make, i64, u8>() -> (S, i64, u8) [121; 152) '()': (S, i64, u8) [162; 163) 'b': (S, i64, u8) [182; 206) 'Trait:...::': fn make, i64, u8>() -> (S, i64, u8) [182; 208) 'Trait:...()': (S, i64, u8) "### ); } #[test] fn infer_call_trait_method_on_generic_param_1() { assert_snapshot!( infer(r#" trait Trait { fn method(&self) -> u32; } fn test(t: T) { t.method(); } "#), @r###" [30; 34) 'self': &Self [64; 65) 't': T [70; 89) '{ ...d(); }': () [76; 77) 't': T [76; 86) 't.method()': u32 "### ); } #[test] fn infer_call_trait_method_on_generic_param_2() { assert_snapshot!( infer(r#" trait Trait { fn method(&self) -> T; } fn test>(t: T) { t.method(); } "#), @r###" [33; 37) 'self': &Self [71; 72) 't': T [77; 96) '{ ...d(); }': () [83; 84) 't': T [83; 93) 't.method()': [missing name] "### ); } #[test] fn infer_with_multiple_trait_impls() { assert_snapshot!( infer(r#" trait Into { fn into(self) -> T; } struct S; impl Into for S {} impl Into for S {} fn test() { let x: u32 = S.into(); let y: u64 = S.into(); let z = Into::::into(S); } "#), @r###" [29; 33) 'self': Self [111; 202) '{ ...(S); }': () [121; 122) 'x': u32 [130; 131) 'S': S [130; 138) 'S.into()': u32 [148; 149) 'y': u64 [157; 158) 'S': S [157; 165) 'S.into()': u64 [175; 176) 'z': u64 [179; 196) 'Into::...::into': fn into(S) -> u64 [179; 199) 'Into::...nto(S)': u64 [197; 198) 'S': S "### ); } #[test] fn method_resolution_unify_impl_self_type() { let t = type_at( r#" //- /main.rs struct S; impl S { fn foo(&self) -> u8 {} } impl S { fn foo(&self) -> i8 {} } fn test() { (S::.foo(), S::.foo())<|>; } "#, ); assert_eq!(t, "(u8, i8)"); } #[test] fn method_resolution_trait_before_autoref() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl S { fn foo(&self) -> i8 { 0 } } impl Trait for S { fn foo(self) -> u128 { 0 } } fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn method_resolution_by_value_before_autoref() { let t = type_at( r#" //- /main.rs trait Clone { fn clone(&self) -> Self; } struct S; impl Clone for S {} impl Clone for &S {} fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; } "#, ); assert_eq!(t, "(S, S, &S)"); } #[test] fn method_resolution_trait_before_autoderef() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl S { fn foo(self) -> i8 { 0 } } impl Trait for &S { fn foo(self) -> u128 { 0 } } fn test() { (&S).foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn method_resolution_impl_before_trait() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl S { fn foo(self) -> i8 { 0 } } impl Trait for S { fn foo(self) -> u128 { 0 } } fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "i8"); } #[test] fn method_resolution_impl_ref_before_trait() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl S { fn foo(&self) -> i8 { 0 } } impl Trait for &S { fn foo(self) -> u128 { 0 } } fn test() { S.foo()<|>; } "#, ); assert_eq!(t, "i8"); } #[test] fn method_resolution_trait_autoderef() { let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl Trait for S { fn foo(self) -> u128 { 0 } } fn test() { (&S).foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn method_resolution_trait_from_prelude() { let (db, pos) = TestDB::with_position( r#" //- /main.rs crate:main deps:other_crate struct S; impl Clone for S {} fn test() { S.clone()<|>; } //- /lib.rs crate:other_crate #[prelude_import] use foo::*; mod foo { trait Clone { fn clone(&self) -> Self; } } "#, ); assert_eq!("S", type_at_pos(&db, pos)); } #[test] fn method_resolution_where_clause_for_unknown_trait() { // The blanket impl currently applies because we ignore the unresolved where clause let t = type_at( r#" //- /main.rs trait Trait { fn foo(self) -> u128; } struct S; impl Trait for T where T: UnknownTrait {} fn test() { (&S).foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn method_resolution_where_clause_not_met() { // The blanket impl shouldn't apply because we can't prove S: Clone let t = type_at( r#" //- /main.rs trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Trait for T where T: Clone {} fn test() { (&S).foo()<|>; } "#, ); // This is also to make sure that we don't resolve to the foo method just // because that's the only method named foo we can find, which would make // the below tests not work assert_eq!(t, "{unknown}"); } #[test] fn method_resolution_where_clause_inline_not_met() { // The blanket impl shouldn't apply because we can't prove S: Clone let t = type_at( r#" //- /main.rs trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Trait for T {} fn test() { (&S).foo()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn method_resolution_where_clause_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() { S.foo()<|>; } "#, ); assert_eq!(t, "u128"); } #[test] fn method_resolution_where_clause_2() { let t = type_at( r#" //- /main.rs trait Into { fn into(self) -> T; } trait From { fn from(other: T) -> Self; } struct S1; struct S2; impl From for S1 {} impl Into for T where U: From {} fn test() { S2.into()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn method_resolution_where_clause_inline() { let t = type_at( r#" //- /main.rs trait Into { fn into(self) -> T; } trait From { fn from(other: T) -> Self; } struct S1; struct S2; impl From for S1 {} impl> Into for T {} fn test() { S2.into()<|>; } "#, ); assert_eq!(t, "{unknown}"); } #[test] fn method_resolution_encountering_fn_type() { type_at( r#" //- /main.rs fn foo() {} trait FnOnce { fn call(self); } fn test() { foo.call()<|>; } "#, ); } #[test] fn method_resolution_slow() { // this can get quite slow if we set the solver size limit too high let t = type_at( r#" //- /main.rs trait SendX {} struct S1; impl SendX for S1 {} struct S2; impl SendX for S2 {} struct U1; trait Trait { fn method(self); } struct X1 {} impl SendX for X1 where A: SendX, B: SendX {} struct S {} trait FnX {} impl Trait for S where C: FnX, B: SendX {} fn test() { (S {}).method()<|>; } "#, ); assert_eq!(t, "()"); }