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}
;
8 AdtId
, CanonicalVarKinds
, Floundered
, Substitution
, TyKind
, TyVariableKind
, VariableKind
,
11 fn push_adt_sized_conditions
<I
: Interner
>(
12 db
: &dyn RustIrDatabase
<I
>,
13 builder
: &mut ClauseBuilder
<'_
, I
>,
14 trait_ref
: TraitRef
<I
>,
16 substitution
: &Substitution
<I
>,
18 let adt_datum
= db
.adt_datum(adt_id
);
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
);
26 let interner
= db
.interner();
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
32 .map_ref(|b
| b
.variants
.clone())
33 .substitute(interner
, substitution
)
35 .take(1) // We have a struct so we're guaranteed one variant
36 .flat_map(|mut v
| v
.fields
.pop());
38 needs_impl_for_tys(db
, builder
, trait_ref
, last_field_ty
);
41 fn push_tuple_sized_conditions
<I
: Interner
>(
42 db
: &dyn RustIrDatabase
<I
>,
43 builder
: &mut ClauseBuilder
<'_
, I
>,
44 trait_ref
: TraitRef
<I
>,
46 substitution
: &Substitution
<I
>,
48 // Empty tuples are always Sized
50 builder
.push_fact(trait_ref
);
54 let interner
= db
.interner();
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
66 needs_impl_for_tys(db
, builder
, trait_ref
, iter
::once(last_elem_ty
));
69 pub fn add_sized_program_clauses
<I
: Interner
>(
70 db
: &dyn RustIrDatabase
<I
>,
71 builder
: &mut ClauseBuilder
<'_
, I
>,
72 trait_ref
: TraitRef
<I
>,
74 binders
: &CanonicalVarKinds
<I
>,
75 ) -> Result
<(), Floundered
> {
77 TyKind
::Adt(adt_id
, ref substitution
) => {
78 push_adt_sized_conditions(db
, builder
, trait_ref
, adt_id
, substitution
)
80 TyKind
::Tuple(arity
, ref substitution
) => {
81 push_tuple_sized_conditions(db
, builder
, trait_ref
, arity
, substitution
)
85 | TyKind
::Closure(_
, _
)
89 | TyKind
::Generator(_
, _
)
90 | TyKind
::GeneratorWitness(_
, _
)
91 | TyKind
::Ref(_
, _
, _
) => builder
.push_fact(trait_ref
),
93 TyKind
::AssociatedType(_
, _
)
95 | TyKind
::OpaqueType(_
, _
)
101 | TyKind
::InferenceVar(_
, TyVariableKind
::Float
)
102 | TyKind
::InferenceVar(_
, TyVariableKind
::Integer
) => builder
.push_fact(trait_ref
),
104 TyKind
::BoundVar(bound_var
) => {
105 let var_kind
= &binders
.at(db
.interner(), bound_var
.index
).kind
;
107 VariableKind
::Ty(TyVariableKind
::Integer
)
108 | VariableKind
::Ty(TyVariableKind
::Float
) => builder
.push_fact(trait_ref
),
111 VariableKind
::Ty(TyVariableKind
::General
) => return Err(Floundered
),
113 VariableKind
::Const(_
) | VariableKind
::Lifetime
=> {}
117 // We don't know enough here
118 TyKind
::InferenceVar(_
, TyVariableKind
::General
) => return Err(Floundered
),
120 // These would be handled elsewhere
121 TyKind
::Placeholder(_
) | TyKind
::Dyn(_
) | TyKind
::Alias(_
) => {}