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