summaryrefslogtreecommitdiffstats
path: root/vendor/chalk-solve-0.87.0/src/clauses/builtin_traits/sized.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chalk-solve-0.87.0/src/clauses/builtin_traits/sized.rs')
-rw-r--r--vendor/chalk-solve-0.87.0/src/clauses/builtin_traits/sized.rs124
1 files changed, 124 insertions, 0 deletions
diff --git a/vendor/chalk-solve-0.87.0/src/clauses/builtin_traits/sized.rs b/vendor/chalk-solve-0.87.0/src/clauses/builtin_traits/sized.rs
new file mode 100644
index 000000000..3ed46d425
--- /dev/null
+++ b/vendor/chalk-solve-0.87.0/src/clauses/builtin_traits/sized.rs
@@ -0,0 +1,124 @@
+use std::iter;
+
+use crate::clauses::builtin_traits::needs_impl_for_tys;
+use crate::clauses::ClauseBuilder;
+use crate::rust_ir::AdtKind;
+use crate::{Interner, RustIrDatabase, TraitRef};
+use chalk_ir::{
+ AdtId, CanonicalVarKinds, Floundered, Substitution, TyKind, TyVariableKind, VariableKind,
+};
+
+fn push_adt_sized_conditions<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ adt_id: AdtId<I>,
+ substitution: &Substitution<I>,
+) {
+ let adt_datum = db.adt_datum(adt_id);
+
+ // WF ensures that all enums are Sized, so we only have to consider structs.
+ if adt_datum.kind != AdtKind::Struct {
+ builder.push_fact(trait_ref);
+ return;
+ }
+
+ let interner = db.interner();
+
+ // To check if a struct S<..> is Sized, we only have to look at its last field.
+ // This is because the WF checks for ADTs require that all the other fields must be Sized.
+ let last_field_ty = adt_datum
+ .binders
+ .map_ref(|b| b.variants.clone())
+ .substitute(interner, substitution)
+ .into_iter()
+ .take(1) // We have a struct so we're guaranteed one variant
+ .flat_map(|mut v| v.fields.pop());
+
+ needs_impl_for_tys(db, builder, trait_ref, last_field_ty);
+}
+
+fn push_tuple_sized_conditions<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ arity: usize,
+ substitution: &Substitution<I>,
+) {
+ // Empty tuples are always Sized
+ if arity == 0 {
+ builder.push_fact(trait_ref);
+ return;
+ }
+
+ let interner = db.interner();
+
+ // To check if a tuple is Sized, we only have to look at its last element.
+ // This is because the WF checks for tuples require that all the other elements must be Sized.
+ let last_elem_ty = substitution
+ .iter(interner)
+ .last()
+ .unwrap()
+ .ty(interner)
+ .unwrap()
+ .clone();
+
+ needs_impl_for_tys(db, builder, trait_ref, iter::once(last_elem_ty));
+}
+
+pub fn add_sized_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ ty: TyKind<I>,
+ binders: &CanonicalVarKinds<I>,
+) -> Result<(), Floundered> {
+ match ty {
+ TyKind::Adt(adt_id, ref substitution) => {
+ push_adt_sized_conditions(db, builder, trait_ref, adt_id, substitution)
+ }
+ TyKind::Tuple(arity, ref substitution) => {
+ push_tuple_sized_conditions(db, builder, trait_ref, arity, substitution)
+ }
+ TyKind::Array(_, _)
+ | TyKind::Never
+ | TyKind::Closure(_, _)
+ | TyKind::FnDef(_, _)
+ | TyKind::Scalar(_)
+ | TyKind::Raw(_, _)
+ | TyKind::Generator(_, _)
+ | TyKind::GeneratorWitness(_, _)
+ | TyKind::Ref(_, _, _) => builder.push_fact(trait_ref),
+
+ TyKind::AssociatedType(_, _)
+ | TyKind::Slice(_)
+ | TyKind::OpaqueType(_, _)
+ | TyKind::Str
+ | TyKind::Foreign(_)
+ | TyKind::Error => {}
+
+ TyKind::Function(_)
+ | TyKind::InferenceVar(_, TyVariableKind::Float)
+ | TyKind::InferenceVar(_, TyVariableKind::Integer) => builder.push_fact(trait_ref),
+
+ TyKind::BoundVar(bound_var) => {
+ let var_kind = &binders.at(db.interner(), bound_var.index).kind;
+ match var_kind {
+ VariableKind::Ty(TyVariableKind::Integer)
+ | VariableKind::Ty(TyVariableKind::Float) => builder.push_fact(trait_ref),
+
+ // Don't know enough
+ VariableKind::Ty(TyVariableKind::General) => return Err(Floundered),
+
+ VariableKind::Const(_) | VariableKind::Lifetime => {}
+ }
+ }
+
+ // We don't know enough here
+ TyKind::InferenceVar(_, TyVariableKind::General) => return Err(Floundered),
+
+ // These would be handled elsewhere
+ TyKind::Placeholder(_) | TyKind::Dyn(_) | TyKind::Alias(_) => {}
+ }
+ Ok(())
+}