]> git.proxmox.com Git - rustc.git/blob - vendor/chalk-solve/src/clauses/builtin_traits/sized.rs
Update (un)suspicious files
[rustc.git] / vendor / chalk-solve / src / clauses / builtin_traits / sized.rs
1 use std::iter;
2
3 use crate::clauses::builtin_traits::needs_impl_for_tys;
4 use crate::clauses::ClauseBuilder;
5 use crate::rust_ir::AdtKind;
6 use crate::{Interner, RustIrDatabase, TraitRef};
7 use chalk_ir::{
8 AdtId, CanonicalVarKinds, Floundered, Substitution, TyKind, TyVariableKind, VariableKind,
9 };
10
11 fn push_adt_sized_conditions<I: Interner>(
12 db: &dyn RustIrDatabase<I>,
13 builder: &mut ClauseBuilder<'_, I>,
14 trait_ref: TraitRef<I>,
15 adt_id: AdtId<I>,
16 substitution: &Substitution<I>,
17 ) {
18 let adt_datum = db.adt_datum(adt_id);
19
20 // WF ensures that all enums are Sized, so we only have to consider structs.
21 if adt_datum.kind != AdtKind::Struct {
22 builder.push_fact(trait_ref);
23 return;
24 }
25
26 let interner = db.interner();
27
28 // To check if a struct S<..> is Sized, we only have to look at its last field.
29 // This is because the WF checks for ADTs require that all the other fields must be Sized.
30 let last_field_ty = adt_datum
31 .binders
32 .map_ref(|b| b.variants.clone())
33 .substitute(interner, substitution)
34 .into_iter()
35 .take(1) // We have a struct so we're guaranteed one variant
36 .flat_map(|mut v| v.fields.pop());
37
38 needs_impl_for_tys(db, builder, trait_ref, last_field_ty);
39 }
40
41 fn push_tuple_sized_conditions<I: Interner>(
42 db: &dyn RustIrDatabase<I>,
43 builder: &mut ClauseBuilder<'_, I>,
44 trait_ref: TraitRef<I>,
45 arity: usize,
46 substitution: &Substitution<I>,
47 ) {
48 // Empty tuples are always Sized
49 if arity == 0 {
50 builder.push_fact(trait_ref);
51 return;
52 }
53
54 let interner = db.interner();
55
56 // To check if a tuple is Sized, we only have to look at its last element.
57 // This is because the WF checks for tuples require that all the other elements must be Sized.
58 let last_elem_ty = substitution
59 .iter(interner)
60 .last()
61 .unwrap()
62 .ty(interner)
63 .unwrap()
64 .clone();
65
66 needs_impl_for_tys(db, builder, trait_ref, iter::once(last_elem_ty));
67 }
68
69 pub fn add_sized_program_clauses<I: Interner>(
70 db: &dyn RustIrDatabase<I>,
71 builder: &mut ClauseBuilder<'_, I>,
72 trait_ref: TraitRef<I>,
73 ty: TyKind<I>,
74 binders: &CanonicalVarKinds<I>,
75 ) -> Result<(), Floundered> {
76 match ty {
77 TyKind::Adt(adt_id, ref substitution) => {
78 push_adt_sized_conditions(db, builder, trait_ref, adt_id, substitution)
79 }
80 TyKind::Tuple(arity, ref substitution) => {
81 push_tuple_sized_conditions(db, builder, trait_ref, arity, substitution)
82 }
83 TyKind::Array(_, _)
84 | TyKind::Never
85 | TyKind::Closure(_, _)
86 | TyKind::FnDef(_, _)
87 | TyKind::Scalar(_)
88 | TyKind::Raw(_, _)
89 | TyKind::Generator(_, _)
90 | TyKind::GeneratorWitness(_, _)
91 | TyKind::Ref(_, _, _) => builder.push_fact(trait_ref),
92
93 TyKind::AssociatedType(_, _)
94 | TyKind::Slice(_)
95 | TyKind::OpaqueType(_, _)
96 | TyKind::Str
97 | TyKind::Foreign(_)
98 | TyKind::Error => {}
99
100 TyKind::Function(_)
101 | TyKind::InferenceVar(_, TyVariableKind::Float)
102 | TyKind::InferenceVar(_, TyVariableKind::Integer) => builder.push_fact(trait_ref),
103
104 TyKind::BoundVar(bound_var) => {
105 let var_kind = &binders.at(db.interner(), bound_var.index).kind;
106 match var_kind {
107 VariableKind::Ty(TyVariableKind::Integer)
108 | VariableKind::Ty(TyVariableKind::Float) => builder.push_fact(trait_ref),
109
110 // Don't know enough
111 VariableKind::Ty(TyVariableKind::General) => return Err(Floundered),
112
113 VariableKind::Const(_) | VariableKind::Lifetime => {}
114 }
115 }
116
117 // We don't know enough here
118 TyKind::InferenceVar(_, TyVariableKind::General) => return Err(Floundered),
119
120 // These would be handled elsewhere
121 TyKind::Placeholder(_) | TyKind::Dyn(_) | TyKind::Alias(_) => {}
122 }
123 Ok(())
124 }