Auto merge of #103880 - b-naber:field-ty-mir, r=lcnr
Use non-ascribed type as field's type in mir Fixes https://github.com/rust-lang/rust/issues/96514 r? `@lcnr`
This commit is contained in:
commit
03770f0e2b
14 changed files with 434 additions and 100 deletions
|
@ -1488,7 +1488,7 @@ impl<'tcx> StatementKind<'tcx> {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// Places
|
||||
|
||||
impl<V, T> ProjectionElem<V, T> {
|
||||
impl<V, T, U> ProjectionElem<V, T, U> {
|
||||
/// Returns `true` if the target of this projection may refer to a different region of memory
|
||||
/// than the base.
|
||||
fn is_indirect(&self) -> bool {
|
||||
|
@ -1517,7 +1517,7 @@ impl<V, T> ProjectionElem<V, T> {
|
|||
|
||||
/// Alias for projections as they appear in `UserTypeProjection`, where we
|
||||
/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
|
||||
pub type ProjectionKind = ProjectionElem<(), ()>;
|
||||
pub type ProjectionKind = ProjectionElem<(), (), ()>;
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG]
|
||||
|
|
|
@ -890,11 +890,18 @@ pub struct Place<'tcx> {
|
|||
pub projection: &'tcx List<PlaceElem<'tcx>>,
|
||||
}
|
||||
|
||||
/// The different kinds of projections that can be used in the projection of a `Place`.
|
||||
///
|
||||
/// `T1` is the generic type for a field projection. For an actual projection on a `Place`
|
||||
/// this parameter will always be `Ty`, but the field type can be unavailable when
|
||||
/// building (by using `PlaceBuilder`) places that correspond to upvars.
|
||||
/// `T2` is the generic type for an `OpaqueCast` (is generic since it's abstracted over
|
||||
/// in dataflow analysis, see `AbstractElem`).
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub enum ProjectionElem<V, T> {
|
||||
pub enum ProjectionElem<V, T1, T2> {
|
||||
Deref,
|
||||
Field(Field, T),
|
||||
Field(Field, T1),
|
||||
/// Index into a slice/array.
|
||||
///
|
||||
/// Note that this does not also dereference, and so it does not exactly correspond to slice
|
||||
|
@ -950,12 +957,36 @@ pub enum ProjectionElem<V, T> {
|
|||
|
||||
/// Like an explicit cast from an opaque type to a concrete type, but without
|
||||
/// requiring an intermediate variable.
|
||||
OpaqueCast(T),
|
||||
OpaqueCast(T2),
|
||||
}
|
||||
|
||||
/// Alias for projections as they appear in places, where the base is a place
|
||||
/// and the index is a local.
|
||||
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
|
||||
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>, Ty<'tcx>>;
|
||||
|
||||
/// Alias for projections that appear in `PlaceBuilder::Upvar`, for which
|
||||
/// we cannot provide any field types.
|
||||
pub type UpvarProjectionElem<'tcx> = ProjectionElem<Local, (), Ty<'tcx>>;
|
||||
|
||||
impl<'tcx> From<PlaceElem<'tcx>> for UpvarProjectionElem<'tcx> {
|
||||
fn from(elem: PlaceElem<'tcx>) -> Self {
|
||||
match elem {
|
||||
ProjectionElem::Deref => ProjectionElem::Deref,
|
||||
ProjectionElem::Field(field, _) => ProjectionElem::Field(field, ()),
|
||||
ProjectionElem::Index(v) => ProjectionElem::Index(v),
|
||||
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
|
||||
ProjectionElem::ConstantIndex { offset, min_length, from_end }
|
||||
}
|
||||
ProjectionElem::Subslice { from, to, from_end } => {
|
||||
ProjectionElem::Subslice { from, to, from_end }
|
||||
}
|
||||
ProjectionElem::Downcast(opt_sym, variant_idx) => {
|
||||
ProjectionElem::Downcast(opt_sym, variant_idx)
|
||||
}
|
||||
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Operands
|
||||
|
|
|
@ -28,8 +28,8 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
/// `place_ty.field_ty(tcx, f)` computes the type at a given field
|
||||
/// of a record or enum-variant. (Most clients of `PlaceTy` can
|
||||
/// instead just extract the relevant type directly from their
|
||||
/// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
|
||||
/// not carry a `Ty` for `T`.)
|
||||
/// `PlaceElem`, but some instances of `ProjectionElem<V, T1, T2>` do
|
||||
/// not carry a `Ty` for `T1` or `T2`.)
|
||||
///
|
||||
/// Note that the resulting type has not been normalized.
|
||||
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
|
||||
|
@ -64,17 +64,18 @@ impl<'tcx> PlaceTy<'tcx> {
|
|||
/// `Ty` or downcast variant corresponding to that projection.
|
||||
/// The `handle_field` callback must map a `Field` to its `Ty`,
|
||||
/// (which should be trivial when `T` = `Ty`).
|
||||
pub fn projection_ty_core<V, T>(
|
||||
pub fn projection_ty_core<V, T1, T2>(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
elem: &ProjectionElem<V, T>,
|
||||
mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
|
||||
mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
|
||||
elem: &ProjectionElem<V, T1, T2>,
|
||||
mut handle_field: impl FnMut(&Self, Field, T1) -> Ty<'tcx>,
|
||||
mut handle_opaque_cast: impl FnMut(&Self, T2) -> Ty<'tcx>,
|
||||
) -> PlaceTy<'tcx>
|
||||
where
|
||||
V: ::std::fmt::Debug,
|
||||
T: ::std::fmt::Debug + Copy,
|
||||
T1: ::std::fmt::Debug + Copy,
|
||||
T2: ::std::fmt::Debug + Copy,
|
||||
{
|
||||
if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
|
||||
bug!("cannot use non field projection on downcasted place")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue