Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13750 - lowr:fix/rpit-in-projection, r=flodiebold
fix: normalize projection after discarding free `BoundVar`s in RPIT Fixes #13307 When we lower the return type of a function, it may contain free `BoundVar`s in `OpaqueType`'s substitution, which would cause panic during canonicalization as part of projection normalization. Those `BoundVar`s are irrelevant in this context and will be discarded, and we should defer projection normalization until then.
bors 2022-12-10
parent 518e39b · parent 34b11d9 · commit 632f804
-rw-r--r--crates/hir-ty/src/infer.rs38
-rw-r--r--crates/hir-ty/src/tests/traits.rs16
2 files changed, 34 insertions, 20 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 874a54fc3e..ad7ec485e9 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -503,7 +503,7 @@ impl<'a> InferenceContext<'a> {
result: InferenceResult::default(),
table: unify::InferenceTable::new(db, trait_env.clone()),
trait_env,
- return_ty: TyKind::Error.intern(Interner), // set in collect_fn_signature
+ return_ty: TyKind::Error.intern(Interner), // set in collect_* calls
resume_yield_tys: None,
db,
owner,
@@ -582,14 +582,17 @@ impl<'a> InferenceContext<'a> {
} else {
&*data.ret_type
};
- let return_ty = self.make_ty_with_mode(return_ty, ImplTraitLoweringMode::Opaque);
- self.return_ty = return_ty;
- if let Some(rpits) = self.db.return_type_impl_traits(func) {
+ let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
+ .with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
+ let return_ty = ctx.lower_ty(return_ty);
+ let return_ty = self.insert_type_vars(return_ty);
+
+ let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
// RPIT opaque types use substitution of their parent function.
let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
- self.return_ty = fold_tys(
- self.return_ty.clone(),
+ fold_tys(
+ return_ty,
|ty, _| {
let opaque_ty_id = match ty.kind(Interner) {
TyKind::OpaqueType(opaque_ty_id, _) => *opaque_ty_id,
@@ -610,14 +613,18 @@ impl<'a> InferenceContext<'a> {
let (var_predicate, binders) = predicate
.substitute(Interner, &var_subst)
.into_value_and_skipped_binders();
- always!(binders.len(Interner) == 0); // quantified where clauses not yet handled
+ always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
self.push_obligation(var_predicate.cast(Interner));
}
var
},
DebruijnIndex::INNERMOST,
- );
- }
+ )
+ } else {
+ return_ty
+ };
+
+ self.return_ty = self.normalize_associated_types_in(return_ty);
}
fn infer_body(&mut self) {
@@ -652,23 +659,14 @@ impl<'a> InferenceContext<'a> {
self.result.diagnostics.push(diagnostic);
}
- fn make_ty_with_mode(
- &mut self,
- type_ref: &TypeRef,
- impl_trait_mode: ImplTraitLoweringMode,
- ) -> Ty {
+ fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
// FIXME use right resolver for block
- let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
- .with_impl_trait_mode(impl_trait_mode);
+ let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
let ty = ctx.lower_ty(type_ref);
let ty = self.insert_type_vars(ty);
self.normalize_associated_types_in(ty)
}
- fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
- self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Disallowed)
- }
-
fn err_ty(&self) -> Ty {
self.result.standard_types.unknown.clone()
}
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 3d7194b6f4..a9fd01ee01 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -1389,6 +1389,22 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
}
#[test]
+fn return_pos_impl_trait_in_projection() {
+ // Note that the unused type param `X` is significant; see #13307.
+ check_no_mismatches(
+ r#"
+//- minicore: sized
+trait Future { type Output; }
+impl Future for () { type Output = i32; }
+type Foo<F> = (<F as Future>::Output, F);
+fn foo<X>() -> Foo<impl Future<Output = ()>> {
+ (0, ())
+}
+"#,
+ )
+}
+
+#[test]
fn dyn_trait() {
check_infer(
r#"