summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_mir_build/src/build/expr
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs40
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs188
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs45
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs10
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs28
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs22
7 files changed, 134 insertions, 204 deletions
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 648d10b9e..37dc1ad9f 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -2,26 +2,19 @@
use crate::build::{parse_float_into_constval, Builder};
use rustc_ast as ast;
-use rustc_hir::def_id::DefId;
+use rustc_middle::mir;
use rustc_middle::mir::interpret::{
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
};
use rustc_middle::mir::*;
use rustc_middle::thir::*;
-use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
+use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, TyCtxt};
use rustc_target::abi::Size;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant!
pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
- let create_uneval_from_def_id =
- |tcx: TyCtxt<'tcx>, def_id: DefId, ty: Ty<'tcx>, substs: SubstsRef<'tcx>| {
- let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
- tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Unevaluated(uneval), ty })
- };
-
let this = self;
let tcx = this.tcx;
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
@@ -41,11 +34,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { span, user_ty: None, literal }
}
- ExprKind::NonHirLiteral { lit, user_ty } => {
- let user_ty = user_ty.map(|user_ty| {
+ ExprKind::NonHirLiteral { lit, ref user_ty } => {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
@@ -53,11 +46,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { span, user_ty: user_ty, literal }
}
- ExprKind::ZstLiteral { user_ty } => {
- let user_ty = user_ty.map(|user_ty| {
+ ExprKind::ZstLiteral { ref user_ty } => {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
@@ -65,15 +58,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { span, user_ty: user_ty, literal }
}
- ExprKind::NamedConst { def_id, substs, user_ty } => {
- let user_ty = user_ty.map(|user_ty| {
+ ExprKind::NamedConst { def_id, substs, ref user_ty } => {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span,
- user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: ty,
})
});
- let literal = ConstantKind::Ty(create_uneval_from_def_id(tcx, def_id, ty, substs));
+
+ let uneval =
+ mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty, span, literal }
}
@@ -85,7 +81,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { user_ty: None, span, literal }
}
ExprKind::ConstBlock { did: def_id, substs } => {
- let literal = ConstantKind::Ty(create_uneval_from_def_id(tcx, def_id, ty, substs));
+ let uneval =
+ mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty: None, span, literal }
}
@@ -144,7 +142,7 @@ pub(crate) fn lit_to_mir_constant<'tcx>(
}
(ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
(ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
- (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
+ (ast::LitKind::Err, _) => return Err(LitToConstError::Reported),
_ => return Err(LitToConstError::TypeError),
};
diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
index e707c373f..c8610af70 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -153,12 +153,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if tcx.features().unsized_fn_params {
let ty = expr.ty;
- let span = expr.span;
let param_env = this.param_env;
- if !ty.is_sized(tcx.at(span), param_env) {
+ if !ty.is_sized(tcx, param_env) {
// !sized means !copy, so this is an unsized move
- assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env));
+ assert!(!ty.is_copy_modulo_regions(tcx, param_env));
// As described above, detect the case where we are passing a value of unsized
// type, and that value is coming from the deref of a box.
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index 0c06aad4e..396782d45 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -2,7 +2,7 @@
use crate::build::expr::category::Category;
use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
-use crate::build::{BlockAnd, BlockAndExtension, Builder};
+use crate::build::{BlockAnd, BlockAndExtension, Builder, Capture, CaptureMap};
use rustc_hir::def_id::LocalDefId;
use rustc_middle::hir::place::Projection as HirProjection;
use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
@@ -17,6 +17,7 @@ use rustc_target::abi::VariantIdx;
use rustc_index::vec::Idx;
+use std::assert_matches::assert_matches;
use std::iter;
/// The "outermost" place that holds this value.
@@ -59,8 +60,6 @@ pub(crate) enum PlaceBase {
var_hir_id: LocalVarId,
/// DefId of the closure
closure_def_id: LocalDefId,
- /// The trait closure implements, `Fn`, `FnMut`, `FnOnce`
- closure_kind: ty::ClosureKind,
},
}
@@ -71,7 +70,7 @@ pub(crate) enum PlaceBase {
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
#[derive(Clone, Debug, PartialEq)]
-pub(crate) struct PlaceBuilder<'tcx> {
+pub(in crate::build) struct PlaceBuilder<'tcx> {
base: PlaceBase,
projection: Vec<PlaceElem<'tcx>>,
}
@@ -104,6 +103,8 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
variant = Some(*idx);
continue;
}
+ // These do not affect anything, they just make sure we know the right type.
+ ProjectionElem::OpaqueCast(_) => continue,
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => {
@@ -145,27 +146,6 @@ fn is_ancestor_or_same_capture(
iter::zip(proj_possible_ancestor, proj_capture).all(|(a, b)| a == b)
}
-/// Computes the index of a capture within the desugared closure provided the closure's
-/// `closure_min_captures` and the capture's index of the capture in the
-/// `ty::MinCaptureList` of the root variable `var_hir_id`.
-fn compute_capture_idx<'tcx>(
- closure_min_captures: &ty::RootVariableMinCaptureList<'tcx>,
- var_hir_id: LocalVarId,
- root_var_idx: usize,
-) -> usize {
- let mut res = 0;
- for (var_id, capture_list) in closure_min_captures {
- if *var_id == var_hir_id.0 {
- res += root_var_idx;
- break;
- } else {
- res += capture_list.len();
- }
- }
-
- res
-}
-
/// Given a closure, returns the index of a capture within the desugared closure struct and the
/// `ty::CapturedPlace` which is the ancestor of the Place represented using the `var_hir_id`
/// and `projection`.
@@ -174,58 +154,39 @@ fn compute_capture_idx<'tcx>(
///
/// Returns None, when the ancestor is not found.
fn find_capture_matching_projections<'a, 'tcx>(
- typeck_results: &'a ty::TypeckResults<'tcx>,
+ upvars: &'a CaptureMap<'tcx>,
var_hir_id: LocalVarId,
- closure_def_id: LocalDefId,
projections: &[PlaceElem<'tcx>],
-) -> Option<(usize, &'a ty::CapturedPlace<'tcx>)> {
- let closure_min_captures = typeck_results.closure_min_captures.get(&closure_def_id)?;
- let root_variable_min_captures = closure_min_captures.get(&var_hir_id.0)?;
-
+) -> Option<(usize, &'a Capture<'tcx>)> {
let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections);
- // If an ancestor is found, `idx` is the index within the list of captured places
- // for root variable `var_hir_id` and `capture` is the `ty::CapturedPlace` itself.
- let (idx, capture) = root_variable_min_captures.iter().enumerate().find(|(_, capture)| {
+ upvars.get_by_key_enumerated(var_hir_id.0).find(|(_, capture)| {
let possible_ancestor_proj_kinds: Vec<_> =
- capture.place.projections.iter().map(|proj| proj.kind).collect();
+ capture.captured_place.place.projections.iter().map(|proj| proj.kind).collect();
is_ancestor_or_same_capture(&possible_ancestor_proj_kinds, &hir_projections)
- })?;
-
- // Convert index to be from the perspective of the entire closure_min_captures map
- // instead of just the root variable capture list
- Some((compute_capture_idx(closure_min_captures, var_hir_id, idx), capture))
+ })
}
/// Takes a PlaceBuilder and resolves the upvar (if any) within it, so that the
/// `PlaceBuilder` now starts from `PlaceBase::Local`.
///
/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
-fn to_upvars_resolved_place_builder<'a, 'tcx>(
+#[instrument(level = "trace", skip(cx), ret)]
+fn to_upvars_resolved_place_builder<'tcx>(
from_builder: PlaceBuilder<'tcx>,
- tcx: TyCtxt<'tcx>,
- typeck_results: &'a ty::TypeckResults<'tcx>,
+ cx: &Builder<'_, 'tcx>,
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
match from_builder.base {
PlaceBase::Local(_) => Ok(from_builder),
- PlaceBase::Upvar { var_hir_id, closure_def_id, closure_kind } => {
- let mut upvar_resolved_place_builder = PlaceBuilder::from(ty::CAPTURE_STRUCT_LOCAL);
- match closure_kind {
- ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
- upvar_resolved_place_builder = upvar_resolved_place_builder.deref();
- }
- ty::ClosureKind::FnOnce => {}
- }
-
+ PlaceBase::Upvar { var_hir_id, closure_def_id } => {
let Some((capture_index, capture)) =
find_capture_matching_projections(
- typeck_results,
+ &cx.upvars,
var_hir_id,
- closure_def_id,
&from_builder.projection,
) else {
- let closure_span = tcx.def_span(closure_def_id);
- if !enable_precise_capture(tcx, closure_span) {
+ let closure_span = cx.tcx.def_span(closure_def_id);
+ if !enable_precise_capture(cx.tcx, closure_span) {
bug!(
"No associated capture found for {:?}[{:#?}] even though \
capture_disjoint_fields isn't enabled",
@@ -241,39 +202,18 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
return Err(from_builder);
};
- // We won't be building MIR if the closure wasn't local
- let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id);
- let closure_ty = typeck_results.node_type(closure_hir_id);
-
- let substs = match closure_ty.kind() {
- ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
- ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
- _ => bug!("Lowering capture for non-closure type {:?}", closure_ty),
- };
-
// Access the capture by accessing the field within the Closure struct.
- //
- // We must have inferred the capture types since we are building MIR, therefore
- // it's safe to call `tuple_element_ty` and we can unwrap here because
- // we know that the capture exists and is the `capture_index`-th capture.
- let var_ty = substs.tupled_upvars_ty().tuple_fields()[capture_index];
-
- upvar_resolved_place_builder =
- upvar_resolved_place_builder.field(Field::new(capture_index), var_ty);
-
- // If the variable is captured via ByRef(Immutable/Mutable) Borrow,
- // we need to deref it
- upvar_resolved_place_builder = match capture.info.capture_kind {
- ty::UpvarCapture::ByRef(_) => upvar_resolved_place_builder.deref(),
- ty::UpvarCapture::ByValue => upvar_resolved_place_builder,
- };
+ let capture_info = &cx.upvars[capture_index];
+
+ let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
// We used some of the projections to build the capture itself,
// now we apply the remaining to the upvar resolved place.
+ trace!(?capture.captured_place, ?from_builder.projection);
let remaining_projections = strip_prefix(
- capture.place.base_ty,
+ capture.captured_place.place.base_ty,
from_builder.projection,
- &capture.place.projections,
+ &capture.captured_place.place.projections,
);
upvar_resolved_place_builder.projection.extend(remaining_projections);
@@ -293,17 +233,20 @@ fn strip_prefix<'tcx>(
projections: Vec<PlaceElem<'tcx>>,
prefix_projections: &[HirProjection<'tcx>],
) -> impl Iterator<Item = PlaceElem<'tcx>> {
- let mut iter = projections.into_iter();
+ let mut iter = projections
+ .into_iter()
+ // Filter out opaque casts, they are unnecessary in the prefix.
+ .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)));
for projection in prefix_projections {
match projection.kind {
HirProjectionKind::Deref => {
- assert!(matches!(iter.next(), Some(ProjectionElem::Deref)));
+ assert_matches!(iter.next(), Some(ProjectionElem::Deref));
}
HirProjectionKind::Field(..) => {
if base_ty.is_enum() {
- assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
+ assert_matches!(iter.next(), Some(ProjectionElem::Downcast(..)));
}
- assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
+ assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
}
HirProjectionKind::Index | HirProjectionKind::Subslice => {
bug!("unexpected projection kind: {:?}", projection);
@@ -315,24 +258,16 @@ fn strip_prefix<'tcx>(
}
impl<'tcx> PlaceBuilder<'tcx> {
- pub(crate) fn into_place<'a>(
- self,
- tcx: TyCtxt<'tcx>,
- typeck_results: &'a ty::TypeckResults<'tcx>,
- ) -> Place<'tcx> {
+ pub(in crate::build) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
if let PlaceBase::Local(local) = self.base {
- Place { local, projection: tcx.intern_place_elems(&self.projection) }
+ Place { local, projection: cx.tcx.intern_place_elems(&self.projection) }
} else {
- self.expect_upvars_resolved(tcx, typeck_results).into_place(tcx, typeck_results)
+ self.expect_upvars_resolved(cx).into_place(cx)
}
}
- fn expect_upvars_resolved<'a>(
- self,
- tcx: TyCtxt<'tcx>,
- typeck_results: &'a ty::TypeckResults<'tcx>,
- ) -> PlaceBuilder<'tcx> {
- to_upvars_resolved_place_builder(self, tcx, typeck_results).unwrap()
+ fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
+ to_upvars_resolved_place_builder(self, cx).unwrap()
}
/// Attempts to resolve the `PlaceBuilder`.
@@ -346,18 +281,21 @@ impl<'tcx> PlaceBuilder<'tcx> {
/// not captured. This can happen because the final mir that will be
/// generated doesn't require a read for this place. Failures will only
/// happen inside closures.
- pub(crate) fn try_upvars_resolved<'a>(
+ pub(in crate::build) fn try_upvars_resolved(
self,
- tcx: TyCtxt<'tcx>,
- typeck_results: &'a ty::TypeckResults<'tcx>,
+ cx: &Builder<'_, 'tcx>,
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
- to_upvars_resolved_place_builder(self, tcx, typeck_results)
+ to_upvars_resolved_place_builder(self, cx)
}
pub(crate) fn base(&self) -> PlaceBase {
self.base
}
+ pub(crate) fn projection(&self) -> &[PlaceElem<'tcx>] {
+ &self.projection
+ }
+
pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
self.project(PlaceElem::Field(f, ty))
}
@@ -392,6 +330,12 @@ impl<'tcx> From<PlaceBase> for PlaceBuilder<'tcx> {
}
}
+impl<'tcx> From<Place<'tcx>> for PlaceBuilder<'tcx> {
+ fn from(p: Place<'tcx>) -> Self {
+ Self { base: PlaceBase::Local(p.local), projection: p.projection.to_vec() }
+ }
+}
+
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a place that we can move from etc.
///
@@ -411,7 +355,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>,
) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_place_builder(block, expr));
- block.and(place_builder.into_place(self.tcx, self.typeck_results))
+ block.and(place_builder.into_place(self))
}
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -435,7 +379,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>,
) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
- block.and(place_builder.into_place(self.tcx, self.typeck_results))
+ block.and(place_builder.into_place(self))
}
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -513,7 +457,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.and(place_builder)
}
- ExprKind::PlaceTypeAscription { source, user_ty } => {
+ ExprKind::PlaceTypeAscription { source, ref user_ty } => {
let place_builder = unpack!(
block = this.expr_as_place(
block,
@@ -526,11 +470,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: expr.ty,
});
- let place = place_builder.clone().into_place(this.tcx, this.typeck_results);
+ let place = place_builder.clone().into_place(this);
this.cfg.push(
block,
Statement {
@@ -547,7 +491,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
block.and(place_builder)
}
- ExprKind::ValueTypeAscription { source, user_ty } => {
+ ExprKind::ValueTypeAscription { source, ref user_ty } => {
let source = &this.thir[source];
let temp =
unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
@@ -555,7 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let annotation_index =
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty,
+ user_ty: user_ty.clone(),
inferred_ty: expr.ty,
});
this.cfg.push(
@@ -629,17 +573,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
closure_def_id: LocalDefId,
var_hir_id: LocalVarId,
) -> BlockAnd<PlaceBuilder<'tcx>> {
- let closure_ty =
- self.typeck_results.node_type(self.tcx.hir().local_def_id_to_hir_id(closure_def_id));
-
- let closure_kind = if let ty::Closure(_, closure_substs) = closure_ty.kind() {
- self.infcx.closure_kind(closure_substs).unwrap()
- } else {
- // Generators are considered FnOnce.
- ty::ClosureKind::FnOnce
- };
-
- block.and(PlaceBuilder::from(PlaceBase::Upvar { var_hir_id, closure_def_id, closure_kind }))
+ block.and(PlaceBuilder::from(PlaceBase::Upvar { var_hir_id, closure_def_id }))
}
/// Lower an index expression
@@ -678,7 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if is_outermost_index {
self.read_fake_borrows(block, fake_borrow_temps, source_info)
} else {
- base_place = base_place.expect_upvars_resolved(self.tcx, self.typeck_results);
+ base_place = base_place.expect_upvars_resolved(self);
self.add_fake_borrows_of_base(
&base_place,
block,
@@ -706,12 +640,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let lt = self.temp(bool_ty, expr_span);
// len = len(slice)
- self.cfg.push_assign(
- block,
- source_info,
- len,
- Rvalue::Len(slice.into_place(self.tcx, self.typeck_results)),
- );
+ self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self)));
// lt = idx < len
self.cfg.push_assign(
block,
@@ -791,6 +720,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ProjectionElem::Field(..)
| ProjectionElem::Downcast(..)
+ | ProjectionElem::OpaqueCast(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => (),
}
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 15f2d17c4..3dafdcb78 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -12,7 +12,7 @@ use rustc_middle::mir::AssertKind;
use rustc_middle::mir::Place;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
-use rustc_middle::ty::cast::CastTy;
+use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
use rustc_middle::ty::{self, Ty, UpvarSubsts};
use rustc_span::Span;
@@ -197,13 +197,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// create all the steps directly in MIR with operations all backends need to support anyway.
let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() {
let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
- let place = unpack!(block = this.as_place(block, source));
+ let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
let discr = this.temp(discr_ty, source.span);
this.cfg.push_assign(
block,
source_info,
discr,
- Rvalue::Discriminant(place),
+ Rvalue::Discriminant(temp.into()),
);
(Operand::Move(discr), discr_ty)
@@ -216,15 +216,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
};
let from_ty = CastTy::from_ty(ty);
let cast_ty = CastTy::from_ty(expr.ty);
- let cast_kind = match (from_ty, cast_ty) {
- (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
- CastKind::PointerExposeAddress
- }
- (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
- CastKind::PointerFromExposedAddress
- }
- (_, _) => CastKind::Misc,
- };
+ debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty,);
+ let cast_kind = mir_cast_kind(ty, expr.ty);
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
}
ExprKind::Pointer { cast, source } => {
@@ -302,7 +295,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
block.and(Rvalue::Aggregate(Box::new(AggregateKind::Tuple), fields))
}
- ExprKind::Closure { closure_id, substs, ref upvars, movability, ref fake_reads } => {
+ ExprKind::Closure(box ClosureExpr {
+ closure_id,
+ substs,
+ ref upvars,
+ movability,
+ ref fake_reads,
+ }) => {
// Convert the closure fake reads, if any, from `ExprRef` to mir `Place`
// and push the fake reads.
// This must come before creating the operands. This is required in case
@@ -321,11 +320,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let place_builder =
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
- if let Ok(place_builder_resolved) =
- place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
- {
- let mir_place =
- place_builder_resolved.into_place(this.tcx, this.typeck_results);
+ if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
+ let mir_place = place_builder_resolved.into_place(this);
this.cfg.push_fake_read(
block,
this.source_info(this.tcx.hir().span(*hir_id)),
@@ -616,8 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// by the parent itself. The mutability of the current capture
// is same as that of the capture in the parent closure.
PlaceBase::Upvar { .. } => {
- let enclosing_upvars_resolved =
- arg_place_builder.clone().into_place(this.tcx, this.typeck_results);
+ let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
match enclosing_upvars_resolved.as_ref() {
PlaceRef {
@@ -637,12 +632,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
// Not in a closure
debug_assert!(
- this.upvar_mutbls.len() > upvar_index.index(),
- "Unexpected capture place, upvar_mutbls={:#?}, upvar_index={:?}",
- this.upvar_mutbls,
+ this.upvars.len() > upvar_index.index(),
+ "Unexpected capture place, upvars={:#?}, upvar_index={:?}",
+ this.upvars,
upvar_index
);
- this.upvar_mutbls[upvar_index.index()]
+ this.upvars[upvar_index.index()].mutability
}
_ => bug!("Unexpected capture place"),
}
@@ -654,7 +649,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
};
- let arg_place = arg_place_builder.into_place(this.tcx, this.typeck_results);
+ let arg_place = arg_place_builder.into_place(this);
this.cfg.push_assign(
block,
diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
index 724b72f87..0ca4e3745 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -23,6 +23,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
}
+ #[instrument(skip(self), level = "debug")]
fn as_temp_inner(
&mut self,
mut block: BasicBlock,
@@ -30,10 +31,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>,
mutability: Mutability,
) -> BlockAnd<Local> {
- debug!(
- "as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
- block, temp_lifetime, expr, mutability
- );
let this = self;
let expr_span = expr.span;
@@ -83,8 +80,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Don't bother with StorageLive and Dead for these temporaries,
// they are never assigned.
ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (),
- ExprKind::Block { body: Block { expr: None, targeted_by_break: false, .. } }
- if expr_ty.is_never() => {}
+ ExprKind::Block { block }
+ if let Block { expr: None, targeted_by_break: false, .. } = this.thir[block]
+ && expr_ty.is_never() => {}
_ => {
this.cfg
.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) });
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 017d43d10..24ecd0a53 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -15,14 +15,13 @@ use std::iter;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized.
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn expr_into_dest(
&mut self,
destination: Place<'tcx>,
mut block: BasicBlock,
expr: &Expr<'tcx>,
) -> BlockAnd<()> {
- debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
-
// since we frequently have to reference `self` from within a
// closure, where `self` would be shadowed, it's easier to
// just use the name `this` uniformly
@@ -46,7 +45,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
})
})
}
- ExprKind::Block { body: ref ast_block } => {
+ ExprKind::Block { block: ast_block } => {
this.ast_block(destination, block, ast_block, source_info)
}
ExprKind::Match { scrutinee, ref arms } => {
@@ -75,7 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.source_info(then_expr.span)
};
let (then_block, else_block) =
- this.in_if_then_scope(condition_scope, |this| {
+ this.in_if_then_scope(condition_scope, then_expr.span, |this| {
let then_blk = unpack!(this.then_else_break(
block,
&this.thir[cond],
@@ -108,7 +107,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ExprKind::Let { expr, ref pat } => {
let scope = this.local_scope();
- let (true_block, false_block) = this.in_if_then_scope(scope, |this| {
+ let (true_block, false_block) = this.in_if_then_scope(scope, expr_span, |this| {
this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span)
});
@@ -314,11 +313,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.cfg.push_assign(block, source_info, destination, address_of);
block.unit()
}
- ExprKind::Adt(box Adt {
+ ExprKind::Adt(box AdtExpr {
adt_def,
variant_index,
substs,
- user_ty,
+ ref user_ty,
ref fields,
ref base,
}) => {
@@ -366,9 +365,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None => {
let place_builder = place_builder.clone();
this.consume_by_copy_or_move(
- place_builder
- .field(n, *ty)
- .into_place(this.tcx, this.typeck_results),
+ place_builder.field(n, *ty).into_place(this),
)
}
})
@@ -378,10 +375,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
};
let inferred_ty = expr.ty;
- let user_ty = user_ty.map(|ty| {
+ let user_ty = user_ty.as_ref().map(|user_ty| {
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
span: source_info.span,
- user_ty: ty,
+ user_ty: user_ty.clone(),
inferred_ty,
})
});
@@ -400,7 +397,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
block.unit()
}
- ExprKind::InlineAsm { template, ref operands, options, line_spans } => {
+ ExprKind::InlineAsm(box InlineAsmExpr {
+ template,
+ ref operands,
+ options,
+ line_spans,
+ }) => {
use rustc_middle::{mir, thir};
let operands = operands
.into_iter()
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index a7e1331aa..00dbcaeb0 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -116,14 +116,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// it is usually better to focus on `the_value` rather
// than the entirety of block(s) surrounding it.
let adjusted_span = (|| {
- if let ExprKind::Block { body } = &expr.kind && let Some(tail_ex) = body.expr {
+ if let ExprKind::Block { block } = expr.kind
+ && let Some(tail_ex) = this.thir[block].expr
+ {
let mut expr = &this.thir[tail_ex];
- while let ExprKind::Block {
- body: Block { expr: Some(nested_expr), .. },
- }
- | ExprKind::Scope { value: nested_expr, .. } = expr.kind
- {
- expr = &this.thir[nested_expr];
+ loop {
+ match expr.kind {
+ ExprKind::Block { block }
+ if let Some(nested_expr) = this.thir[block].expr =>
+ {
+ expr = &this.thir[nested_expr];
+ }
+ ExprKind::Scope { value: nested_expr, .. } => {
+ expr = &this.thir[nested_expr];
+ }
+ _ => break,
+ }
}
this.block_context.push(BlockFrame::TailExpr {
tail_result_is_ignored: true,