]>
Commit | Line | Data |
---|---|---|
f9f354fc XL |
1 | use std::iter; |
2 | ||
3 | use crate::clauses::builtin_traits::needs_impl_for_tys; | |
4 | use crate::clauses::ClauseBuilder; | |
3dfed10e | 5 | use crate::rust_ir::AdtKind; |
f9f354fc | 6 | use crate::{Interner, RustIrDatabase, TraitRef}; |
29967ef6 | 7 | use chalk_ir::{AdtId, CanonicalVarKinds, Substitution, TyKind, TyVariableKind, VariableKind}; |
f9f354fc | 8 | |
f035d41b | 9 | fn 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 | ||
39 | fn 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 | ||
67 | pub 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 | } |