pub trait Qualif {
const ANALYSIS_NAME: &'static str;
const IS_CLEARED_ON_MOVE: bool = false;
const ALLOW_PROMOTED: bool = false;
// Required methods
fn in_qualifs(qualifs: &ConstQualifs) -> bool;
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool;
fn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
adt: AdtDef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> bool;
fn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool;
}
Expand description
A “qualif”(-ication) is a way to look for something “bad” in the MIR that would disqualify some code for promotion or prevent it from evaluating at compile time.
Normally, we would determine what qualifications apply to each type and error when an illegal
operation is performed on such a type. However, this was found to be too imprecise, especially
in the presence of enum
s. If only a single variant of an enum has a certain qualification, we
needn’t reject code unless it actually constructs and operates on the qualified variant.
To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a type-based one). Qualifications propagate structurally across variables: If a local (or a projection of a local) is assigned a qualified value, that local itself becomes qualified.
Required Associated Constants§
sourceconst ANALYSIS_NAME: &'static str
const ANALYSIS_NAME: &'static str
The name of the file used to debug the dataflow analysis that computes this qualif.
Provided Associated Constants§
sourceconst IS_CLEARED_ON_MOVE: bool = false
const IS_CLEARED_ON_MOVE: bool = false
Whether this Qualif
is cleared when a local is moved from.
sourceconst ALLOW_PROMOTED: bool = false
const ALLOW_PROMOTED: bool = false
Whether this Qualif
might be evaluated after the promotion and can encounter a promoted.
Required Methods§
sourcefn in_qualifs(qualifs: &ConstQualifs) -> bool
fn in_qualifs(qualifs: &ConstQualifs) -> bool
Extracts the field of ConstQualifs
that corresponds to this Qualif
.
sourcefn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool
Returns true
if any value of the given type could possibly have this Qualif
.
This function determines Qualif
s when we cannot do a value-based analysis. Since qualif
propagation is context-insensitive, this includes function arguments and values returned
from a call to another function.
It also determines the Qualif
s for primitive types.
sourcefn in_adt_inherently<'tcx>(
cx: &ConstCx<'_, 'tcx>,
adt: AdtDef<'tcx>,
args: GenericArgsRef<'tcx>,
) -> bool
fn in_adt_inherently<'tcx>( cx: &ConstCx<'_, 'tcx>, adt: AdtDef<'tcx>, args: GenericArgsRef<'tcx>, ) -> bool
Returns true
if this Qualif
is inherent to the given struct or enum.
By default, Qualif
s propagate into ADTs in a structural way: An ADT only becomes
qualified if part of it is assigned a value with that Qualif
. However, some ADTs always
have a certain Qualif
, regardless of whether their fields have it. For example, a type
with a custom Drop
impl is inherently NeedsDrop
.
Returning true
for in_adt_inherently
but false
for in_any_value_of_ty
is unsound.
sourcefn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool
fn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool
Returns true
if this Qualif
behaves sructurally for pointers and references:
the pointer/reference qualifies if and only if the pointee qualifies.
(This is currently false
for all our instances, but that may change in the future. Also,
by keeping it abstract, the handling of Deref
in in_place
becomes more clear.)