Description
As far as I can tell, the actual discriminant values of an enum aren't exposed in stable_mir. Which, amongst other things, means we can't tell what branch we traverse in match/if-let statements.
Kani uses discriminant_for_variant
on a rustc_middle::ty::Ty
for this. discriminant_for_variant
returns an Option<Discr<'tcx>>
where Discr
contains a val: u128
, and a ty: Ty<'tcx>
.
Would a PR adding this method to stable_mir be welcome?
I think the most natural place for this in stable_mir
is RigidTy
, which is also where discriminant_ty
is in stable_mir
.
The value is really meaningful for two variants of RigidTy
: AdtDef
and Coroutine
. rustc_middle::Ty::discriminant_for_variant
returns None
except on those two types. We could either copy that behavior, or we could follow the definition of stable_mir::Rvalue::Discriminant
and return a 0
of the appropriate type for all RigidTy
s other than AdtDef
and Coroutine
(probably requiring that variant_idx = 0
). The latter seems more consistent with the intent to me, but I don't think it matters a whole lot either way.
Alternatively or additionally we could add it (and maybe discriminant_ty
as well) on AdtDef
and Coroutine
. Or we could follow rustc_middle
and put it on Ty
, though IMHO that's a strange place to have it.
For context:
rustc_middle
exposes discriminant_for_variant
on Ty
(returning an Option
), and directly on AdtDef
(which might make sense for us), and CoroutineArgs
(which we don't even have, but we could substitute in Coroutine
). It also exposes discriminant_ty
only on Ty
, not on RigidTy
(like stable_mir
does), nor on AdtDef
/Coroutine
despite the discriminant_for_variant
functions.
discriminant_ty
's detailed behavior in rustc_middle
is as follows:
Bound
,Placeholder
,Fresh...Ty
:bug
AdtDef
andCoroutine
delegate toAdtDef
/CourtineArgsExt
.Param
,Alias
, andInfer
it returns some projected type (not sure I understand that)ty::Pat
it defers to thety
in the pattern.- For everything else it returns
u8
.
stable_mir
has a discriminant_ty
on TyKind
as well as RigidTy
, it returns an Option<Ty>
and is simply calling RigidTy
's AdtDef
.
rustc_middle
also has AdtDef
/CoroutineArgs``::discriminants
returning an iterator over all variants, and AdtDef::discrimimant_def_for_variant
returning a Option<DefId>
of the most recent variant with an explicit definition and a u32
offset from that.