Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/closure.rs')
-rw-r--r--crates/hir-ty/src/infer/closure.rs84
1 files changed, 65 insertions, 19 deletions
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 346c7f6df6..d3acbf7b40 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -2,7 +2,11 @@
use std::{cmp, collections::HashMap, convert::Infallible, mem};
-use chalk_ir::{cast::Cast, AliasEq, AliasTy, FnSubst, Mutability, TyKind, WhereClause};
+use chalk_ir::{
+ cast::Cast,
+ fold::{FallibleTypeFolder, TypeFoldable},
+ AliasEq, AliasTy, BoundVar, DebruijnIndex, FnSubst, Mutability, TyKind, WhereClause,
+};
use hir_def::{
data::adt::VariantData,
hir::{
@@ -11,7 +15,7 @@ use hir_def::{
},
lang_item::LangItem,
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
- FieldId, HasModule, VariantId,
+ DefWithBodyId, FieldId, HasModule, VariantId,
};
use hir_expand::name;
use rustc_hash::FxHashMap;
@@ -20,12 +24,13 @@ use stdx::never;
use crate::{
db::HirDatabase,
+ from_placeholder_idx, make_binders,
mir::{BorrowKind, MirSpan, ProjectionElem},
static_lifetime, to_chalk_trait_id,
traits::FnTrait,
- utils::{self, pattern_matching_dereference_count},
- Adjust, Adjustment, Canonical, CanonicalVarKinds, ChalkTraitId, ClosureId, DynTy, FnPointer,
- FnSig, InEnvironment, Interner, Substitution, Ty, TyBuilder, TyExt,
+ utils::{self, generics, pattern_matching_dereference_count, Generics},
+ Adjust, Adjustment, Binders, ChalkTraitId, ClosureId, DynTy, FnPointer, FnSig, Interner,
+ Substitution, Ty, TyExt,
};
use super::{Expectation, InferenceContext};
@@ -117,7 +122,7 @@ impl HirPlace {
fn ty(&self, ctx: &mut InferenceContext<'_>) -> Ty {
let mut ty = ctx.table.resolve_completely(ctx.result[self.local].clone());
for p in &self.projections {
- ty = p.projected_ty(ty, ctx.db, |_, _| {
+ ty = p.projected_ty(ty, ctx.db, |_, _, _| {
unreachable!("Closure field only happens in MIR");
});
}
@@ -152,7 +157,7 @@ pub struct CapturedItem {
pub(crate) place: HirPlace,
pub(crate) kind: CaptureKind,
pub(crate) span: MirSpan,
- pub(crate) ty: Ty,
+ pub(crate) ty: Binders<Ty>,
}
impl CapturedItem {
@@ -232,6 +237,52 @@ pub(crate) struct CapturedItemWithoutTy {
impl CapturedItemWithoutTy {
fn with_ty(self, ctx: &mut InferenceContext<'_>) -> CapturedItem {
+ fn replace_placeholder_with_binder(
+ db: &dyn HirDatabase,
+ owner: DefWithBodyId,
+ ty: Ty,
+ ) -> Binders<Ty> {
+ struct Filler<'a> {
+ db: &'a dyn HirDatabase,
+ generics: Generics,
+ }
+ impl FallibleTypeFolder<Interner> for Filler<'_> {
+ type Error = ();
+
+ fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> {
+ self
+ }
+
+ fn interner(&self) -> Interner {
+ Interner
+ }
+
+ fn try_fold_free_placeholder_ty(
+ &mut self,
+ idx: chalk_ir::PlaceholderIndex,
+ _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))
+ }
+ }
+ let g_def = match owner {
+ DefWithBodyId::FunctionId(f) => Some(f.into()),
+ DefWithBodyId::StaticId(_) => None,
+ DefWithBodyId::ConstId(f) => Some(f.into()),
+ DefWithBodyId::VariantId(f) => Some(f.into()),
+ };
+ let Some(generics) = g_def.map(|g_def| generics(db.upcast(), g_def)) else {
+ return Binders::empty(Interner, ty);
+ };
+ let filler = &mut Filler { db, generics };
+ let result = ty.clone().try_fold_with(filler, DebruijnIndex::INNERMOST).unwrap_or(ty);
+ make_binders(db, &filler.generics, result)
+ }
let ty = self.place.ty(ctx).clone();
let ty = match &self.kind {
CaptureKind::ByValue => ty,
@@ -243,7 +294,12 @@ impl CapturedItemWithoutTy {
TyKind::Ref(m, static_lifetime(), ty).intern(Interner)
}
};
- CapturedItem { place: self.place, kind: self.kind, span: self.span, ty }
+ CapturedItem {
+ place: self.place,
+ kind: self.kind,
+ span: self.span,
+ ty: replace_placeholder_with_binder(ctx.db, ctx.owner, ty),
+ }
}
}
@@ -590,17 +646,7 @@ impl InferenceContext<'_> {
// without creating query cycles.
return self.result.closure_info.get(id).map(|x| x.1 == FnTrait::Fn).unwrap_or(true);
}
- let crate_id = self.owner.module(self.db.upcast()).krate();
- let Some(copy_trait) = self.db.lang_item(crate_id, LangItem::Copy).and_then(|x| x.as_trait()) else {
- return false;
- };
- let trait_ref = TyBuilder::trait_ref(self.db, copy_trait).push(ty).build();
- let env = self.db.trait_environment_for_body(self.owner);
- let goal = Canonical {
- value: InEnvironment::new(&env.env, trait_ref.cast(Interner)),
- binders: CanonicalVarKinds::empty(Interner),
- };
- self.db.trait_solve(crate_id, None, goal).is_some()
+ ty.is_copy(self.db, self.owner)
}
fn select_from_expr(&mut self, expr: ExprId) {