Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/tests/traits.rs')
| -rw-r--r-- | crates/hir-ty/src/tests/traits.rs | 383 |
1 files changed, 322 insertions, 61 deletions
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index da76d7fd83..829a6ab189 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -90,7 +90,7 @@ fn infer_async_closure() { async fn test() { let f = async move |x: i32| x + 42; f; -// ^ |i32| -> impl Future<Output = i32> +// ^ impl Fn(i32) -> impl Future<Output = i32> let a = f(4); a; // ^ impl Future<Output = i32> @@ -99,7 +99,7 @@ async fn test() { // ^ i32 let f = async move || 42; f; -// ^ || -> impl Future<Output = i32> +// ^ impl Fn() -> impl Future<Output = i32> let a = f(); a; // ^ impl Future<Output = i32> @@ -116,7 +116,7 @@ async fn test() { }; let _: Option<u64> = c().await; c; -// ^ || -> impl Future<Output = Option<u64>> +// ^ impl Fn() -> impl Future<Output = Option<u64>> } "#, ); @@ -206,19 +206,27 @@ fn test() { fn infer_try_trait() { check_types( r#" -//- minicore: try, result +//- minicore: try, result, from fn test() { let r: Result<i32, u64> = Result::Ok(1); let v = r?; v; } //^ i32 - -impl<O, E> core::ops::Try for Result<O, E> { - type Output = O; - type Error = Result<core::convert::Infallible, E>; +"#, + ); } -impl<T, E, F: From<E>> core::ops::FromResidual<Result<core::convert::Infallible, E>> for Result<T, F> {} +#[test] +fn infer_try_block() { + // FIXME: We should test more cases, but it currently doesn't work, since + // our labeled block type inference is broken. + check_types( + r#" +//- minicore: try, option +fn test() { + let x: Option<_> = try { Some(2)?; }; + //^ Option<()> +} "#, ); } @@ -542,7 +550,7 @@ fn test() -> u64 { 53..54 'a': S 57..58 'S': S(fn(u32) -> u64) -> S 57..74 'S(|i| ...s u64)': S - 59..73 '|i| 2*i as u64': |u32| -> u64 + 59..73 '|i| 2*i as u64': impl Fn(u32) -> u64 60..61 'i': u32 63..64 '2': u64 63..73 '2*i as u64': u64 @@ -1325,9 +1333,9 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) { } "#, expect![[r#" - 134..165 '{ ...(C)) }': (|&str, T| -> (), Bar<u8>) - 140..163 '(|inpu...ar(C))': (|&str, T| -> (), Bar<u8>) - 141..154 '|input, t| {}': |&str, T| -> () + 134..165 '{ ...(C)) }': (impl Fn(&str, T), Bar<u8>) + 140..163 '(|inpu...ar(C))': (impl Fn(&str, T), Bar<u8>) + 141..154 '|input, t| {}': impl Fn(&str, T) 142..147 'input': &str 149..150 't': T 152..154 '{}': () @@ -1498,8 +1506,8 @@ fn main() { 71..105 '{ ...()); }': () 77..78 'f': fn f(&dyn Fn(S)) 77..102 'f(&|nu...foo())': () - 79..101 '&|numb....foo()': &|S| -> () - 80..101 '|numbe....foo()': |S| -> () + 79..101 '&|numb....foo()': &impl Fn(S) + 80..101 '|numbe....foo()': impl Fn(S) 81..87 'number': S 89..95 'number': S 89..101 'number.foo()': () @@ -1904,13 +1912,13 @@ fn test() { 131..132 'f': F 151..153 '{}': Lazy<T, F> 251..497 '{ ...o(); }': () - 261..266 'lazy1': Lazy<Foo, || -> Foo> - 283..292 'Lazy::new': fn new<Foo, || -> Foo>(|| -> Foo) -> Lazy<Foo, || -> Foo> - 283..300 'Lazy::...| Foo)': Lazy<Foo, || -> Foo> - 293..299 '|| Foo': || -> Foo + 261..266 'lazy1': Lazy<Foo, impl Fn() -> Foo> + 283..292 'Lazy::new': fn new<Foo, impl Fn() -> Foo>(impl Fn() -> Foo) -> Lazy<Foo, impl Fn() -> Foo> + 283..300 'Lazy::...| Foo)': Lazy<Foo, impl Fn() -> Foo> + 293..299 '|| Foo': impl Fn() -> Foo 296..299 'Foo': Foo 310..312 'r1': usize - 315..320 'lazy1': Lazy<Foo, || -> Foo> + 315..320 'lazy1': Lazy<Foo, impl Fn() -> Foo> 315..326 'lazy1.foo()': usize 368..383 'make_foo_fn_ptr': fn() -> Foo 399..410 'make_foo_fn': fn make_foo_fn() -> Foo @@ -1955,20 +1963,20 @@ fn test() { 163..167 '1u32': u32 174..175 'x': Option<u32> 174..190 'x.map(...v + 1)': Option<u32> - 180..189 '|v| v + 1': |u32| -> u32 + 180..189 '|v| v + 1': impl Fn(u32) -> u32 181..182 'v': u32 184..185 'v': u32 184..189 'v + 1': u32 188..189 '1': u32 196..197 'x': Option<u32> 196..212 'x.map(... 1u64)': Option<u64> - 202..211 '|_v| 1u64': |u32| -> u64 + 202..211 '|_v| 1u64': impl Fn(u32) -> u64 203..205 '_v': u32 207..211 '1u64': u64 222..223 'y': Option<i64> 239..240 'x': Option<u32> 239..252 'x.map(|_v| 1)': Option<i64> - 245..251 '|_v| 1': |u32| -> i64 + 245..251 '|_v| 1': impl Fn(u32) -> i64 246..248 '_v': u32 250..251 '1': i64 "#]], @@ -1997,11 +2005,11 @@ fn test<F: FnOnce(u32) -> u64>(f: F) { //^^^^ u64 let g = |v| v + 1; //^^^^^ u64 - //^^^^^^^^^ |u64| -> u64 + //^^^^^^^^^ impl Fn(u64) -> u64 g(1u64); //^^^^^^^ u64 let h = |v| 1u128 + v; - //^^^^^^^^^^^^^ |u128| -> u128 + //^^^^^^^^^^^^^ impl Fn(u128) -> u128 }"#, ); } @@ -2054,17 +2062,17 @@ fn test() { 312..314 '{}': () 330..489 '{ ... S); }': () 340..342 'x1': u64 - 345..349 'foo1': fn foo1<S, u64, |S| -> u64>(S, |S| -> u64) -> u64 + 345..349 'foo1': fn foo1<S, u64, impl Fn(S) -> u64>(S, impl Fn(S) -> u64) -> u64 345..368 'foo1(S...hod())': u64 350..351 'S': S - 353..367 '|s| s.method()': |S| -> u64 + 353..367 '|s| s.method()': impl Fn(S) -> u64 354..355 's': S 357..358 's': S 357..367 's.method()': u64 378..380 'x2': u64 - 383..387 'foo2': fn foo2<S, u64, |S| -> u64>(|S| -> u64, S) -> u64 + 383..387 'foo2': fn foo2<S, u64, impl Fn(S) -> u64>(impl Fn(S) -> u64, S) -> u64 383..406 'foo2(|...(), S)': u64 - 388..402 '|s| s.method()': |S| -> u64 + 388..402 '|s| s.method()': impl Fn(S) -> u64 389..390 's': S 392..393 's': S 392..402 's.method()': u64 @@ -2073,14 +2081,14 @@ fn test() { 421..422 'S': S 421..446 'S.foo1...hod())': u64 428..429 'S': S - 431..445 '|s| s.method()': |S| -> u64 + 431..445 '|s| s.method()': impl Fn(S) -> u64 432..433 's': S 435..436 's': S 435..445 's.method()': u64 456..458 'x4': u64 461..462 'S': S 461..486 'S.foo2...(), S)': u64 - 468..482 '|s| s.method()': |S| -> u64 + 468..482 '|s| s.method()': impl Fn(S) -> u64 469..470 's': S 472..473 's': S 472..482 's.method()': u64 @@ -2554,9 +2562,9 @@ fn main() { 72..74 '_v': F 117..120 '{ }': () 132..163 '{ ... }); }': () - 138..148 'f::<(), _>': fn f<(), |&()| -> ()>(|&()| -> ()) + 138..148 'f::<(), _>': fn f<(), impl Fn(&())>(impl Fn(&())) 138..160 'f::<()... z; })': () - 149..159 '|z| { z; }': |&()| -> () + 149..159 '|z| { z; }': impl Fn(&()) 150..151 'z': &() 153..159 '{ z; }': () 155..156 'z': &() @@ -2713,9 +2721,9 @@ fn main() { 983..998 'Vec::<i32>::new': fn new<i32>() -> Vec<i32> 983..1000 'Vec::<...:new()': Vec<i32> 983..1012 'Vec::<...iter()': IntoIter<i32> - 983..1075 'Vec::<...one })': FilterMap<IntoIter<i32>, |i32| -> Option<u32>> + 983..1075 'Vec::<...one })': FilterMap<IntoIter<i32>, impl Fn(i32) -> Option<u32>> 983..1101 'Vec::<... y; })': () - 1029..1074 '|x| if...None }': |i32| -> Option<u32> + 1029..1074 '|x| if...None }': impl Fn(i32) -> Option<u32> 1030..1031 'x': i32 1033..1074 'if x >...None }': Option<u32> 1036..1037 'x': i32 @@ -2728,7 +2736,7 @@ fn main() { 1049..1057 'x as u32': u32 1066..1074 '{ None }': Option<u32> 1068..1072 'None': Option<u32> - 1090..1100 '|y| { y; }': |u32| -> () + 1090..1100 '|y| { y; }': impl Fn(u32) 1091..1092 'y': u32 1094..1100 '{ y; }': () 1096..1097 'y': u32 @@ -2971,13 +2979,13 @@ fn foo() { 52..126 '{ ...)(s) }': () 62..63 's': Option<i32> 66..78 'Option::None': Option<i32> - 88..89 'f': |Option<i32>| -> () - 92..111 '|x: Op...2>| {}': |Option<i32>| -> () + 88..89 'f': impl Fn(Option<i32>) + 92..111 '|x: Op...2>| {}': impl Fn(Option<i32>) 93..94 'x': Option<i32> 109..111 '{}': () 117..124 '(&f)(s)': () - 118..120 '&f': &|Option<i32>| -> () - 119..120 'f': |Option<i32>| -> () + 118..120 '&f': &impl Fn(Option<i32>) + 119..120 'f': impl Fn(Option<i32>) 122..123 's': Option<i32> "#]], ); @@ -3043,7 +3051,7 @@ impl<T: ?Sized> core::ops::Deref for Box<T> { type Target = T; fn deref(&self) -> &T { - &self.inner + unsafe { &*self.inner } } } @@ -3054,23 +3062,25 @@ fn foo() { }"#, expect![[r#" 154..158 'self': &Box<T> - 166..193 '{ ... }': &T - 176..187 '&self.inner': &*mut T - 177..181 'self': &Box<T> - 177..187 'self.inner': *mut T - 206..296 '{ ...&s); }': () - 216..217 's': Option<i32> - 220..224 'None': Option<i32> - 234..235 'f': Box<dyn FnOnce(&Option<i32>)> - 269..282 'box (|ps| {})': Box<|&Option<i32>| -> ()> - 274..281 '|ps| {}': |&Option<i32>| -> () - 275..277 'ps': &Option<i32> - 279..281 '{}': () - 288..289 'f': Box<dyn FnOnce(&Option<i32>)> - 288..293 'f(&s)': () - 290..292 '&s': &Option<i32> - 291..292 's': Option<i32> - 269..282: expected Box<dyn FnOnce(&Option<i32>)>, got Box<|&Option<i32>| -> ()> + 166..205 '{ ... }': &T + 176..199 'unsafe...nner }': &T + 185..197 '&*self.inner': &T + 186..197 '*self.inner': T + 187..191 'self': &Box<T> + 187..197 'self.inner': *mut T + 218..308 '{ ...&s); }': () + 228..229 's': Option<i32> + 232..236 'None': Option<i32> + 246..247 'f': Box<dyn FnOnce(&Option<i32>)> + 281..294 'box (|ps| {})': Box<impl Fn(&Option<i32>)> + 286..293 '|ps| {}': impl Fn(&Option<i32>) + 287..289 'ps': &Option<i32> + 291..293 '{}': () + 300..301 'f': Box<dyn FnOnce(&Option<i32>)> + 300..305 'f(&s)': () + 302..304 '&s': &Option<i32> + 303..304 's': Option<i32> + 281..294: expected Box<dyn FnOnce(&Option<i32>)>, got Box<impl Fn(&Option<i32>)> "#]], ); } @@ -3709,7 +3719,6 @@ async fn get_accounts() -> Result<u32, ()> { #[test] fn local_impl_1() { - check!(block_local_impls); check_types( r#" trait Trait<T> { @@ -3731,7 +3740,6 @@ fn test() { #[test] fn local_impl_2() { - check!(block_local_impls); check_types( r#" struct S; @@ -3753,7 +3761,6 @@ fn test() { #[test] fn local_impl_3() { - check!(block_local_impls); check_types( r#" trait Trait<T> { @@ -3778,6 +3785,62 @@ fn test() { } #[test] +fn foreign_trait_with_local_trait_impl() { + check!(block_local_impls); + check( + r#" +mod module { + pub trait T { + const C: usize; + fn f(&self); + } +} + +fn f() { + use module::T; + impl T for usize { + const C: usize = 0; + fn f(&self) {} + } + 0usize.f(); + //^^^^^^^^^^ type: () + usize::C; + //^^^^^^^^type: usize +} +"#, + ); +} + +#[test] +fn regression_14443_trait_solve() { + check_no_mismatches( + r#" +trait T { + fn f(&self) {} +} + + +fn main() { + struct A; + impl T for A {} + + let a = A; + + let b = { + struct B; + impl T for B {} + + B + }; + + a.f(); + b.f(); +} +"#, + ) +} + +#[test] fn associated_type_sized_bounds() { check_infer( r#" @@ -4149,3 +4212,201 @@ fn test() { "#, ); } + +#[test] +fn associated_type_in_struct_expr_path() { + // FIXME: All annotation should be resolvable. + // For lines marked as unstable, see rust-lang/rust#86935. + // FIXME: Remove the comments once stablized. + check_types( + r#" +trait Trait { + type Assoc; + fn f(); +} + +struct S { x: u32 } + +impl Trait for () { + type Assoc = S; + + fn f() { + let x = 42; + let a = Self::Assoc { x }; + // ^ S + let a = <Self>::Assoc { x }; // unstable + // ^ {unknown} + + // should be `Copy` but we don't track ownership anyway. + let value = S { x }; + if let Self::Assoc { x } = value {} + // ^ u32 + if let <Self>::Assoc { x } = value {} // unstable + // ^ {unknown} + } +} + "#, + ); +} + +#[test] +fn associated_type_in_struct_expr_path_enum() { + // FIXME: All annotation should be resolvable. + // For lines marked as unstable, see rust-lang/rust#86935. + // FIXME: Remove the comments once stablized. + check_types( + r#" +trait Trait { + type Assoc; + fn f(); +} + +enum E { + Unit, + Struct { x: u32 }, +} + +impl Trait for () { + type Assoc = E; + + fn f() { + let a = Self::Assoc::Unit; + // ^ E + let a = <Self>::Assoc::Unit; + // ^ E + let a = <Self::Assoc>::Unit; + // ^ E + let a = <<Self>::Assoc>::Unit; + // ^ E + + // should be `Copy` but we don't track ownership anyway. + let value = E::Unit; + if let Self::Assoc::Unit = value {} + // ^^^^^^^^^^^^^^^^^ E + if let <Self>::Assoc::Unit = value {} + // ^^^^^^^^^^^^^^^^^^^ E + if let <Self::Assoc>::Unit = value {} + // ^^^^^^^^^^^^^^^^^^^ E + if let <<Self>::Assoc>::Unit = value {} + // ^^^^^^^^^^^^^^^^^^^^^ E + + let x = 42; + let a = Self::Assoc::Struct { x }; + // ^ E + let a = <Self>::Assoc::Struct { x }; // unstable + // ^ {unknown} + let a = <Self::Assoc>::Struct { x }; // unstable + // ^ {unknown} + let a = <<Self>::Assoc>::Struct { x }; // unstable + // ^ {unknown} + + // should be `Copy` but we don't track ownership anyway. + let value = E::Struct { x: 42 }; + if let Self::Assoc::Struct { x } = value {} + // ^ u32 + if let <Self>::Assoc::Struct { x } = value {} // unstable + // ^ {unknown} + if let <Self::Assoc>::Struct { x } = value {} // unstable + // ^ {unknown} + if let <<Self>::Assoc>::Struct { x } = value {} // unstable + // ^ {unknown} + } +} + "#, + ); +} + +#[test] +fn derive_macro_bounds() { + check_types( + r#" + //- minicore: clone, derive + #[derive(Clone)] + struct Copy; + struct NotCopy; + #[derive(Clone)] + struct Generic<T>(T); + trait Tr { + type Assoc; + } + impl Tr for Copy { + type Assoc = NotCopy; + } + #[derive(Clone)] + struct AssocGeneric<T: Tr>(T::Assoc); + + #[derive(Clone)] + struct AssocGeneric2<T: Tr>(<T as Tr>::Assoc); + + #[derive(Clone)] + struct AssocGeneric3<T: Tr>(Generic<T::Assoc>); + + #[derive(Clone)] + struct Vec<T>(); + + #[derive(Clone)] + struct R1(Vec<R2>); + #[derive(Clone)] + struct R2(R1); + + fn f() { + let x = (&Copy).clone(); + //^ Copy + let x = (&NotCopy).clone(); + //^ &NotCopy + let x = (&Generic(Copy)).clone(); + //^ Generic<Copy> + let x = (&Generic(NotCopy)).clone(); + //^ &Generic<NotCopy> + let x: &AssocGeneric<Copy> = &AssocGeneric(NotCopy); + let x = x.clone(); + //^ &AssocGeneric<Copy> + let x: &AssocGeneric2<Copy> = &AssocGeneric2(NotCopy); + let x = x.clone(); + //^ &AssocGeneric2<Copy> + let x: &AssocGeneric3<Copy> = &AssocGeneric3(Generic(NotCopy)); + let x = x.clone(); + //^ &AssocGeneric3<Copy> + let x = (&R1(Vec())).clone(); + //^ R1 + let x = (&R2(R1(Vec()))).clone(); + //^ R2 + } + "#, + ); +} + +#[test] +fn trait_obligations_should_be_registered_during_path_inference() { + check_types( + r#" +//- minicore: fn, from +struct S<T>(T); +fn map<T, U, F: FnOnce(T) -> S<U>>(_: T, _: F) -> U { loop {} } + +fn test(v: S<i32>) { + let res = map(v, Into::into); + //^^^ i32 +} +"#, + ); +} + +#[test] +fn fn_obligation_should_be_registered_during_path_inference() { + check_types( + r#" +//- minicore: fn, from +struct S<T>(T); +impl<T> S<T> { + fn foo<U: Into<S<T>>>(_: U) -> Self { loop {} } +} +fn map<T, U, F: FnOnce(T) -> U>(_: T, _: F) -> U { loop {} } + +fn test(v: S<i32>) { + let res = map(v, S::foo); + //^^^ S<i32> +} +"#, + ); +} |