@@ -62,16 +62,12 @@ pub trait Qualif {
62
62
/// It also determines the `Qualif`s for primitive types.
63
63
fn in_any_value_of_ty < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , ty : Ty < ' tcx > ) -> bool ;
64
64
65
- /// Returns `true` if the `Qualif` is not structural, i.e. that we should not recurse
66
- /// into the operand.
67
- fn is_non_structural < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool ;
68
-
69
- /// Returns `true` if this `Qualif` behaves sructurally for pointers and references:
70
- /// the pointer/reference qualifies if and only if the pointee qualifies.
65
+ /// Returns `true` if the `Qualif` is structural in an ADT's fields, i.e. that we may
66
+ /// recurse into an operand if we know what it is.
71
67
///
72
- /// (This is currently ` false` for all our instances, but that may change in the future. Also,
73
- /// by keeping it abstract, the handling of `Deref` in `in_place` becomes more clear.)
74
- fn deref_structural < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > ) -> bool ;
68
+ /// If this returns false, `in_any_value_of_ty` will be invoked to determine the
69
+ /// final qualif for this ADT.
70
+ fn is_structural_in_adt < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool ;
75
71
}
76
72
77
73
/// Constant containing interior mutability (`UnsafeCell<T>`).
@@ -123,18 +119,13 @@ impl Qualif for HasMutInterior {
123
119
!errors. is_empty ( )
124
120
}
125
121
126
- fn is_non_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
122
+ fn is_structural_in_adt < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
127
123
// Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
128
124
// It arises structurally for all other types.
129
- adt. is_unsafe_cell ( )
130
- }
131
-
132
- fn deref_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > ) -> bool {
133
- false
125
+ !adt. is_unsafe_cell ( )
134
126
}
135
127
}
136
128
137
- // FIXME(const_trait_impl): Get rid of this!
138
129
/// Constant containing an ADT that implements `Drop`.
139
130
/// This must be ruled out because implicit promotion would remove side-effects
140
131
/// that occur as part of dropping that value. N.B., the implicit promotion has
@@ -154,12 +145,8 @@ impl Qualif for NeedsDrop {
154
145
ty. needs_drop ( cx. tcx , cx. param_env )
155
146
}
156
147
157
- fn is_non_structural < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
158
- adt. has_dtor ( cx. tcx )
159
- }
160
-
161
- fn deref_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > ) -> bool {
162
- false
148
+ fn is_structural_in_adt < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
149
+ !adt. has_dtor ( cx. tcx )
163
150
}
164
151
}
165
152
@@ -183,6 +170,11 @@ impl Qualif for NeedsNonConstDrop {
183
170
return false ;
184
171
}
185
172
173
+ // We check that the type is `~const Destruct` since that will verify that
174
+ // the type is both `~const Drop` (if a drop impl exists for the adt), *and*
175
+ // that the components of this type are also `~const Destruct`. This
176
+ // amounts to verifying that there are no values in this ADT that may have
177
+ // a non-const drop.
186
178
if cx. tcx . features ( ) . const_trait_impl ( ) {
187
179
let destruct_def_id = cx. tcx . require_lang_item ( LangItem :: Destruct , Some ( cx. body . span ) ) ;
188
180
let infcx = cx. tcx . infer_ctxt ( ) . build ( TypingMode :: from_param_env ( cx. param_env ) ) ;
@@ -204,15 +196,18 @@ impl Qualif for NeedsNonConstDrop {
204
196
}
205
197
}
206
198
207
- fn is_non_structural < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
208
- // Even a `const` dtor may have `~const` bounds that may need to
209
- // be satisfied, so this becomes non-structural as soon as the
210
- // ADT gets a destructor at all.
211
- adt. has_dtor ( cx. tcx )
212
- }
213
-
214
- fn deref_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > ) -> bool {
215
- false
199
+ fn is_structural_in_adt < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
200
+ // As soon as an ADT has a destructor, then the drop becomes non-structural
201
+ // in its value since:
202
+ // 1. The destructor may have `~const` bounds that need to be satisfied on
203
+ // top of checking that the components of a specific operand are const-drop.
204
+ // While this could be instead satisfied by checking that the `~const Drop`
205
+ // impl holds (i.e. replicating part of the `in_any_value_of_ty` logic above),
206
+ // even in this case, we have another problem, which is,
207
+ // 2. The destructor may *modify* the operand being dropped, so even if we
208
+ // did recurse on the components of the operand, we may not be even dropping
209
+ // the same values that were present before the custom destructor was invoked.
210
+ !adt. has_dtor ( cx. tcx )
216
211
}
217
212
}
218
213
@@ -266,7 +261,12 @@ where
266
261
// qualified.
267
262
if let AggregateKind :: Adt ( adt_did, ..) = * * kind {
268
263
let def = cx. tcx . adt_def ( adt_did) ;
269
- if def. is_union ( ) || Q :: is_non_structural ( cx, def) {
264
+ // Don't do any value-based reasoning for unions.
265
+ // Also, if the ADT is not structural in its fields,
266
+ // then we cannot recurse on its fields. Instead,
267
+ // we fall back to checking the qualif for *any* value
268
+ // of the ADT.
269
+ if def. is_union ( ) || !Q :: is_structural_in_adt ( cx, def) {
270
270
return Q :: in_any_value_of_ty ( cx, rvalue. ty ( cx. body , cx. tcx ) ) ;
271
271
}
272
272
}
@@ -304,7 +304,12 @@ where
304
304
return false ;
305
305
}
306
306
307
- if matches ! ( elem, ProjectionElem :: Deref ) && !Q :: deref_structural ( cx) {
307
+ // This is currently unconditionally true for all qualifs, since we do
308
+ // not recurse into the pointer of a deref projection, but that may change
309
+ // in the future. If that changes, each qualif should be required to
310
+ // specify whether it operates structurally for deref projections, just like
311
+ // we do for `Qualif::is_structural_in_adt`.
312
+ if matches ! ( elem, ProjectionElem :: Deref ) {
308
313
// We have to assume that this qualifies.
309
314
return true ;
310
315
}
0 commit comments