Skip to content

Revert #103880 "Use non-ascribed type as field's type in mir" #105905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 20, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -1488,7 +1488,7 @@ impl<'tcx> StatementKind<'tcx> {
///////////////////////////////////////////////////////////////////////////
// Places

impl<V, T, U> ProjectionElem<V, T, U> {
impl<V, T> ProjectionElem<V, T> {
/// 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, U> ProjectionElem<V, T, U> {

/// 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]
39 changes: 4 additions & 35 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
@@ -890,18 +890,11 @@ 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, T1, T2> {
pub enum ProjectionElem<V, T> {
Deref,
Field(Field, T1),
Field(Field, T),
/// Index into a slice/array.
///
/// Note that this does not also dereference, and so it does not exactly correspond to slice
@@ -957,36 +950,12 @@ pub enum ProjectionElem<V, T1, T2> {

/// Like an explicit cast from an opaque type to a concrete type, but without
/// requiring an intermediate variable.
OpaqueCast(T2),
OpaqueCast(T),
}

/// 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>, 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),
}
}
}
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;

///////////////////////////////////////////////////////////////////////////
// Operands
15 changes: 7 additions & 8 deletions compiler/rustc_middle/src/mir/tcx.rs
Original file line number Diff line number Diff line change
@@ -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, T1, T2>` do
/// not carry a `Ty` for `T1` or `T2`.)
/// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
/// not carry a `Ty` for `T`.)
///
/// Note that the resulting type has not been normalized.
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
@@ -64,18 +64,17 @@ 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, T1, T2>(
pub fn projection_ty_core<V, T>(
self,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'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>,
elem: &ProjectionElem<V, T>,
mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
) -> PlaceTy<'tcx>
where
V: ::std::fmt::Debug,
T1: ::std::fmt::Debug + Copy,
T2: ::std::fmt::Debug + Copy,
T: ::std::fmt::Debug + Copy,
{
if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
bug!("cannot use non field projection on downcasted place")
355 changes: 64 additions & 291 deletions compiler/rustc_mir_build/src/build/expr/as_place.rs

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
@@ -4,8 +4,9 @@ use rustc_index::vec::Idx;
use rustc_middle::ty::util::IntTypeExt;
use rustc_target::abi::{Abi, Primitive};

use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::category::{Category, RvalueFunc};
use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary, PlaceBuilder};
use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
use rustc_hir::lang_items::LangItem;
use rustc_middle::middle::region;
use rustc_middle::mir::AssertKind;
@@ -650,15 +651,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {

let arg_place_builder = unpack!(block = this.as_place_builder(block, arg));

let mutability = match arg_place_builder {
let mutability = match arg_place_builder.base() {
// We are capturing a path that starts off a local variable in the parent.
// The mutability of the current capture is same as the mutability
// of the local declaration in the parent.
PlaceBuilder::Local { local, .. } => this.local_decls[local].mutability,
PlaceBase::Local(local) => this.local_decls[local].mutability,
// Parent is a closure and we are capturing a path that is captured
// by the parent itself. The mutability of the current capture
// is same as that of the capture in the parent closure.
PlaceBuilder::Upvar { .. } => {
PlaceBase::Upvar { .. } => {
let enclosing_upvars_resolved = arg_place_builder.to_place(this);

match enclosing_upvars_resolved.as_ref() {
8 changes: 3 additions & 5 deletions compiler/rustc_mir_build/src/build/expr/into.rs
Original file line number Diff line number Diff line change
@@ -355,13 +355,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// base-supplied field, generate an operand that
// reads it from the base.
iter::zip(field_names, &**field_types)
.map(|(n, _ty)| match fields_map.get(&n) {
.map(|(n, ty)| match fields_map.get(&n) {
Some(v) => v.clone(),
None => {
let place_builder = place_builder.clone();
this.consume_by_copy_or_move(
place_builder.field(this, n).to_place(this),
)
let place = place_builder.clone_project(PlaceElem::Field(n, *ty));
this.consume_by_copy_or_move(place.to_place(this))
}
})
.collect()
6 changes: 3 additions & 3 deletions compiler/rustc_mir_build/src/build/matches/simplify.rs
Original file line number Diff line number Diff line change
@@ -272,9 +272,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|| !adt_def.is_variant_list_non_exhaustive());
if irrefutable {
let place_builder = match_pair.place.downcast(adt_def, variant_index);
let field_match_pairs =
self.field_match_pairs(place_builder.clone(), subpatterns);
candidate.match_pairs.extend(field_match_pairs);
candidate
.match_pairs
.extend(self.field_match_pairs(place_builder, subpatterns));
Ok(())
} else {
Err(match_pair)
3 changes: 2 additions & 1 deletion compiler/rustc_mir_build/src/build/matches/test.rs
Original file line number Diff line number Diff line change
@@ -757,7 +757,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
// e.g., `(x as Variant).0`
let place = downcast_place.clone().field(self, subpattern.field);
let place = downcast_place
.clone_project(PlaceElem::Field(subpattern.field, subpattern.pattern.ty));
// e.g., `(x as Variant).0 @ P1`
MatchPair::new(place, &subpattern.pattern, self)
});
11 changes: 6 additions & 5 deletions compiler/rustc_mir_build/src/build/matches/util.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::as_place::PlaceBuilder;
use crate::build::matches::MatchPair;
use crate::build::Builder;
@@ -16,8 +17,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
subpatterns
.iter()
.map(|fieldpat| {
let place = place.clone().field(self, fieldpat.field);

let place =
place.clone_project(PlaceElem::Field(fieldpat.field, fieldpat.pattern.ty));
MatchPair::new(place, &fieldpat.pattern, self)
})
.collect()
@@ -106,9 +107,9 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {

// Only add the OpaqueCast projection if the given place is an opaque type and the
// expected type from the pattern is not.
let may_need_cast = match place {
PlaceBuilder::Local { local, ref projection } => {
let ty = Place::ty_from(local, projection, &cx.local_decls, cx.tcx).ty;
let may_need_cast = match place.base() {
PlaceBase::Local(local) => {
let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty;
ty != pattern.ty && ty.has_opaque_types()
}
_ => true,
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ use rustc_middle::ty::Ty;
pub struct AbstractOperand;
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct AbstractType;
pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType, AbstractType>;
pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;

pub trait Lift {
type Abstract;
4 changes: 2 additions & 2 deletions compiler/rustc_mir_dataflow/src/value_analysis.rs
Original file line number Diff line number Diff line change
@@ -777,10 +777,10 @@ pub enum TrackElem {
Field(Field),
}

impl<V, T1, T2> TryFrom<ProjectionElem<V, T1, T2>> for TrackElem {
impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
type Error = ();

fn try_from(value: ProjectionElem<V, T1, T2>) -> Result<Self, Self::Error> {
fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
match value {
ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)),
_ => Err(()),
24 changes: 0 additions & 24 deletions src/test/ui/mir/field-projection-invariant.rs

This file was deleted.

15 changes: 0 additions & 15 deletions src/test/ui/mir/field-ty-ascription-enums.rs

This file was deleted.

37 changes: 0 additions & 37 deletions src/test/ui/mir/field-ty-ascription.rs

This file was deleted.

36 changes: 36 additions & 0 deletions src/test/ui/mir/issue-105809.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Non-regression test ICE from issue #105809 and duplicates.

// build-pass: the ICE is during codegen
// compile-flags: --edition 2018 -Zmir-opt-level=1

use std::{future::Future, pin::Pin};

// Create a `T` without affecting analysis like `loop {}`.
fn create<T>() -> T {
loop {}
}

async fn trivial_future() {}

struct Connection<H> {
_h: H,
}

async fn complex_future<H>(conn: &Connection<H>) {
let small_fut = async move {
let _ = conn;
trivial_future().await;
};

let mut tuple = (small_fut,);
let (small_fut_again,) = &mut tuple;
let _ = small_fut_again;
}

fn main() {
let mut fut = complex_future(&Connection { _h: () });

let mut cx = create();
let future = unsafe { Pin::new_unchecked(&mut fut) };
let _ = future.poll(&mut cx);
}