Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/tests/regression/new_solver.rs')
| -rw-r--r-- | crates/hir-ty/src/tests/regression/new_solver.rs | 283 |
1 files changed, 279 insertions, 4 deletions
diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs index ead79a8f5b..5c1f85cb2a 100644 --- a/crates/hir-ty/src/tests/regression/new_solver.rs +++ b/crates/hir-ty/src/tests/regression/new_solver.rs @@ -1,6 +1,6 @@ use expect_test::expect; -use crate::tests::{check_infer, check_no_mismatches}; +use crate::tests::{check_infer, check_no_mismatches, check_types}; #[test] fn regression_20365() { @@ -84,7 +84,7 @@ fn test() -> i32 { 307..359 'core::...n Foo)': DynMetadata<dyn Foo + '?> 327..328 '0': usize 327..340 '0 as *const F': *const F - 327..358 '0 as *...yn Foo': *const (dyn Foo + '?) + 327..358 '0 as *...yn Foo': *const (dyn Foo + 'static) 370..371 'f': F 374..378 'F {}': F 388..395 'fat_ptr': *const (dyn Foo + '?) @@ -180,7 +180,7 @@ impl<'a> IntoIterator for &'a Grid { "#, expect![[r#" 150..154 'self': &'a Grid - 174..181 '{ }': impl Iterator<Item = &'a ()> + 174..181 '{ }': () "#]], ); } @@ -414,7 +414,282 @@ fn foo() { 244..246 '_x': {unknown} 249..257 'to_bytes': fn to_bytes() -> [u8; _] 249..259 'to_bytes()': [u8; _] - 249..268 'to_byt..._vec()': Vec<<[u8; _] as Foo>::Item> + 249..268 'to_byt..._vec()': {unknown} + "#]], + ); +} + +#[test] +fn regression_19637() { + check_no_mismatches( + r#" +//- minicore: coerce_unsized +pub trait Any {} + +impl<T: 'static> Any for T {} + +pub trait Trait: Any { + type F; +} + +pub struct TT {} + +impl Trait for TT { + type F = f32; +} + +pub fn coercion(x: &mut dyn Any) -> &mut dyn Any { + x +} + +fn main() { + let mut t = TT {}; + let tt = &mut t as &mut dyn Trait<F = f32>; + let st = coercion(tt); +} + "#, + ); +} + +#[test] +fn double_into_iter() { + check_types( + r#" +//- minicore: iterator + +fn intoiter_issue<A, B>(foo: A) +where + A: IntoIterator<Item = B>, + B: IntoIterator<Item = usize>, +{ + for x in foo { + // ^ B + for m in x { + // ^ usize + } + } +} +"#, + ); +} + +#[test] +fn regression_16282() { + check_infer( + r#" +//- minicore: coerce_unsized, dispatch_from_dyn +trait MapLookup<Q> { + type MapValue; +} + +impl<K> MapLookup<K> for K { + type MapValue = K; +} + +trait Map: MapLookup<<Self as Map>::Key> { + type Key; +} + +impl<K> Map for K { + type Key = K; +} + + +fn main() { + let _ = &() + as &dyn Map<Key=u32,MapValue=u32>; +} +"#, + expect![[r#" + 210..272 '{ ...32>; }': () + 220..221 '_': &'? (dyn Map<MapValue = u32, Key = u32> + '?) + 224..227 '&()': &'? () + 224..269 '&() ...e=u32>': &'? (dyn Map<MapValue = u32, Key = u32> + 'static) + 225..227 '()': () + "#]], + ); +} + +#[test] +fn regression_18692() { + check_no_mismatches( + r#" +//- minicore: coerce_unsized, dispatch_from_dyn, send +trait Trait: Send {} + +fn f(_: *const (dyn Trait + Send)) {} +fn g(it: *const (dyn Trait)) { + f(it); +} +"#, + ); +} + +#[test] +fn regression_20951() { + check_infer( + r#" +//- minicore: async_fn +trait DoesSomething { + fn do_something(&self) -> impl Future<Output = usize>; +} + +impl<F> DoesSomething for F +where + F: AsyncFn() -> usize, +{ + fn do_something(&self) -> impl Future<Output = usize> { + self() + } +} +"#, + expect![[r#" + 43..47 'self': &'? Self + 168..172 'self': &'? F + 205..227 '{ ... }': <F as AsyncFnMut<()>>::CallRefFuture<'<erased>> + 215..219 'self': &'? F + 215..221 'self()': <F as AsyncFnMut<()>>::CallRefFuture<'<erased>> + "#]], + ); +} + +#[test] +fn regression_19957() { + // This test documents issue #19957: async-trait patterns incorrectly produce + // type mismatches between Pin<Box<dyn Future>> and Pin<Box<impl Future>>. + check_no_mismatches( + r#" +//- minicore: future, pin, result, error, send, coerce_unsized, dispatch_from_dyn +use core::{future::Future, pin::Pin}; + +#[lang = "owned_box"] +pub struct Box<T: ?Sized> { + inner: *mut T, +} + +impl<T> Box<T> { + fn pin(value: T) -> Pin<Box<T>> { + // Implementation details don't matter here for type checking + loop {} + } +} + +impl<T: ?Sized + core::marker::Unsize<U>, U: ?Sized> core::ops::CoerceUnsized<Box<U>> for Box<T> {} + +impl<T: ?Sized + core::ops::DispatchFromDyn<U>, U: ?Sized> core::ops::DispatchFromDyn<Box<U>> for Box<T> {} + +pub struct ExampleData { + pub id: i32, +} + +// Simulates what #[async_trait] expands to +pub trait SimpleModel { + fn save<'life0, 'async_trait>( + &'life0 self, + ) -> Pin<Box<dyn Future<Output = i32> + Send + 'async_trait>> + where + 'life0: 'async_trait, + Self: 'async_trait; +} + +impl SimpleModel for ExampleData { + fn save<'life0, 'async_trait>( + &'life0 self, + ) -> Pin<Box<dyn Future<Output = i32> + Send + 'async_trait>> + where + 'life0: 'async_trait, + Self: 'async_trait, + { + // Body creates Pin<Box<impl Future>>, which should coerce to Pin<Box<dyn Future>> + Box::pin(async move { self.id }) + } +} +"#, + ) +} + +#[test] +fn regression_20975() { + check_infer( + r#" +//- minicore: future, iterators, range +use core::future::Future; + +struct Foo<T>(T); + +trait X {} + +impl X for i32 {} +impl X for i64 {} + +impl<T: X> Iterator for Foo<T> { + type Item = T; + fn next(&mut self) -> Option<Self::Item> { + self.next_spec() + } +} + +trait Bar { + type Item; + + fn next_spec(&mut self) -> Option<Self::Item>; +} + +impl<T: X> Bar for Foo<T> { + type Item = T; + + fn next_spec(&mut self) -> Option<Self::Item> { + None + } +} + +struct JoinAll<F> +where + F: Future, +{ + f: F, +} + +fn join_all<I>(iter: I) -> JoinAll<<I as IntoIterator>::Item> +where + I: IntoIterator, + <I as IntoIterator>::Item: Future, +{ + loop {} +} + +fn main() { + let x = Foo(42).filter_map(|_| Some(async {})); + join_all(x); +} +"#, + expect![[r#" + 164..168 'self': &'? mut Foo<T> + 192..224 '{ ... }': Option<T> + 202..206 'self': &'? mut Foo<T> + 202..218 'self.n...spec()': Option<T> + 278..282 'self': &'? mut Self + 380..384 'self': &'? mut Foo<T> + 408..428 '{ ... }': Option<T> + 418..422 'None': Option<T> + 501..505 'iter': I + 614..629 '{ loop {} }': JoinAll<impl Future> + 620..627 'loop {}': ! + 625..627 '{}': () + 641..713 '{ ...(x); }': () + 651..652 'x': FilterMap<Foo<i32>, impl FnMut(i32) -> Option<impl Future<Output = ()>>> + 655..658 'Foo': fn Foo<i32>(i32) -> Foo<i32> + 655..662 'Foo(42)': Foo<i32> + 655..693 'Foo(42...c {}))': FilterMap<Foo<i32>, impl FnMut(i32) -> Option<impl Future<Output = ()>>> + 659..661 '42': i32 + 674..692 '|_| So...nc {})': impl FnMut(i32) -> Option<impl Future<Output = ()>> + 675..676 '_': i32 + 678..682 'Some': fn Some<impl Future<Output = ()>>(impl Future<Output = ()>) -> Option<impl Future<Output = ()>> + 678..692 'Some(async {})': Option<impl Future<Output = ()>> + 683..691 'async {}': impl Future<Output = ()> + 699..707 'join_all': fn join_all<FilterMap<Foo<i32>, impl FnMut(i32) -> Option<impl Future<Output = ()>>>>(FilterMap<Foo<i32>, impl FnMut(i32) -> Option<impl Future<Output = ()>>>) -> JoinAll<<FilterMap<Foo<i32>, impl FnMut(i32) -> Option<impl Future<Output = ()>>> as IntoIterator>::Item> + 699..710 'join_all(x)': JoinAll<impl Future<Output = ()>> + 708..709 'x': FilterMap<Foo<i32>, impl FnMut(i32) -> Option<impl Future<Output = ()>>> "#]], ); } |