use expect_test::expect; use crate::tests::check; use super::{check_infer, check_no_mismatches, check_types}; #[test] fn infer_slice_method() { check_types( r#" impl [T] { fn foo(&self) -> T { loop {} } } fn test(x: &[u8]) { <[_]>::foo(x); //^^^^^^^^^^^^^ u8 } "#, ); } #[test] fn cross_crate_primitive_method() { check_types( r#" //- /main.rs crate:main deps:other_crate fn test() { let x = 1f32; x.foo(); } //^^^^^^^ f32 //- /lib.rs crate:other_crate mod foo { impl f32 { pub fn foo(self) -> f32 { 0. } } } "#, ); } #[test] fn infer_array_inherent_impl() { check_types( r#" impl [T; N] { fn foo(&self) -> T { loop {} } } fn test(x: &[u8; 0]) { <[_; 0]>::foo(x); //^^^^^^^^^^^^^^^^ u8 } "#, ); } #[test] fn infer_associated_method_struct() { check_infer( r#" struct A { x: u32 } impl A { fn new() -> A { A { x: 0 } } } fn test() { let a = A::new(); a.x; } "#, expect![[r#" 48..74 '{ ... }': A 58..68 'A { x: 0 }': A 65..66 '0': u32 87..121 '{ ...a.x; }': () 97..98 'a': A 101..107 'A::new': fn new() -> A 101..109 'A::new()': A 115..116 'a': A 115..118 'a.x': u32 "#]], ); } #[test] fn infer_associated_method_struct_in_local_scope() { check_infer( r#" fn mismatch() { struct A; impl A { fn from(_: i32, _: i32) -> Self { A } } let _a = A::from(1, 2); } "#, expect![[r#" 14..146 '{ ... 2); }': () 125..127 '_a': A 130..137 'A::from': fn from(i32, i32) -> A 130..143 'A::from(1, 2)': A 138..139 '1': i32 141..142 '2': i32 60..61 '_': i32 68..69 '_': i32 84..109 '{ ... }': A 98..99 'A': A "#]], ); } #[test] fn infer_associated_method_enum() { check_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; } "#, expect![[r#" 46..66 '{ ... }': A 56..60 'A::B': A 87..107 '{ ... }': A 97..101 'A::C': A 120..177 '{ ... c; }': () 130..131 'a': A 134..138 'A::b': fn b() -> A 134..140 'A::b()': A 146..147 'a': A 157..158 'c': A 161..165 'A::c': fn c() -> A 161..167 'A::c()': A 173..174 'c': A "#]], ); } #[test] fn infer_associated_method_with_modules() { check_infer( r#" mod a { pub struct A; impl A { pub fn thing() -> A { A {} }} } mod b { pub struct B; impl B { pub fn thing() -> u32 { 99 }} pub mod c { pub 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(); } "#, expect![[r#" 59..67 '{ A {} }': A 61..65 'A {}': A 133..139 '{ 99 }': u32 135..137 '99': u32 217..225 '{ C {} }': C 219..223 'C {}': C 256..340 '{ ...g(); }': () 266..267 'x': A 270..281 'a::A::thing': fn thing() -> A 270..283 'a::A::thing()': A 293..294 'y': u32 297..308 'b::B::thing': fn thing() -> u32 297..310 'b::B::thing()': u32 320..321 'z': C 324..335 'c::C::thing': fn thing() -> C 324..337 'c::C::thing()': C "#]], ); } #[test] fn infer_associated_method_generics() { check_infer( r#" struct Gen { val: T } impl Gen { pub fn make(val: T) -> Gen { Gen { val } } } fn test() { let a = Gen::make(0u32); } "#, expect![[r#" 63..66 'val': T 81..108 '{ ... }': Gen 91..102 'Gen { val }': Gen 97..100 'val': T 122..154 '{ ...32); }': () 132..133 'a': Gen 136..145 'Gen::make': fn make(u32) -> Gen 136..151 'Gen::make(0u32)': Gen 146..150 '0u32': u32 "#]], ); } #[test] fn infer_associated_method_generics_without_args() { check_infer( r#" struct Gen { val: T } impl Gen { pub fn make() -> Gen { loop { } } } fn test() { let a = Gen::::make(); } "#, expect![[r#" 75..99 '{ ... }': Gen 85..93 'loop { }': ! 90..93 '{ }': () 113..148 '{ ...e(); }': () 123..124 'a': Gen 127..143 'Gen::<...::make': fn make() -> Gen 127..145 'Gen::<...make()': Gen "#]], ); } #[test] fn infer_associated_method_generics_2_type_params_without_args() { check_infer( r#" struct Gen { val: T, val2: U, } impl Gen { pub fn make() -> Gen { loop { } } } fn test() { let a = Gen::::make(); } "#, expect![[r#" 101..125 '{ ... }': Gen 111..119 'loop { }': ! 116..119 '{ }': () 139..179 '{ ...e(); }': () 149..150 'a': Gen 153..174 'Gen::<...::make': fn make() -> Gen 153..176 'Gen::<...make()': Gen "#]], ); } #[test] fn cross_crate_associated_method_call() { check_types( r#" //- /main.rs crate:main deps:other_crate fn test() { let x = other_crate::foo::S::thing(); x; } //^ i128 //- /lib.rs crate:other_crate pub mod foo { pub struct S; impl S { pub fn thing() -> i128 { 0 } } } "#, ); } #[test] fn infer_trait_method_simple() { // the trait implementation is intentionally incomplete -- it shouldn't matter check_types( 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 //^^^^^^^^^^^ i128 } "#, ); } #[test] fn infer_trait_method_scoped() { // the trait implementation is intentionally incomplete -- it shouldn't matter check_types( 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 } } "#, ); } #[test] fn infer_trait_method_generic_1() { // the trait implementation is intentionally incomplete -- it shouldn't matter check_types( r#" trait Trait { fn method(&self) -> T; } struct S; impl Trait for S {} fn test() { S.method(); //^^^^^^^^^^ u32 } "#, ); } #[test] fn infer_trait_method_generic_more_params() { // the trait implementation is intentionally incomplete -- it shouldn't matter check_types( 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) } "#, ); } #[test] fn infer_trait_method_generic_2() { // the trait implementation is intentionally incomplete -- it shouldn't matter check_types( r#" trait Trait { fn method(&self) -> T; } struct S(T); impl Trait for S {} fn test() { S(1u32).method(); //^^^^^^^^^^^^^^^^ u32 } "#, ); } #[test] fn infer_trait_assoc_method() { check_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(); } "#, expect![[r#" 86..192 '{ ...t(); }': () 96..98 's1': S 104..120 'Defaul...efault': fn default() -> S 104..122 'Defaul...ault()': S 132..134 's2': S 137..147 'S::default': fn default() -> S 137..149 'S::default()': S 159..161 's3': S 164..187 '() -> S 164..189 ' { 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(); } "#, expect![[r#" 126..210 '{ ...e(); }': () 136..137 'a': u32 140..147 'S::make': fn make() -> u32 140..149 'S::make()': u32 159..160 'b': u64 163..177 'G::::make': fn make, u64>() -> u64 163..179 'G::, f64>() -> f64 198..207 'G::make()': f64 "#]], ); } #[test] fn infer_trait_assoc_method_generics_2() { check_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(); } "#, expect![[r#" 134..312 '{ ...e(); }': () 144..145 'a': (u32, i64) 148..162 'S::make::': fn make() -> (u32, i64) 148..164 'S::mak...i64>()': (u32, i64) 174..175 'b': (u32, i64) 188..195 'S::make': fn make() -> (u32, i64) 188..197 'S::make()': (u32, i64) 207..208 'c': (u32, i64) 211..232 'G::': fn make, u32, i64>() -> (u32, i64) 211..234 'G::()': (u32, i64) 244..245 'd': (u32, i64) 258..272 'G::make::': fn make, u32, i64>() -> (u32, i64) 258..274 'G::mak...i64>()': (u32, i64) 284..285 'e': (u32, i64) 300..307 'G::make': fn make, u32, i64>() -> (u32, i64) 300..309 'G::make()': (u32, i64) "#]], ); } #[test] fn infer_trait_assoc_method_generics_3() { check_infer( r#" trait Trait { fn make() -> (Self, T); } struct S; impl Trait for S {} fn test() { let a = S::make(); } "#, expect![[r#" 100..126 '{ ...e(); }': () 110..111 'a': (S, i64) 114..121 'S::make': fn make, i64>() -> (S, i64) 114..123 'S::make()': (S, i64) "#]], ); } #[test] fn infer_trait_assoc_method_generics_4() { check_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(); } "#, expect![[r#" 130..202 '{ ...e(); }': () 140..141 'a': (S, i64) 157..164 'S::make': fn make, i64>() -> (S, i64) 157..166 'S::make()': (S, i64) 176..177 'b': (S, i32) 190..197 'S::make': fn make, i32>() -> (S, i32) 190..199 'S::make()': (S, i32) "#]], ); } #[test] fn infer_trait_assoc_method_generics_5() { check_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::(); } "#, expect![[r#" 106..210 '{ ...>(); }': () 116..117 'a': (S, i64, u8) 120..149 '': fn make, i64, u8>() -> (S, i64, u8) 120..151 '()': (S, i64, u8) 161..162 'b': (S, i64, u8) 181..205 'Trait:...::': fn make, i64, u8>() -> (S, i64, u8) 181..207 'Trait:...()': (S, i64, u8) "#]], ); } #[test] fn infer_call_trait_method_on_generic_param_1() { check_infer( r#" trait Trait { fn method(&self) -> u32; } fn test(t: T) { t.method(); } "#, expect![[r#" 29..33 'self': &Self 63..64 't': T 69..88 '{ ...d(); }': () 75..76 't': T 75..85 't.method()': u32 "#]], ); } #[test] fn infer_call_trait_method_on_generic_param_2() { check_infer( r#" trait Trait { fn method(&self) -> T; } fn test>(t: T) { t.method(); } "#, expect![[r#" 32..36 'self': &Self 70..71 't': T 76..95 '{ ...d(); }': () 82..83 't': T 82..92 't.method()': U "#]], ); } #[test] fn infer_with_multiple_trait_impls() { check_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); } "#, expect![[r#" 28..32 'self': Self 110..201 '{ ...(S); }': () 120..121 'x': u32 129..130 'S': S 129..137 'S.into()': u32 147..148 'y': u64 156..157 'S': S 156..164 'S.into()': u64 174..175 'z': u64 178..195 'Into::...::into': fn into(S) -> u64 178..198 'Into::...nto(S)': u64 196..197 'S': S "#]], ); } #[test] fn method_resolution_unify_impl_self_type() { check_types( r#" struct S; impl S { fn foo(&self) -> u8 { 0 } } impl S { fn foo(&self) -> i8 { 0 } } fn test() { (S::.foo(), S::.foo()); } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (u8, i8) "#, ); } #[test] fn method_resolution_trait_before_autoref() { check_types( r#" 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(); } //^^^^^^^ u128 "#, ); } #[test] fn method_resolution_by_value_before_autoref() { check_types( r#" trait Clone { fn clone(&self) -> Self; } struct S; impl Clone for S {} impl Clone for &S {} fn test() { (S.clone(), (&S).clone(), (&&S).clone()); } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (S, S, &S) "#, ); } #[test] fn method_resolution_trait_before_autoderef() { check_types( r#" 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(); } //^^^^^^^^^^ u128 "#, ); } #[test] fn method_resolution_impl_before_trait() { check_types( r#" 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(); } //^^^^^^^ i8 "#, ); } #[test] fn method_resolution_impl_ref_before_trait() { check_types( r#" 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(); } //^^^^^^^ i8 "#, ); } #[test] fn method_resolution_trait_autoderef() { check_types( r#" trait Trait { fn foo(self) -> u128; } struct S; impl Trait for S { fn foo(self) -> u128 { 0 } } fn test() { (&S).foo(); } //^^^^^^^^^^ u128 "#, ); } #[test] fn method_resolution_unsize_array() { check_types( r#" //- minicore: slice fn test() { let a = [1, 2, 3]; a.len(); } //^^^^^^^ usize "#, ); } #[test] fn method_resolution_trait_from_prelude() { check_types( r#" //- /main.rs crate:main deps:core struct S; impl Clone for S {} fn test() { S.clone(); //^^^^^^^^^ S } //- /lib.rs crate:core pub mod prelude { pub mod rust_2018 { pub trait Clone { fn clone(&self) -> Self; } } } "#, ); } #[test] fn method_resolution_where_clause_for_unknown_trait() { // The blanket impl currently applies because we ignore the unresolved where clause check_types( r#" trait Trait { fn foo(self) -> u128; } struct S; impl Trait for T where T: UnknownTrait {} fn test() { (&S).foo(); } //^^^^^^^^^^ u128 "#, ); } #[test] fn method_resolution_where_clause_not_met() { // The blanket impl shouldn't apply because we can't prove S: Clone // 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 check_types( r#" trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Trait for T where T: Clone {} fn test() { (&S).foo(); } //^^^^^^^^^^ {unknown} "#, ); } #[test] fn method_resolution_where_clause_inline_not_met() { // The blanket impl shouldn't apply because we can't prove S: Clone check_types( r#" trait Clone {} trait Trait { fn foo(self) -> u128; } struct S; impl Trait for T {} fn test() { (&S).foo(); } //^^^^^^^^^^ {unknown} "#, ); } #[test] fn method_resolution_where_clause_1() { check_types( r#" 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(); } //^^^^^^^ u128 "#, ); } #[test] fn method_resolution_where_clause_2() { check_types( r#" 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(); } //^^^^^^^^^ {unknown} "#, ); } #[test] fn method_resolution_where_clause_inline() { check_types( r#" 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(); } //^^^^^^^^^ {unknown} "#, ); } #[test] fn method_resolution_overloaded_method() { check_types( r#" struct Wrapper(T); struct Foo(T); struct Bar(T); impl Wrapper> { pub fn new(foo_: T) -> Self { Wrapper(Foo(foo_)) } } impl Wrapper> { pub fn new(bar_: T) -> Self { Wrapper(Bar(bar_)) } } fn main() { let a = Wrapper::>::new(1.0); let b = Wrapper::>::new(1.0); (a, b); //^^^^^^ (Wrapper>, Wrapper>) } "#, ); } #[test] fn method_resolution_overloaded_const() { cov_mark::check!(const_candidate_self_type_mismatch); check_types( r#" struct Wrapper(T); struct Foo(T); struct Bar(T); impl Wrapper> { pub const VALUE: Foo; } impl Wrapper> { pub const VALUE: Bar; } fn main() { let a = Wrapper::>::VALUE; let b = Wrapper::>::VALUE; (a, b); //^^^^^^ (Foo, Bar) } "#, ); } #[test] fn method_resolution_encountering_fn_type() { check_types( r#" //- /main.rs fn foo() {} trait FnOnce { fn call(self); } fn test() { foo.call(); } //^^^^^^^^^^ {unknown} "#, ); } #[test] fn super_trait_impl_return_trait_method_resolution() { check_infer( r#" //- minicore: sized trait Base { fn foo(self) -> usize; } trait Super : Base {} fn base1() -> impl Base { loop {} } fn super1() -> impl Super { loop {} } fn test(base2: impl Base, super2: impl Super) { base1().foo(); super1().foo(); base2.foo(); super2.foo(); } "#, expect![[r#" 24..28 'self': Self 90..101 '{ loop {} }': ! 92..99 'loop {}': ! 97..99 '{}': () 128..139 '{ loop {} }': ! 130..137 'loop {}': ! 135..137 '{}': () 149..154 'base2': impl Base 167..173 'super2': impl Super 187..264 '{ ...o(); }': () 193..198 'base1': fn base1() -> impl Base 193..200 'base1()': impl Base 193..206 'base1().foo()': usize 212..218 'super1': fn super1() -> impl Super 212..220 'super1()': impl Super 212..226 'super1().foo()': usize 232..237 'base2': impl Base 232..243 'base2.foo()': usize 249..255 'super2': impl Super 249..261 'super2.foo()': usize "#]], ); } #[test] fn method_resolution_non_parameter_type() { check_types( r#" mod a { pub trait Foo { fn foo(&self); } } struct Wrapper(T); fn foo(t: Wrapper) where Wrapper: a::Foo, { t.foo(); } //^^^^^^^ {unknown} "#, ); } #[test] fn method_resolution_3373() { check_types( r#" struct A(T); impl A { fn from(v: i32) -> A { A(v) } } fn main() { A::from(3); } //^^^^^^^^^^ A "#, ); } #[test] fn method_resolution_slow() { // this can get quite slow if we set the solver size limit too high check_types( r#" 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(); } //^^^^^^^^^^^^^^^ () "#, ); } #[test] fn dyn_trait_super_trait_not_in_scope() { check_infer( r#" mod m { pub trait SuperTrait { fn foo(&self) -> u32 { 0 } } } trait Trait: m::SuperTrait {} struct S; impl m::SuperTrait for S {} impl Trait for S {} fn test(d: &dyn Trait) { d.foo(); } "#, expect![[r#" 51..55 'self': &Self 64..69 '{ 0 }': u32 66..67 '0': u32 176..177 'd': &dyn Trait 191..207 '{ ...o(); }': () 197..198 'd': &dyn Trait 197..204 'd.foo()': u32 "#]], ); } #[test] fn method_resolution_foreign_opaque_type() { check_infer( r#" extern "C" { type S; fn f() -> &'static S; } impl S { fn foo(&self) -> bool { true } } fn test() { let s = unsafe { f() }; s.foo(); } "#, expect![[r#" 75..79 'self': &S 89..109 '{ ... }': bool 99..103 'true': bool 123..167 '{ ...o(); }': () 133..134 's': &S 137..151 'unsafe { f() }': &S 137..151 'unsafe { f() }': &S 146..147 'f': fn f() -> &S 146..149 'f()': &S 157..158 's': &S 157..164 's.foo()': bool "#]], ); } #[test] fn method_with_allocator_box_self_type() { check_types( r#" struct Slice {} struct Box {} impl Slice { pub fn into_vec(self: Box) { } } fn main() { let foo: Slice; foo.into_vec(); // we shouldn't crash on this at least } //^^^^^^^^^^^^^^ {unknown} "#, ); } #[test] fn method_on_dyn_impl() { check_types( r#" trait Foo {} impl Foo for u32 {} impl dyn Foo + '_ { pub fn dyn_foo(&self) -> u32 { 0 } } fn main() { let f = &42u32 as &dyn Foo; f.dyn_foo(); // ^^^^^^^^^^^ u32 } "#, ); } #[test] fn dyn_trait_method_priority() { check_types( r#" //- minicore: from trait Trait { fn into(&self) -> usize { 0 } } fn foo(a: &dyn Trait) { let _ = a.into(); //^usize } "#, ); } #[test] fn trait_method_priority_for_placeholder_type() { check_types( r#" //- minicore: from trait Trait { fn into(&self) -> usize { 0 } } fn foo(a: &T) { let _ = a.into(); //^usize } "#, ); } #[test] fn autoderef_visibility_field() { check( r#" //- minicore: deref mod a { pub struct Foo(pub char); pub struct Bar(i32); impl Bar { pub fn new() -> Self { Self(0) } } impl core::ops::Deref for Bar { type Target = Foo; fn deref(&self) -> &Foo { &Foo('z') } } } mod b { fn foo() { let x = super::a::Bar::new().0; // ^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Not))) // ^^^^^^^^^^^^^^^^^^^^^^ type: char } } "#, ) } #[test] fn autoderef_visibility_method() { cov_mark::check!(autoderef_candidate_not_visible); check( r#" //- minicore: deref mod a { pub struct Foo(pub char); impl Foo { pub fn mango(&self) -> char { self.0 } } pub struct Bar(i32); impl Bar { pub fn new() -> Self { Self(0) } fn mango(&self) -> i32 { self.0 } } impl core::ops::Deref for Bar { type Target = Foo; fn deref(&self) -> &Foo { &Foo('z') } } } mod b { fn foo() { let x = super::a::Bar::new().mango(); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: char } } "#, ) } #[test] fn trait_vs_private_inherent_const() { cov_mark::check!(const_candidate_not_visible); check( r#" mod a { pub struct Foo; impl Foo { const VALUE: u32 = 2; } pub trait Trait { const VALUE: usize; } impl Trait for Foo { const VALUE: usize = 3; } fn foo() { let x = Foo::VALUE; // ^^^^^^^^^^ type: u32 } } use a::Trait; fn foo() { let x = a::Foo::VALUE; // ^^^^^^^^^^^^^ type: usize } "#, ) } #[test] fn trait_impl_in_unnamed_const() { check_types( r#" struct S; trait Tr { fn method(&self) -> u16; } const _: () = { impl Tr for S {} }; fn f() { S.method(); //^^^^^^^^^^ u16 } "#, ); } #[test] fn trait_impl_in_synstructure_const() { check_types( r#" struct S; trait Tr { fn method(&self) -> u16; } const _DERIVE_Tr_: () = { impl Tr for S {} }; fn f() { S.method(); //^^^^^^^^^^ u16 } "#, ); } #[test] fn inherent_impl_in_unnamed_const() { check_types( r#" struct S; const _: () = { impl S { fn method(&self) -> u16 { 0 } pub(super) fn super_method(&self) -> u16 { 0 } pub(crate) fn crate_method(&self) -> u16 { 0 } pub fn pub_method(&self) -> u16 { 0 } } }; fn f() { S.method(); //^^^^^^^^^^ u16 S.super_method(); //^^^^^^^^^^^^^^^^ u16 S.crate_method(); //^^^^^^^^^^^^^^^^ u16 S.pub_method(); //^^^^^^^^^^^^^^ u16 } "#, ); } #[test] fn resolve_const_generic_array_methods() { check_types( r#" #[lang = "array"] impl [T; N] { pub fn map(self, f: F) -> [U; N] where F: FnMut(T) -> U, { loop {} } } #[lang = "slice"] impl [T] { pub fn map(self, f: F) -> &[U] where F: FnMut(T) -> U, { loop {} } } fn f() { let v = [1, 2].map::<_, usize>(|x| -> x * 2); v; //^ [usize; 2] } "#, ); } #[test] fn resolve_const_generic_method() { check_types( r#" struct Const; #[lang = "array"] impl [T; N] { pub fn my_map(self, f: F, c: Const) -> [U; X] where F: FnMut(T) -> U, { loop {} } } #[lang = "slice"] impl [T] { pub fn my_map(self, f: F, c: Const) -> &[U] where F: FnMut(T) -> U, { loop {} } } fn f() { let v = [1, 2].my_map::<_, (), 12>(|x| -> x * 2, Const::<12>); v; //^ [(); 12] let v = [1, 2].my_map::<_, P, C>(|x| -> x * 2, Const::); v; //^ [P; C] } "#, ); } #[test] fn const_generic_type_alias() { check_types( r#" struct Const; type U2 = Const<2>; type U5 = Const<5>; impl U2 { fn f(self) -> Const<12> { loop {} } } impl U5 { fn f(self) -> Const<15> { loop {} } } fn f(x: U2) { let y = x.f(); //^ Const<12> } "#, ); } #[test] fn skip_array_during_method_dispatch() { check_types( r#" //- /main2018.rs crate:main2018 deps:core use core::IntoIterator; fn f() { let v = [4].into_iter(); v; //^ &i32 let a = [0, 1].into_iter(); a; //^ &i32 } //- /main2021.rs crate:main2021 deps:core edition:2021 use core::IntoIterator; fn f() { let v = [4].into_iter(); v; //^ i32 let a = [0, 1].into_iter(); a; //^ &i32 } //- /core.rs crate:core #[rustc_skip_array_during_method_dispatch] pub trait IntoIterator { type Out; fn into_iter(self) -> Self::Out; } impl IntoIterator for [T; 1] { type Out = T; fn into_iter(self) -> Self::Out { loop {} } } impl<'a, T> IntoIterator for &'a [T] { type Out = &'a T; fn into_iter(self) -> Self::Out { loop {} } } "#, ); } #[test] fn sized_blanket_impl() { check_infer( r#" //- minicore: sized trait Foo { fn foo() -> u8; } impl Foo for T {} fn f() { u32::foo; S::foo; T::foo; U::foo; <[u32]>::foo; } "#, expect![[r#" 89..160 '{ ...foo; }': () 95..103 'u32::foo': fn foo() -> u8 109..115 'S::foo': fn foo() -> u8 121..127 'T::foo': fn foo() -> u8 133..139 'U::foo': {unknown} 145..157 '<[u32]>::foo': {unknown} "#]], ); } #[test] fn local_impl() { check_types( r#" fn main() { struct SomeStruct(i32); impl SomeStruct { fn is_even(&self) -> bool { self.0 % 2 == 0 } } let o = SomeStruct(3); let is_even = o.is_even(); // ^^^^^^^ bool } "#, ); } #[test] fn deref_fun_1() { check_types( r#" //- minicore: deref struct A(T, U); struct B(T); struct C(T); impl core::ops::Deref for A, u32> { type Target = B; fn deref(&self) -> &B { &self.0 } } impl core::ops::Deref for B { type Target = C; fn deref(&self) -> &C { loop {} } } impl C { fn thing(&self) -> T { self.0 } } fn make() -> T { loop {} } fn test() { let a1 = A(make(), make()); let _: usize = (*a1).0; a1; //^^ A, u32> let a2 = A(make(), make()); a2.thing(); //^^^^^^^^^^ isize a2; //^^ A, u32> } "#, ); } #[test] fn deref_fun_2() { check_types( r#" //- minicore: deref struct A(T, U); struct B(T); struct C(T); impl core::ops::Deref for A, u32> { type Target = B; fn deref(&self) -> &B { &self.0 } } impl core::ops::Deref for B { type Target = C; fn deref(&self) -> &C { loop {} } } impl core::ops::Deref for A, i32> { type Target = C; fn deref(&self) -> &C { &self.0 } } impl C { fn thing(&self) -> T { self.0 } } fn make() -> T { loop {} } fn test() { let a1 = A(make(), 1u32); a1.thing(); a1; //^^ A, u32> let a2 = A(make(), 1i32); let _: &str = a2.thing(); a2; //^^ A, i32> } "#, ); } #[test] fn receiver_adjustment_autoref() { check( r#" struct Foo; impl Foo { fn foo(&self) {} } fn test() { Foo.foo(); //^^^ adjustments: Borrow(Ref(Not)) (&Foo).foo(); // ^^^^ adjustments: , } "#, ); } #[test] fn receiver_adjustment_unsize_array() { // FIXME not quite correct check( r#" //- minicore: slice fn test() { let a = [1, 2, 3]; a.len(); } //^ adjustments: Pointer(Unsize), Borrow(Ref(Not)) "#, ); } #[test] fn bad_inferred_reference_1() { check_no_mismatches( r#" //- minicore: sized pub trait Into: Sized { fn into(self) -> T; } impl Into for T { fn into(self) -> T { self } } trait ExactSizeIterator { fn len(&self) -> usize; } pub struct Foo; impl Foo { fn len(&self) -> usize { 0 } } pub fn test(generic_args: impl Into) { let generic_args = generic_args.into(); generic_args.len(); let _: Foo = generic_args; } "#, ); } #[test] fn bad_inferred_reference_2() { check_no_mismatches( r#" //- minicore: deref trait ExactSizeIterator { fn len(&self) -> usize; } pub struct Foo; impl Foo { fn len(&self) -> usize { 0 } } pub fn test() { let generic_args; generic_args.len(); let _: Foo = generic_args; } "#, ); } #[test] fn resolve_minicore_iterator() { check_types( r#" //- minicore: iterators, sized fn foo() { let m = core::iter::repeat(()).filter_map(|()| Some(92)).next(); } //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Option "#, ); } #[test] fn primitive_assoc_fn_shadowed_by_use() { check_types( r#" //- /lib.rs crate:lib deps:core use core::u16; fn f() -> u16 { let x = u16::from_le_bytes(); x //^ u16 } //- /core.rs crate:core pub mod u16 {} impl u16 { pub fn from_le_bytes() -> Self { 0 } } "#, ) } #[test] fn with_impl_bounds() { check_types( r#" trait Trait {} struct Foo(T); impl Trait for isize {} impl Foo { fn foo() -> isize { 0 } fn bar(&self) -> isize { 0 } } impl Foo<()> { fn foo() {} fn bar(&self) {} } fn f() { let _ = Foo::::foo(); //^isize let _ = Foo(0isize).bar(); //^isize let _ = Foo::<()>::foo(); //^() let _ = Foo(()).bar(); //^() let _ = Foo::::foo(); //^{unknown} let _ = Foo(0usize).bar(); //^{unknown} } fn g(a: T) { let _ = Foo::::foo(); //^isize let _ = Foo(a).bar(); //^isize } "#, ); } #[test] fn incoherent_impls() { check( r#" //- minicore: error, send pub struct Box(T); use core::error::Error; #[rustc_allow_incoherent_impl] impl dyn Error { pub fn downcast(self: Box) -> Result, Box> { loop {} } } #[rustc_allow_incoherent_impl] impl dyn Error + Send { /// Attempts to downcast the box to a concrete type. pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; // ^^^^ expected Box, got Box // FIXME, type mismatch should not occur ::downcast(err).map_err(|_| loop {}) //^^^^^^^^^^^^^^^^^^^^^ type: fn downcast<{unknown}>(Box) -> Result, Box> } } "#, ); } #[test] fn fallback_private_methods() { check( r#" mod module { pub struct Struct; impl Struct { fn func(&self) {} } } fn foo() { let s = module::Struct; s.func(); //^^^^^^^^ type: () } "#, ); }