diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 016edb2310eb..953470e1ddcc 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1597,7 +1597,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> { tried_resolving_once = true; ty = self.table.insert_type_vars(ty); - ty = self.table.normalize_associated_types_in(ty); ty = self.table.structurally_resolve_type(ty); if ty.is_ty_error() { return (self.err_ty(), None); diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs index c128977d7b08..eeed8713dea9 100644 --- a/crates/hir-ty/src/infer/cast.rs +++ b/crates/hir-ty/src/infer/cast.rs @@ -110,8 +110,8 @@ impl<'db> CastCheck<'db> { &mut self, ctx: &mut InferenceContext<'_, 'db>, ) -> Result<(), InferenceDiagnostic<'db>> { - self.expr_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.expr_ty); - self.cast_ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(self.cast_ty); + self.expr_ty = ctx.table.try_structurally_resolve_type(self.expr_ty); + self.cast_ty = ctx.table.try_structurally_resolve_type(self.cast_ty); // This should always come first so that we apply the coercion, which impacts infer vars. if ctx @@ -159,7 +159,7 @@ impl<'db> CastCheck<'db> { TyKind::FnDef(..) => { let sig = self.expr_ty.callable_sig(ctx.interner()).expect("FnDef had no sig"); - let sig = ctx.table.eagerly_normalize_and_resolve_shallow_in(sig); + let sig = ctx.table.normalize_associated_types_in(sig); let fn_ptr = Ty::new_fn_ptr(ctx.interner(), sig); if ctx .coerce( @@ -191,7 +191,7 @@ impl<'db> CastCheck<'db> { }, // array-ptr-cast CastTy::Ptr(t, m) => { - let t = ctx.table.eagerly_normalize_and_resolve_shallow_in(t); + let t = ctx.table.try_structurally_resolve_type(t); if !ctx.table.is_sized(t) { return Err(CastError::IllegalCast); } @@ -375,7 +375,7 @@ fn pointer_kind<'db>( ty: Ty<'db>, ctx: &mut InferenceContext<'_, 'db>, ) -> Result>, ()> { - let ty = ctx.table.eagerly_normalize_and_resolve_shallow_in(ty); + let ty = ctx.table.try_structurally_resolve_type(ty); if ctx.table.is_sized(ty) { return Ok(Some(PointerKind::Thin)); diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index b7ab109b3b9d..285c1ee50293 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -1819,7 +1819,7 @@ impl<'db> InferenceContext<'_, 'db> { indices_to_skip, is_varargs, ); - self.table.normalize_associated_types_in(ret_ty) + self.table.structurally_resolve_type(ret_ty) } fn infer_method_call( @@ -1999,7 +1999,7 @@ impl<'db> InferenceContext<'_, 'db> { self.table.unify(formal_receiver_ty, receiver_ty); self.check_call_arguments(tgt_expr, ¶m_tys, ret_ty, expected, args, &[], is_varargs); - self.table.normalize_associated_types_in(ret_ty) + self.table.structurally_resolve_type(ret_ty) } /// Generic function that factors out common logic from function calls, diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 59e8d84190f0..646b67015dd2 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -298,17 +298,6 @@ impl<'db> InferenceTable<'db> { .unwrap_or(ty) } - /// Works almost same as [`Self::normalize_associated_types_in`], but this also resolves shallow - /// the inference variables - pub(crate) fn eagerly_normalize_and_resolve_shallow_in(&mut self, ty: T) -> T - where - T: TypeFoldable>, - { - let ty = self.resolve_vars_with_obligations(ty); - let ty = self.normalize_associated_types_in(ty); - self.resolve_vars_with_obligations(ty) - } - pub(crate) fn normalize_alias_ty(&mut self, alias: Ty<'db>) -> Ty<'db> { self.infer_ctxt .at(&ObligationCause::new(), self.trait_env.env) @@ -762,7 +751,7 @@ impl<'db> InferenceTable<'db> { } let mut ty = ty; - ty = self.eagerly_normalize_and_resolve_shallow_in(ty); + ty = self.try_structurally_resolve_type(ty); if let Some(sized) = short_circuit_trivial_tys(ty) { return sized; } @@ -784,7 +773,7 @@ impl<'db> InferenceTable<'db> { // Structs can have DST as its last field and such cases are not handled // as unsized by the chalk, so we do this manually. ty = last_field_ty; - ty = self.eagerly_normalize_and_resolve_shallow_in(ty); + ty = self.try_structurally_resolve_type(ty); if let Some(sized) = short_circuit_trivial_tys(ty) { return sized; } diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs index 2f41de64cbbd..f669fb68a8da 100644 --- a/crates/hir-ty/src/tests/macros.rs +++ b/crates/hir-ty/src/tests/macros.rs @@ -197,7 +197,7 @@ fn expr_macro_def_expanded_in_various_places() { 39..442 '{ ...!(); }': {unknown} 73..94 'spam!(...am!())': {unknown} 100..119 'for _ ...!() {}': fn into_iter(isize) -> ::IntoIter - 100..119 'for _ ...!() {}': ::IntoIter + 100..119 'for _ ...!() {}': {unknown} 100..119 'for _ ...!() {}': ! 100..119 'for _ ...!() {}': {unknown} 100..119 'for _ ...!() {}': &'? mut {unknown} @@ -291,7 +291,7 @@ fn expr_macro_rules_expanded_in_various_places() { 53..456 '{ ...!(); }': {unknown} 87..108 'spam!(...am!())': {unknown} 114..133 'for _ ...!() {}': fn into_iter(isize) -> ::IntoIter - 114..133 'for _ ...!() {}': ::IntoIter + 114..133 'for _ ...!() {}': {unknown} 114..133 'for _ ...!() {}': ! 114..133 'for _ ...!() {}': {unknown} 114..133 'for _ ...!() {}': &'? mut {unknown} diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs index 4d68179a88b8..ef60c1e9f57a 100644 --- a/crates/hir-ty/src/tests/never_type.rs +++ b/crates/hir-ty/src/tests/never_type.rs @@ -362,7 +362,7 @@ fn diverging_expression_3_break() { 140..141 'x': u32 149..175 '{ for ...; }; }': u32 151..172 'for a ...eak; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter - 151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter + 151..172 'for a ...eak; }': {unknown} 151..172 'for a ...eak; }': ! 151..172 'for a ...eak; }': {unknown} 151..172 'for a ...eak; }': &'? mut {unknown} @@ -379,7 +379,7 @@ fn diverging_expression_3_break() { 226..227 'x': u32 235..253 '{ for ... {}; }': u32 237..250 'for a in b {}': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter - 237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter + 237..250 'for a in b {}': {unknown} 237..250 'for a in b {}': ! 237..250 'for a in b {}': {unknown} 237..250 'for a in b {}': &'? mut {unknown} @@ -395,7 +395,7 @@ fn diverging_expression_3_break() { 304..305 'x': u32 313..340 '{ for ...; }; }': u32 315..337 'for a ...urn; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter - 315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter + 315..337 'for a ...urn; }': {unknown} 315..337 'for a ...urn; }': ! 315..337 'for a ...urn; }': {unknown} 315..337 'for a ...urn; }': &'? mut {unknown} diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index 607daada42eb..cb07e15b8666 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -48,7 +48,7 @@ fn infer_pattern() { 83..84 '1': i32 86..93 '"hello"': &'static str 101..151 'for (e... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter - 101..151 'for (e... }': <{unknown} as IntoIterator>::IntoIter + 101..151 'for (e... }': {unknown} 101..151 'for (e... }': ! 101..151 'for (e... }': {unknown} 101..151 'for (e... }': &'? mut {unknown} diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs index 75d32035d099..09a03278ebd9 100644 --- a/crates/hir-ty/src/tests/regression.rs +++ b/crates/hir-ty/src/tests/regression.rs @@ -269,7 +269,7 @@ fn infer_std_crash_5() { expect![[r#" 26..322 '{ ... } }': () 32..320 'for co... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter - 32..320 'for co... }': <{unknown} as IntoIterator>::IntoIter + 32..320 'for co... }': {unknown} 32..320 'for co... }': ! 32..320 'for co... }': {unknown} 32..320 'for co... }': &'? mut {unknown} @@ -1255,7 +1255,7 @@ fn test() { expect![[r#" 10..68 '{ ... } }': () 16..66 'for _ ... }': fn into_iter<()>(()) -> <() as IntoIterator>::IntoIter - 16..66 'for _ ... }': <() as IntoIterator>::IntoIter + 16..66 'for _ ... }': {unknown} 16..66 'for _ ... }': ! 16..66 'for _ ... }': {unknown} 16..66 'for _ ... }': &'? mut {unknown} diff --git a/crates/hir-ty/src/tests/regression/new_solver.rs b/crates/hir-ty/src/tests/regression/new_solver.rs index 90c81d1e8f3e..e7ca9bebfee5 100644 --- a/crates/hir-ty/src/tests/regression/new_solver.rs +++ b/crates/hir-ty/src/tests/regression/new_solver.rs @@ -552,3 +552,89 @@ where "#]], ); } + +#[test] +fn regression_20975() { + check_infer( + r#" +//- minicore: future, iterators, range +use core::future::Future; + +struct Foo(T); + +trait X {} + +impl X for i32 {} +impl X for i64 {} + +impl Iterator for Foo { + type Item = T; + fn next(&mut self) -> Option { + self.next_spec() + } +} + +trait Bar { + type Item; + + fn next_spec(&mut self) -> Option; +} + +impl Bar for Foo { + type Item = T; + + fn next_spec(&mut self) -> Option { + None + } +} + +struct JoinAll +where + F: Future, +{ + f: F, +} + +fn join_all(iter: I) -> JoinAll<::Item> +where + I: IntoIterator, + ::Item: Future, +{ + loop {} +} + +fn main() { + let x = Foo(42).filter_map(|_| Some(async {})); + join_all(x); +} +"#, + expect![[r#" + 164..168 'self': &'? mut Foo + 192..224 '{ ... }': Option + 202..206 'self': &'? mut Foo + 202..218 'self.n...spec()': Option + 278..282 'self': &'? mut Self + 380..384 'self': &'? mut Foo + 408..428 '{ ... }': Option + 418..422 'None': Option + 501..505 'iter': I + 614..629 '{ loop {} }': JoinAll + 620..627 'loop {}': ! + 625..627 '{}': () + 641..713 '{ ...(x); }': () + 651..652 'x': FilterMap, impl FnMut(i32) -> Option>> + 655..658 'Foo': fn Foo(i32) -> Foo + 655..662 'Foo(42)': Foo + 655..693 'Foo(42...c {}))': FilterMap, impl FnMut(i32) -> Option>> + 659..661 '42': i32 + 674..692 '|_| So...nc {})': impl FnMut(i32) -> Option> + 675..676 '_': i32 + 678..682 'Some': fn Some>(impl Future) -> Option> + 678..692 'Some(async {})': Option> + 683..691 'async {}': impl Future + 699..707 'join_all': fn join_all, impl FnMut(i32) -> Option>>>(FilterMap, impl FnMut(i32) -> Option>>) -> JoinAll<, impl FnMut(i32) -> Option>> as IntoIterator>::Item> + 699..710 'join_all(x)': JoinAll> + 708..709 'x': FilterMap, impl FnMut(i32) -> Option>> + "#]], + ); +} diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index c2392b36baba..9834de558397 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -3891,7 +3891,7 @@ fn foo() { expect![[r#" 110..127 '{ ...z(); }': () 116..122 'T::baz': fn baz() -> <{unknown} as Foo>::Gat<'?> - 116..124 'T::baz()': <{unknown} as Foo>::Gat<'?> + 116..124 'T::baz()': {unknown} "#]], ); } diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index c0e439310e98..640c9e53e212 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -4274,7 +4274,7 @@ fn f<'a>(v: &dyn Trait = &'a i32>) { 127..128 'v': &'? (dyn Trait = &'a i32> + 'static) 164..195 '{ ...f(); }': () 170..171 'v': &'? (dyn Trait = &'a i32> + 'static) - 170..184 'v.get::()': = &'a i32> + 'static as Trait>::Assoc + 170..184 'v.get::()': {unknown} 170..192 'v.get:...eref()': {unknown} "#]], );