Skip to content

Commit 300d9c5

Browse files
More comments, reverse polarity of structural check
1 parent de03964 commit 300d9c5

File tree

1 file changed

+38
-33
lines changed
  • compiler/rustc_const_eval/src/check_consts

1 file changed

+38
-33
lines changed

compiler/rustc_const_eval/src/check_consts/qualifs.rs

+38-33
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)