@@ -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>`).
@@ -123,18 +119,13 @@ impl Qualif for HasMutInterior {
123119 !errors. is_empty ( )
124120 }
125121
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 {
127123 // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
128124 // 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 ( )
134126 }
135127}
136128
137- // FIXME(const_trait_impl): Get rid of this!
138129/// Constant containing an ADT that implements `Drop`.
139130/// This must be ruled out because implicit promotion would remove side-effects
140131/// that occur as part of dropping that value. N.B., the implicit promotion has
@@ -154,12 +145,8 @@ impl Qualif for NeedsDrop {
154145 ty. needs_drop ( cx. tcx , cx. param_env )
155146 }
156147
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 )
163150 }
164151}
165152
@@ -183,6 +170,11 @@ impl Qualif for NeedsNonConstDrop {
183170 return false ;
184171 }
185172
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.
186178 if cx. tcx . features ( ) . const_trait_impl ( ) {
187179 let destruct_def_id = cx. tcx . require_lang_item ( LangItem :: Destruct , Some ( cx. body . span ) ) ;
188180 let infcx = cx. tcx . infer_ctxt ( ) . build ( TypingMode :: from_param_env ( cx. param_env ) ) ;
@@ -204,15 +196,18 @@ impl Qualif for NeedsNonConstDrop {
204196 }
205197 }
206198
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 )
216211 }
217212}
218213
@@ -266,7 +261,12 @@ where
266261 // qualified.
267262 if let AggregateKind :: Adt ( adt_did, ..) = * * kind {
268263 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) {
270270 return Q :: in_any_value_of_ty ( cx, rvalue. ty ( cx. body , cx. tcx ) ) ;
271271 }
272272 }
@@ -304,7 +304,12 @@ where
304304 return false ;
305305 }
306306
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 ) {
308313 // We have to assume that this qualifies.
309314 return true ;
310315 }
0 commit comments