1
1
use std:: iter;
2
2
3
+ use crate :: clauses:: builtin_traits:: needs_impl_for_tys;
3
4
use crate :: clauses:: ClauseBuilder ;
4
5
use crate :: { Interner , RustIrDatabase , TraitRef } ;
5
- use chalk_ir:: { ApplicationTy , Substitution , TyData , TypeName } ;
6
+ use chalk_ir:: { ApplicationTy , StructId , Substitution , TyData , TypeName } ;
6
7
7
- pub fn add_sized_program_clauses < I : Interner > (
8
+ fn push_struct_sized_conditions < I : Interner > (
8
9
db : & dyn RustIrDatabase < I > ,
9
10
builder : & mut ClauseBuilder < ' _ , I > ,
10
11
trait_ref : & TraitRef < I > ,
11
- ty : & TyData < I > ,
12
+ struct_id : StructId < I > ,
13
+ substitution : & Substitution < I > ,
12
14
) {
13
- let interner = db. interner ( ) ;
14
-
15
- let ( struct_id, substitution) = match ty {
16
- TyData :: Apply ( ApplicationTy {
17
- name : TypeName :: Struct ( struct_id) ,
18
- substitution,
19
- } ) => ( * struct_id, substitution) ,
20
- // TODO(areredify)
21
- // when #368 lands, extend this to handle everything accordingly
22
- _ => return ,
23
- } ;
24
-
25
15
let struct_datum = db. struct_datum ( struct_id) ;
26
16
27
17
// Structs with no fields are always Sized
@@ -30,16 +20,66 @@ pub fn add_sized_program_clauses<I: Interner>(
30
20
return ;
31
21
}
32
22
23
+ let interner = db. interner ( ) ;
24
+
33
25
// To check if a struct type S<..> is Sized, we only have to look at its last field.
34
26
// This is because the WF checks for structs require that all the other fields must be Sized.
35
27
let last_field_ty = struct_datum
36
28
. binders
37
29
. map_ref ( |b| b. fields . last ( ) . unwrap ( ) )
38
30
. substitute ( interner, substitution) ;
39
31
40
- let last_field_sized_goal = TraitRef {
41
- trait_id : trait_ref. trait_id ,
42
- substitution : Substitution :: from1 ( interner, last_field_ty) ,
43
- } ;
44
- builder. push_clause ( trait_ref. clone ( ) , iter:: once ( last_field_sized_goal) ) ;
32
+ needs_impl_for_tys ( db, builder, trait_ref, iter:: once ( last_field_ty) ) ;
33
+ }
34
+
35
+ fn push_tuple_sized_conditions < I : Interner > (
36
+ db : & dyn RustIrDatabase < I > ,
37
+ builder : & mut ClauseBuilder < ' _ , I > ,
38
+ trait_ref : & TraitRef < I > ,
39
+ arity : usize ,
40
+ substitution : & Substitution < I > ,
41
+ ) {
42
+ // Empty tuples are always Sized
43
+ if arity == 0 {
44
+ builder. push_fact ( trait_ref. clone ( ) ) ;
45
+ return ;
46
+ }
47
+
48
+ let interner = db. interner ( ) ;
49
+
50
+ // To check if a tuple is Sized, we only have to look at its last element.
51
+ // This is because the WF checks for tuples require that all the other elements must be Sized.
52
+ let last_elem_ty = substitution
53
+ . iter ( interner)
54
+ . last ( )
55
+ . unwrap ( )
56
+ . ty ( interner)
57
+ . unwrap ( )
58
+ . clone ( ) ;
59
+
60
+ needs_impl_for_tys ( db, builder, trait_ref, iter:: once ( last_elem_ty) ) ;
61
+ }
62
+
63
+ pub fn add_sized_program_clauses < I : Interner > (
64
+ db : & dyn RustIrDatabase < I > ,
65
+ builder : & mut ClauseBuilder < ' _ , I > ,
66
+ trait_ref : & TraitRef < I > ,
67
+ ty : & TyData < I > ,
68
+ ) {
69
+ match ty {
70
+ TyData :: Apply ( ApplicationTy { name, substitution } ) => match name {
71
+ TypeName :: Struct ( struct_id) => {
72
+ push_struct_sized_conditions ( db, builder, trait_ref, * struct_id, substitution)
73
+ }
74
+ TypeName :: Scalar ( _) => builder. push_fact ( trait_ref. clone ( ) ) ,
75
+ TypeName :: Tuple ( arity) => {
76
+ push_tuple_sized_conditions ( db, builder, trait_ref, * arity, substitution)
77
+ }
78
+ _ => return ,
79
+ } ,
80
+ TyData :: Function ( _) => builder. push_fact ( trait_ref. clone ( ) ) ,
81
+ // TODO(areredify)
82
+ // when #368 lands, extend this to handle everything accordingly
83
+ _ => return ,
84
+ }
45
85
}
0 commit comments