Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/unify.rs')
-rw-r--r--crates/hir-ty/src/infer/unify.rs30
1 files changed, 29 insertions, 1 deletions
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index c0f5ddddcb..99ad678980 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -9,6 +9,7 @@ use chalk_ir::{
use chalk_solve::infer::ParameterEnaVariableExt;
use either::Either;
use ena::unify::UnifyKey;
+use hir_def::{lang_item::LangItem, AdtId};
use hir_expand::name::Name;
use intern::sym;
use rustc_hash::FxHashMap;
@@ -21,7 +22,7 @@ use crate::{
to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment,
InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar,
- Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
+ Solution, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind,
WhereClause,
};
@@ -898,6 +899,33 @@ impl<'a> InferenceTable<'a> {
_ => c,
}
}
+
+ /// Check if given type is `Sized` or not
+ pub(crate) fn is_sized(&mut self, ty: &Ty) -> bool {
+ if let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
+ let struct_data = self.db.struct_data(id);
+ if let Some((last_field, _)) = struct_data.variant_data.fields().iter().last() {
+ let last_field_ty =
+ self.db.field_types(id.into())[last_field].clone().substitute(Interner, subst);
+ // Structs can have DST as its last field and such cases are not handled
+ // as unsized by the chalk, so we do this manually
+ return self.is_sized(&last_field_ty);
+ }
+ }
+ let Some(sized) = self
+ .db
+ .lang_item(self.trait_env.krate, LangItem::Sized)
+ .and_then(|sized| sized.as_trait())
+ else {
+ return false;
+ };
+ let sized_pred = WhereClause::Implemented(TraitRef {
+ trait_id: to_chalk_trait_id(sized),
+ substitution: Substitution::from1(Interner, ty.clone()),
+ });
+ let goal = GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(sized_pred)).intern(Interner);
+ matches!(self.try_obligation(goal), Some(Solution::Unique(_)))
+ }
}
impl fmt::Debug for InferenceTable<'_> {