@@ -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>`).
@@ -127,18 +123,13 @@ impl Qualif for HasMutInterior {
127
123
!errors. is_empty ( )
128
124
}
129
125
130
- fn is_non_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
126
+ fn is_structural_in_adt < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
131
127
// Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
132
128
// It arises structurally for all other types.
133
- adt. is_unsafe_cell ( )
134
- }
135
-
136
- fn deref_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > ) -> bool {
137
- false
129
+ !adt. is_unsafe_cell ( )
138
130
}
139
131
}
140
132
141
- // FIXME(const_trait_impl): Get rid of this!
142
133
/// Constant containing an ADT that implements `Drop`.
143
134
/// This must be ruled out because implicit promotion would remove side-effects
144
135
/// that occur as part of dropping that value. N.B., the implicit promotion has
@@ -158,12 +149,8 @@ impl Qualif for NeedsDrop {
158
149
ty. needs_drop ( cx. tcx , cx. typing_env )
159
150
}
160
151
161
- fn is_non_structural < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
162
- adt. has_dtor ( cx. tcx )
163
- }
164
-
165
- fn deref_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > ) -> bool {
166
- false
152
+ fn is_structural_in_adt < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
153
+ !adt. has_dtor ( cx. tcx )
167
154
}
168
155
}
169
156
@@ -187,14 +174,20 @@ impl Qualif for NeedsNonConstDrop {
187
174
return false ;
188
175
}
189
176
177
+ // We check that the type is `~const Destruct` since that will verify that
178
+ // the type is both `~const Drop` (if a drop impl exists for the adt), *and*
179
+ // that the components of this type are also `~const Destruct`. This
180
+ // amounts to verifying that there are no values in this ADT that may have
181
+ // a non-const drop.
190
182
if cx. tcx . features ( ) . const_trait_impl ( ) {
191
183
let destruct_def_id = cx. tcx . require_lang_item ( LangItem :: Destruct , Some ( cx. body . span ) ) ;
192
- let infcx = cx. tcx . infer_ctxt ( ) . build ( TypingMode :: from_param_env ( cx. param_env ) ) ;
184
+ let infcx =
185
+ cx. tcx . infer_ctxt ( ) . build ( TypingMode :: from_param_env ( cx. typing_env . param_env ) ) ;
193
186
let ocx = ObligationCtxt :: new ( & infcx) ;
194
187
ocx. register_obligation ( Obligation :: new (
195
188
cx. tcx ,
196
189
ObligationCause :: misc ( cx. body . span , cx. def_id ( ) ) ,
197
- cx. param_env ,
190
+ cx. typing_env . param_env ,
198
191
ty:: Binder :: dummy ( ty:: TraitRef :: new ( cx. tcx , destruct_def_id, [ ty] ) )
199
192
. to_host_effect_clause ( cx. tcx , match cx. const_kind ( ) {
200
193
rustc_hir:: ConstContext :: ConstFn => ty:: BoundConstness :: Maybe ,
@@ -208,15 +201,18 @@ impl Qualif for NeedsNonConstDrop {
208
201
}
209
202
}
210
203
211
- fn is_non_structural < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
212
- // Even a `const` dtor may have `~const` bounds that may need to
213
- // be satisfied, so this becomes non-structural as soon as the
214
- // ADT gets a destructor at all.
215
- adt. has_dtor ( cx. tcx )
216
- }
217
-
218
- fn deref_structural < ' tcx > ( _cx : & ConstCx < ' _ , ' tcx > ) -> bool {
219
- false
204
+ fn is_structural_in_adt < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , adt : AdtDef < ' tcx > ) -> bool {
205
+ // As soon as an ADT has a destructor, then the drop becomes non-structural
206
+ // in its value since:
207
+ // 1. The destructor may have `~const` bounds that need to be satisfied on
208
+ // top of checking that the components of a specific operand are const-drop.
209
+ // While this could be instead satisfied by checking that the `~const Drop`
210
+ // impl holds (i.e. replicating part of the `in_any_value_of_ty` logic above),
211
+ // even in this case, we have another problem, which is,
212
+ // 2. The destructor may *modify* the operand being dropped, so even if we
213
+ // did recurse on the components of the operand, we may not be even dropping
214
+ // the same values that were present before the custom destructor was invoked.
215
+ !adt. has_dtor ( cx. tcx )
220
216
}
221
217
}
222
218
@@ -270,7 +266,12 @@ where
270
266
// qualified.
271
267
if let AggregateKind :: Adt ( adt_did, ..) = * * kind {
272
268
let def = cx. tcx . adt_def ( adt_did) ;
273
- if def. is_union ( ) || Q :: is_non_structural ( cx, def) {
269
+ // Don't do any value-based reasoning for unions.
270
+ // Also, if the ADT is not structural in its fields,
271
+ // then we cannot recurse on its fields. Instead,
272
+ // we fall back to checking the qualif for *any* value
273
+ // of the ADT.
274
+ if def. is_union ( ) || !Q :: is_structural_in_adt ( cx, def) {
274
275
return Q :: in_any_value_of_ty ( cx, rvalue. ty ( cx. body , cx. tcx ) ) ;
275
276
}
276
277
}
@@ -308,7 +309,12 @@ where
308
309
return false ;
309
310
}
310
311
311
- if matches ! ( elem, ProjectionElem :: Deref ) && !Q :: deref_structural ( cx) {
312
+ // This is currently unconditionally true for all qualifs, since we do
313
+ // not recurse into the pointer of a deref projection, but that may change
314
+ // in the future. If that changes, each qualif should be required to
315
+ // specify whether it operates structurally for deref projections, just like
316
+ // we do for `Qualif::is_structural_in_adt`.
317
+ if matches ! ( elem, ProjectionElem :: Deref ) {
312
318
// We have to assume that this qualifies.
313
319
return true ;
314
320
}
0 commit comments