@@ -62,16 +62,12 @@ pub trait Qualif {
6262 /// It also determines the `Qualif`s for primitive types.
6363 fn in_any_value_of_ty < ' tcx > ( cx : & ConstCx < ' _ , ' tcx > , ty : Ty < ' tcx > ) -> bool ;
6464
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.
7167 ///
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 ;
7571}
7672
7773/// Constant containing interior mutability (`UnsafeCell<T>`).
@@ -127,18 +123,13 @@ impl Qualif for HasMutInterior {
127123 !errors. is_empty ( )
128124 }
129125
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 {
131127 // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
132128 // 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 ( )
138130 }
139131}
140132
141- // FIXME(const_trait_impl): Get rid of this!
142133/// Constant containing an ADT that implements `Drop`.
143134/// This must be ruled out because implicit promotion would remove side-effects
144135/// that occur as part of dropping that value. N.B., the implicit promotion has
@@ -158,12 +149,8 @@ impl Qualif for NeedsDrop {
158149 ty. needs_drop ( cx. tcx , cx. typing_env )
159150 }
160151
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 )
167154 }
168155}
169156
@@ -187,14 +174,20 @@ impl Qualif for NeedsNonConstDrop {
187174 return false ;
188175 }
189176
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.
190182 if cx. tcx . features ( ) . const_trait_impl ( ) {
191183 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 ) ) ;
193186 let ocx = ObligationCtxt :: new ( & infcx) ;
194187 ocx. register_obligation ( Obligation :: new (
195188 cx. tcx ,
196189 ObligationCause :: misc ( cx. body . span , cx. def_id ( ) ) ,
197- cx. param_env ,
190+ cx. typing_env . param_env ,
198191 ty:: Binder :: dummy ( ty:: TraitRef :: new ( cx. tcx , destruct_def_id, [ ty] ) )
199192 . to_host_effect_clause ( cx. tcx , match cx. const_kind ( ) {
200193 rustc_hir:: ConstContext :: ConstFn => ty:: BoundConstness :: Maybe ,
@@ -208,15 +201,18 @@ impl Qualif for NeedsNonConstDrop {
208201 }
209202 }
210203
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 )
220216 }
221217}
222218
@@ -270,7 +266,12 @@ where
270266 // qualified.
271267 if let AggregateKind :: Adt ( adt_did, ..) = * * kind {
272268 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) {
274275 return Q :: in_any_value_of_ty ( cx, rvalue. ty ( cx. body , cx. tcx ) ) ;
275276 }
276277 }
@@ -308,7 +309,12 @@ where
308309 return false ;
309310 }
310311
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 ) {
312318 // We have to assume that this qualifies.
313319 return true ;
314320 }
0 commit comments