1
1
//! Utilities for computing drop info about types.
2
2
3
- use chalk_ir:: cast:: Cast ;
4
- use hir_def:: AdtId ;
5
- use hir_def:: lang_item:: LangItem ;
6
- use hir_def:: signatures:: StructFlags ;
3
+ use hir_def:: { AdtId , lang_item:: LangItem , signatures:: StructFlags } ;
4
+ use rustc_hash:: FxHashSet ;
5
+ use rustc_type_ir:: inherent:: { AdtDef , IntoKind , SliceLike } ;
7
6
use stdx:: never;
8
7
use triomphe:: Arc ;
9
8
10
- use crate :: next_solver:: DbInterner ;
11
- use crate :: next_solver:: mapping:: { ChalkToNextSolver , NextSolverToChalk } ;
12
9
use crate :: {
13
- AliasTy , Canonical , CanonicalVarKinds , ConcreteConst , ConstScalar , ConstValue , InEnvironment ,
14
- Interner , ProjectionTy , TraitEnvironment , Ty , TyBuilder , TyKind , db:: HirDatabase ,
10
+ TraitEnvironment , consteval_nextsolver ,
11
+ db:: HirDatabase ,
15
12
method_resolution:: TyFingerprint ,
13
+ next_solver:: {
14
+ Ty , TyKind ,
15
+ infer:: { InferCtxt , traits:: ObligationCause } ,
16
+ obligation_ctxt:: ObligationCtxt ,
17
+ } ,
16
18
} ;
17
19
18
20
fn has_destructor ( db : & dyn HirDatabase , adt : AdtId ) -> bool {
@@ -45,27 +47,52 @@ pub enum DropGlue {
45
47
HasDropGlue ,
46
48
}
47
49
48
- pub ( crate ) fn has_drop_glue (
49
- db : & dyn HirDatabase ,
50
- ty : Ty ,
51
- env : Arc < TraitEnvironment < ' _ > > ,
50
+ pub fn has_drop_glue < ' db > (
51
+ infcx : & InferCtxt < ' db > ,
52
+ ty : Ty < ' db > ,
53
+ env : Arc < TraitEnvironment < ' db > > ,
52
54
) -> DropGlue {
53
- match ty. kind ( Interner ) {
54
- TyKind :: Adt ( adt, subst) => {
55
- if has_destructor ( db, adt. 0 ) {
55
+ has_drop_glue_impl ( infcx, ty, env, & mut FxHashSet :: default ( ) )
56
+ }
57
+
58
+ fn has_drop_glue_impl < ' db > (
59
+ infcx : & InferCtxt < ' db > ,
60
+ ty : Ty < ' db > ,
61
+ env : Arc < TraitEnvironment < ' db > > ,
62
+ visited : & mut FxHashSet < Ty < ' db > > ,
63
+ ) -> DropGlue {
64
+ let mut ocx = ObligationCtxt :: new ( infcx) ;
65
+ let ty = ocx. structurally_normalize_ty ( & ObligationCause :: dummy ( ) , env. env , ty) . unwrap_or ( ty) ;
66
+
67
+ if !visited. insert ( ty) {
68
+ // Recursive type.
69
+ return DropGlue :: None ;
70
+ }
71
+
72
+ let db = infcx. interner . db ;
73
+ match ty. kind ( ) {
74
+ TyKind :: Adt ( adt_def, subst) => {
75
+ let adt_id = adt_def. def_id ( ) . 0 ;
76
+ if has_destructor ( db, adt_id) {
56
77
return DropGlue :: HasDropGlue ;
57
78
}
58
- match adt . 0 {
79
+ match adt_id {
59
80
AdtId :: StructId ( id) => {
60
- if db. struct_signature ( id) . flags . contains ( StructFlags :: IS_MANUALLY_DROP ) {
81
+ if db
82
+ . struct_signature ( id)
83
+ . flags
84
+ . intersects ( StructFlags :: IS_MANUALLY_DROP | StructFlags :: IS_PHANTOM_DATA )
85
+ {
61
86
return DropGlue :: None ;
62
87
}
63
- db. field_types ( id. into ( ) )
88
+ db. field_types_ns ( id. into ( ) )
64
89
. iter ( )
65
90
. map ( |( _, field_ty) | {
66
- db. has_drop_glue (
67
- field_ty. clone ( ) . substitute ( Interner , subst) ,
91
+ has_drop_glue_impl (
92
+ infcx,
93
+ field_ty. instantiate ( infcx. interner , subst) ,
68
94
env. clone ( ) ,
95
+ visited,
69
96
)
70
97
} )
71
98
. max ( )
@@ -78,12 +105,14 @@ pub(crate) fn has_drop_glue(
78
105
. variants
79
106
. iter ( )
80
107
. map ( |& ( variant, _, _) | {
81
- db. field_types ( variant. into ( ) )
108
+ db. field_types_ns ( variant. into ( ) )
82
109
. iter ( )
83
110
. map ( |( _, field_ty) | {
84
- db. has_drop_glue (
85
- field_ty. clone ( ) . substitute ( Interner , subst) ,
111
+ has_drop_glue_impl (
112
+ infcx,
113
+ field_ty. instantiate ( infcx. interner , subst) ,
86
114
env. clone ( ) ,
115
+ visited,
87
116
)
88
117
} )
89
118
. max ( )
@@ -93,123 +122,70 @@ pub(crate) fn has_drop_glue(
93
122
. unwrap_or ( DropGlue :: None ) ,
94
123
}
95
124
}
96
- TyKind :: Tuple ( _, subst) => subst
97
- . iter ( Interner )
98
- . map ( |ty| ty. assert_ty_ref ( Interner ) )
99
- . map ( |ty| db. has_drop_glue ( ty. clone ( ) , env. clone ( ) ) )
125
+ TyKind :: Tuple ( tys) => tys
126
+ . iter ( )
127
+ . map ( |ty| has_drop_glue_impl ( infcx, ty, env. clone ( ) , visited) )
100
128
. max ( )
101
129
. unwrap_or ( DropGlue :: None ) ,
102
130
TyKind :: Array ( ty, len) => {
103
- if let ConstValue :: Concrete ( ConcreteConst { interned : ConstScalar :: Bytes ( len, _) } ) =
104
- & len. data ( Interner ) . value
105
- {
106
- match ( & * * len) . try_into ( ) {
107
- Ok ( len) => {
108
- let len = usize:: from_le_bytes ( len) ;
109
- if len == 0 {
110
- // Arrays of size 0 don't have drop glue.
111
- return DropGlue :: None ;
112
- }
113
- }
114
- Err ( _) => {
115
- never ! ( "const array size with non-usize len" ) ;
116
- }
117
- }
131
+ if consteval_nextsolver:: try_const_usize ( db, len) == Some ( 0 ) {
132
+ // Arrays of size 0 don't have drop glue.
133
+ return DropGlue :: None ;
118
134
}
119
- db . has_drop_glue ( ty . clone ( ) , env)
135
+ has_drop_glue_impl ( infcx , ty , env, visited )
120
136
}
121
- TyKind :: Slice ( ty) => db . has_drop_glue ( ty . clone ( ) , env) ,
137
+ TyKind :: Slice ( ty) => has_drop_glue_impl ( infcx , ty , env, visited ) ,
122
138
TyKind :: Closure ( closure_id, subst) => {
123
- let closure_id = ( * closure_id) . into ( ) ;
124
- let owner = db. lookup_intern_closure ( closure_id) . 0 ;
139
+ let owner = db. lookup_intern_closure ( closure_id. 0 ) . 0 ;
125
140
let infer = db. infer ( owner) ;
126
- let ( captures, _) = infer. closure_info ( closure_id) ;
141
+ let ( captures, _) = infer. closure_info ( closure_id. 0 ) ;
127
142
let env = db. trait_environment_for_body ( owner) ;
128
- let interner = DbInterner :: conjure ( ) ;
129
143
captures
130
144
. iter ( )
131
145
. map ( |capture| {
132
- db. has_drop_glue (
133
- capture. ty ( db, subst. to_nextsolver ( interner) ) . to_chalk ( interner) ,
134
- env. clone ( ) ,
135
- )
146
+ has_drop_glue_impl ( infcx, capture. ty ( db, subst) , env. clone ( ) , visited)
136
147
} )
137
148
. max ( )
138
149
. unwrap_or ( DropGlue :: None )
139
150
}
140
151
// FIXME: Handle coroutines.
141
- TyKind :: Coroutine ( ..) | TyKind :: CoroutineWitness ( ..) => DropGlue :: None ,
152
+ TyKind :: Coroutine ( ..) | TyKind :: CoroutineWitness ( ..) | TyKind :: CoroutineClosure ( ..) => {
153
+ DropGlue :: None
154
+ }
142
155
TyKind :: Ref ( ..)
143
- | TyKind :: Raw ( ..)
156
+ | TyKind :: RawPtr ( ..)
144
157
| TyKind :: FnDef ( ..)
145
158
| TyKind :: Str
146
159
| TyKind :: Never
147
- | TyKind :: Scalar ( _)
148
- | TyKind :: Function ( _)
160
+ | TyKind :: Bool
161
+ | TyKind :: Char
162
+ | TyKind :: Int ( _)
163
+ | TyKind :: Uint ( _)
164
+ | TyKind :: Float ( _)
165
+ | TyKind :: FnPtr ( ..)
149
166
| TyKind :: Foreign ( _)
150
- | TyKind :: Error => DropGlue :: None ,
151
- TyKind :: Dyn ( _) => DropGlue :: HasDropGlue ,
152
- TyKind :: AssociatedType ( assoc_type_id, subst) => projection_has_drop_glue (
153
- db,
154
- env,
155
- ProjectionTy { associated_ty_id : * assoc_type_id, substitution : subst. clone ( ) } ,
156
- ty,
157
- ) ,
158
- TyKind :: Alias ( AliasTy :: Projection ( projection) ) => {
159
- projection_has_drop_glue ( db, env, projection. clone ( ) , ty)
160
- }
161
- TyKind :: OpaqueType ( ..) | TyKind :: Alias ( AliasTy :: Opaque ( _) ) => {
162
- if is_copy ( db, ty, env) {
167
+ | TyKind :: Error ( _)
168
+ | TyKind :: Bound ( ..)
169
+ | TyKind :: Placeholder ( ..) => DropGlue :: None ,
170
+ TyKind :: Dynamic ( ..) => DropGlue :: HasDropGlue ,
171
+ TyKind :: Alias ( ..) => {
172
+ if infcx. type_is_copy_modulo_regions ( env. env , ty) {
163
173
DropGlue :: None
164
174
} else {
165
175
DropGlue :: HasDropGlue
166
176
}
167
177
}
168
- TyKind :: Placeholder ( _ ) | TyKind :: BoundVar ( _) => {
169
- if is_copy ( db , ty, env ) {
178
+ TyKind :: Param ( _) => {
179
+ if infcx . type_is_copy_modulo_regions ( env . env , ty) {
170
180
DropGlue :: None
171
181
} else {
172
182
DropGlue :: DependOnParams
173
183
}
174
184
}
175
- TyKind :: InferenceVar ( ..) => unreachable ! ( "inference vars shouldn't exist out of inference" ) ,
176
- }
177
- }
178
-
179
- fn projection_has_drop_glue (
180
- db : & dyn HirDatabase ,
181
- env : Arc < TraitEnvironment < ' _ > > ,
182
- projection : ProjectionTy ,
183
- ty : Ty ,
184
- ) -> DropGlue {
185
- let normalized = db. normalize_projection ( projection, env. clone ( ) ) ;
186
- match normalized. kind ( Interner ) {
187
- TyKind :: Alias ( AliasTy :: Projection ( _) ) | TyKind :: AssociatedType ( ..) => {
188
- if is_copy ( db, ty, env) { DropGlue :: None } else { DropGlue :: DependOnParams }
185
+ TyKind :: Infer ( ..) => unreachable ! ( "inference vars shouldn't exist out of inference" ) ,
186
+ TyKind :: Pat ( ..) | TyKind :: UnsafeBinder ( ..) => {
187
+ never ! ( "we do not handle pattern and unsafe binder types" ) ;
188
+ DropGlue :: None
189
189
}
190
- _ => db. has_drop_glue ( normalized, env) ,
191
190
}
192
191
}
193
-
194
- fn is_copy ( db : & dyn HirDatabase , ty : Ty , env : Arc < TraitEnvironment < ' _ > > ) -> bool {
195
- let Some ( copy_trait) = LangItem :: Copy . resolve_trait ( db, env. krate ) else {
196
- return false ;
197
- } ;
198
- let trait_ref = TyBuilder :: trait_ref ( db, copy_trait) . push ( ty) . build ( ) ;
199
- let goal = Canonical {
200
- value : InEnvironment :: new (
201
- & env. env . to_chalk ( DbInterner :: new_with ( db, Some ( env. krate ) , env. block ) ) ,
202
- trait_ref. cast ( Interner ) ,
203
- ) ,
204
- binders : CanonicalVarKinds :: empty ( Interner ) ,
205
- } ;
206
- db. trait_solve ( env. krate , env. block , goal) . certain ( )
207
- }
208
-
209
- pub ( crate ) fn has_drop_glue_cycle_result (
210
- _db : & dyn HirDatabase ,
211
- _ty : Ty ,
212
- _env : Arc < TraitEnvironment < ' _ > > ,
213
- ) -> DropGlue {
214
- DropGlue :: None
215
- }
0 commit comments