Skip to content

Commit 632f804

Browse files
committed
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.
2 parents 518e39b + 34b11d9 commit 632f804

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

crates/hir-ty/src/infer.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ impl<'a> InferenceContext<'a> {
503503
result: InferenceResult::default(),
504504
table: unify::InferenceTable::new(db, trait_env.clone()),
505505
trait_env,
506-
return_ty: TyKind::Error.intern(Interner), // set in collect_fn_signature
506+
return_ty: TyKind::Error.intern(Interner), // set in collect_* calls
507507
resume_yield_tys: None,
508508
db,
509509
owner,
@@ -582,14 +582,17 @@ impl<'a> InferenceContext<'a> {
582582
} else {
583583
&*data.ret_type
584584
};
585-
let return_ty = self.make_ty_with_mode(return_ty, ImplTraitLoweringMode::Opaque);
586-
self.return_ty = return_ty;
587585

588-
if let Some(rpits) = self.db.return_type_impl_traits(func) {
586+
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
587+
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
588+
let return_ty = ctx.lower_ty(return_ty);
589+
let return_ty = self.insert_type_vars(return_ty);
590+
591+
let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
589592
// RPIT opaque types use substitution of their parent function.
590593
let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
591-
self.return_ty = fold_tys(
592-
self.return_ty.clone(),
594+
fold_tys(
595+
return_ty,
593596
|ty, _| {
594597
let opaque_ty_id = match ty.kind(Interner) {
595598
TyKind::OpaqueType(opaque_ty_id, _) => *opaque_ty_id,
@@ -610,14 +613,18 @@ impl<'a> InferenceContext<'a> {
610613
let (var_predicate, binders) = predicate
611614
.substitute(Interner, &var_subst)
612615
.into_value_and_skipped_binders();
613-
always!(binders.len(Interner) == 0); // quantified where clauses not yet handled
616+
always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
614617
self.push_obligation(var_predicate.cast(Interner));
615618
}
616619
var
617620
},
618621
DebruijnIndex::INNERMOST,
619-
);
620-
}
622+
)
623+
} else {
624+
return_ty
625+
};
626+
627+
self.return_ty = self.normalize_associated_types_in(return_ty);
621628
}
622629

623630
fn infer_body(&mut self) {
@@ -652,23 +659,14 @@ impl<'a> InferenceContext<'a> {
652659
self.result.diagnostics.push(diagnostic);
653660
}
654661

655-
fn make_ty_with_mode(
656-
&mut self,
657-
type_ref: &TypeRef,
658-
impl_trait_mode: ImplTraitLoweringMode,
659-
) -> Ty {
662+
fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
660663
// FIXME use right resolver for block
661-
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
662-
.with_impl_trait_mode(impl_trait_mode);
664+
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
663665
let ty = ctx.lower_ty(type_ref);
664666
let ty = self.insert_type_vars(ty);
665667
self.normalize_associated_types_in(ty)
666668
}
667669

668-
fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
669-
self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Disallowed)
670-
}
671-
672670
fn err_ty(&self) -> Ty {
673671
self.result.standard_types.unknown.clone()
674672
}

crates/hir-ty/src/tests/traits.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,6 +1388,22 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
13881388
);
13891389
}
13901390

1391+
#[test]
1392+
fn return_pos_impl_trait_in_projection() {
1393+
// Note that the unused type param `X` is significant; see #13307.
1394+
check_no_mismatches(
1395+
r#"
1396+
//- minicore: sized
1397+
trait Future { type Output; }
1398+
impl Future for () { type Output = i32; }
1399+
type Foo<F> = (<F as Future>::Output, F);
1400+
fn foo<X>() -> Foo<impl Future<Output = ()>> {
1401+
(0, ())
1402+
}
1403+
"#,
1404+
)
1405+
}
1406+
13911407
#[test]
13921408
fn dyn_trait() {
13931409
check_infer(

0 commit comments

Comments
 (0)