Skip to content

Commit fde5564

Browse files
committed
Auto merge of rust-lang#17505 - ShoyuVanilla:issue-17199, r=Veykril
Use proper `ImplTraits` in `insert_inference_vars_for_impl_trait` Fixes rust-lang#17199 and fixes rust-lang#17403 In the previous implementation, I passed `rpits` as a function parameter and used `idx` of `ImplTraitId` for indexing `ImplTrait`. https://github.com/rust-lang/rust-analyzer/blob/4e836c622a7bdab41be8e82733dd9fe40af128b2/crates/hir-ty/src/infer.rs#L881-L887 But that `idx` is rather a "local" one, so in the cases like mentioned issues, the async function that can be expanded roughly as ```rust type TypeAlias = impl Something; fn expanded_async() -> impl Future<Output = TypeAlias> { ... } ``` there are two bundles of `ImplTraits`; one for the `impl Future` and the other one for `TypeAlias`. So using `idx` with `rpits` returns `ImplTrait` for `impl Future` even if we are asking for `TypeAlias` and this caused a stack overflow. This PR is a fix for that implementation miss 😅
2 parents af8575e + 4b7fb6a commit fde5564

File tree

2 files changed

+38
-31
lines changed

2 files changed

+38
-31
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/infer.rs

+19-31
Original file line numberDiff line numberDiff line change
@@ -835,11 +835,7 @@ impl<'a> InferenceContext<'a> {
835835
let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
836836
// RPIT opaque types use substitution of their parent function.
837837
let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
838-
let result = self.insert_inference_vars_for_impl_trait(
839-
return_ty,
840-
rpits.clone(),
841-
fn_placeholders,
842-
);
838+
let result = self.insert_inference_vars_for_impl_trait(return_ty, fn_placeholders);
843839
let rpits = rpits.skip_binders();
844840
for (id, _) in rpits.impl_traits.iter() {
845841
if let Entry::Vacant(e) = self.result.type_of_rpit.entry(id) {
@@ -862,12 +858,7 @@ impl<'a> InferenceContext<'a> {
862858
self.insert_atpit_coercion_table(params_and_ret_tys.iter());
863859
}
864860

865-
fn insert_inference_vars_for_impl_trait<T>(
866-
&mut self,
867-
t: T,
868-
rpits: Arc<chalk_ir::Binders<crate::ImplTraits>>,
869-
placeholders: Substitution,
870-
) -> T
861+
fn insert_inference_vars_for_impl_trait<T>(&mut self, t: T, placeholders: Substitution) -> T
871862
where
872863
T: crate::HasInterner<Interner = Interner> + crate::TypeFoldable<Interner>,
873864
{
@@ -878,25 +869,30 @@ impl<'a> InferenceContext<'a> {
878869
TyKind::OpaqueType(opaque_ty_id, _) => *opaque_ty_id,
879870
_ => return ty,
880871
};
881-
let idx = match self.db.lookup_intern_impl_trait_id(opaque_ty_id.into()) {
882-
ImplTraitId::ReturnTypeImplTrait(_, idx) => idx,
883-
ImplTraitId::AssociatedTypeImplTrait(_, idx) => idx,
884-
_ => unreachable!(),
872+
let (impl_traits, idx) =
873+
match self.db.lookup_intern_impl_trait_id(opaque_ty_id.into()) {
874+
ImplTraitId::ReturnTypeImplTrait(def, idx) => {
875+
(self.db.return_type_impl_traits(def), idx)
876+
}
877+
ImplTraitId::AssociatedTypeImplTrait(def, idx) => {
878+
(self.db.type_alias_impl_traits(def), idx)
879+
}
880+
_ => unreachable!(),
881+
};
882+
let Some(impl_traits) = impl_traits else {
883+
return ty;
885884
};
886-
let bounds =
887-
(*rpits).map_ref(|rpits| rpits.impl_traits[idx].bounds.map_ref(|it| it.iter()));
885+
let bounds = (*impl_traits)
886+
.map_ref(|rpits| rpits.impl_traits[idx].bounds.map_ref(|it| it.iter()));
888887
let var = self.table.new_type_var();
889888
let var_subst = Substitution::from1(Interner, var.clone());
890889
for bound in bounds {
891890
let predicate = bound.map(|it| it.cloned()).substitute(Interner, &placeholders);
892891
let (var_predicate, binders) =
893892
predicate.substitute(Interner, &var_subst).into_value_and_skipped_binders();
894893
always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
895-
let var_predicate = self.insert_inference_vars_for_impl_trait(
896-
var_predicate,
897-
rpits.clone(),
898-
placeholders.clone(),
899-
);
894+
let var_predicate = self
895+
.insert_inference_vars_for_impl_trait(var_predicate, placeholders.clone());
900896
self.push_obligation(var_predicate.cast(Interner));
901897
}
902898
self.result.type_of_rpit.insert(idx, var.clone());
@@ -983,16 +979,8 @@ impl<'a> InferenceContext<'a> {
983979
self.db.lookup_intern_impl_trait_id(opaque_ty_id.into())
984980
{
985981
if assoc_tys.contains(&alias_id) {
986-
let atpits = self
987-
.db
988-
.type_alias_impl_traits(alias_id)
989-
.expect("Marked as ATPIT but no impl traits!");
990982
let alias_placeholders = TyBuilder::placeholder_subst(self.db, alias_id);
991-
let ty = self.insert_inference_vars_for_impl_trait(
992-
ty,
993-
atpits,
994-
alias_placeholders,
995-
);
983+
let ty = self.insert_inference_vars_for_impl_trait(ty, alias_placeholders);
996984
return Some((opaque_ty_id, ty));
997985
}
998986
}

src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1999,3 +1999,22 @@ where
19991999
"#,
20002000
);
20012001
}
2002+
2003+
#[test]
2004+
fn tait_async_stack_overflow_17199() {
2005+
check_types(
2006+
r#"
2007+
//- minicore: fmt, future
2008+
type Foo = impl core::fmt::Debug;
2009+
2010+
async fn foo() -> Foo {
2011+
()
2012+
}
2013+
2014+
async fn test() {
2015+
let t = foo().await;
2016+
// ^ impl Debug
2017+
}
2018+
"#,
2019+
);
2020+
}

0 commit comments

Comments
 (0)