fix: consider outer binders when folding captured items' type

This commit is contained in:
Ryo Yoshida 2023-06-04 19:38:47 +09:00
parent 4fb1df6b7a
commit 275afd6e79
No known key found for this signature in database
GPG Key ID: E25698A930586171
2 changed files with 40 additions and 11 deletions

View File

@ -5,7 +5,7 @@ use std::{cmp, collections::HashMap, convert::Infallible, mem};
use chalk_ir::{
cast::Cast,
fold::{FallibleTypeFolder, TypeFoldable},
AliasEq, AliasTy, BoundVar, ConstData, DebruijnIndex, FnSubst, Mutability, TyKind, WhereClause,
AliasEq, AliasTy, BoundVar, DebruijnIndex, FnSubst, Mutability, TyKind, WhereClause,
};
use hir_def::{
data::adt::VariantData,
@ -26,8 +26,8 @@ use crate::{
static_lifetime, to_chalk_trait_id,
traits::FnTrait,
utils::{self, generics, Generics},
Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, ConstValue, DynTy,
FnPointer, FnSig, Interner, Substitution, Ty, TyExt,
Adjust, Adjustment, Binders, BindingMode, ChalkTraitId, ClosureId, DynTy, FnPointer, FnSig,
Interner, Substitution, Ty, TyExt,
};
use super::{Expectation, InferenceContext};
@ -266,24 +266,19 @@ impl CapturedItemWithoutTy {
let Some(idx) = self.generics.param_idx(x) else {
return Err(());
};
Ok(ConstData {
ty,
value: ConstValue::BoundVar(BoundVar::new(outer_binder, idx)),
}
.intern(Interner))
Ok(BoundVar::new(outer_binder, idx).to_const(Interner, ty))
}
fn try_fold_free_placeholder_ty(
&mut self,
idx: chalk_ir::PlaceholderIndex,
_outer_binder: DebruijnIndex,
outer_binder: DebruijnIndex,
) -> std::result::Result<Ty, Self::Error> {
let x = from_placeholder_idx(self.db, idx);
let Some(idx) = self.generics.param_idx(x) else {
return Err(());
};
Ok(TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, idx))
.intern(Interner))
Ok(BoundVar::new(outer_binder, idx).to_ty(Interner))
}
}
let g_def = match owner {

View File

@ -640,3 +640,37 @@ fn main() {
"#,
);
}
#[test]
fn regression_14966() {
check_pass(
r#"
//- minicore: fn, copy, coerce_unsized
trait A<T> {
fn a(&self) {}
}
impl A<()> for () {}
struct B;
impl B {
pub fn b<T>(s: &dyn A<T>) -> Self {
B
}
}
struct C;
impl C {
fn c<T>(a: &dyn A<T>) -> Self {
let mut c = C;
let b = B::b(a);
c.d(|| a.a());
c
}
fn d(&mut self, f: impl FnOnce()) {}
}
fn main() {
C::c(&());
}
"#,
);
}