Skip to content

Commit

Permalink
Auto merge of rust-lang#79553 - sexxi-goose:mir_min_cap_writeback, r=…
Browse files Browse the repository at this point in the history
…nikomatsakis

Capture precise paths in THIR and MIR

This PR allows THIR and MIR to use the result of the new capture analysis to actually capture precise paths

To achieve we:
- Writeback min capture results to TypeckResults
- Move handling upvars to PlaceBuilder in mir_build
- Lower precise paths in THIR build by reading min_captures
- Search for ancestors in min_capture when trying to build a MIR place which starts off of an upvar

Closes: rust-lang/project-rfc-2229#10

Partly implements: rust-lang/project-rfc-2229#18

Work that remains (not in this PR):
- [ ] [Known bugs when feature gate is enabled](https://github.com/rust-lang/project-rfc-2229/projects/1?card_filter_query=label%3Abug)
- [ ] Use min_capure_map for
  - [ ] Liveness analysis
  - [ ] rustc_mir/interpret/validity.rs
  - [ ] regionck
- [ ] rust-lang/project-rfc-2229#8
- [ ] remove closure_captures and upvar_capture_map

r? `@ghost`
  • Loading branch information
bors committed Dec 12, 2020
2 parents 9eb3a7c + 01df563 commit 5bd9b60
Show file tree
Hide file tree
Showing 41 changed files with 1,483 additions and 233 deletions.
43 changes: 38 additions & 5 deletions compiler/rustc_middle/src/hir/place.rs
Expand Up @@ -4,7 +4,18 @@ use crate::ty::Ty;
use rustc_hir::HirId;
use rustc_target::abi::VariantIdx;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
pub enum PlaceBase {
/// A temporary variable
Rvalue,
Expand All @@ -16,7 +27,18 @@ pub enum PlaceBase {
Upvar(ty::UpvarId),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
pub enum ProjectionKind {
/// A dereference of a pointer, reference or `Box<T>` of the given type
Deref,
Expand All @@ -36,7 +58,18 @@ pub enum ProjectionKind {
Subslice,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
pub struct Projection<'tcx> {
/// Type after the projection is being applied.
pub ty: Ty<'tcx>,
Expand All @@ -48,7 +81,7 @@ pub struct Projection<'tcx> {
/// A `Place` represents how a value is located in memory.
///
/// This is an HIR version of `mir::Place`
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct Place<'tcx> {
/// The type of the `PlaceBase`
pub base_ty: Ty<'tcx>,
Expand All @@ -61,7 +94,7 @@ pub struct Place<'tcx> {
/// A `PlaceWithHirId` represents how a value is located in memory.
///
/// This is an HIR version of `mir::Place`
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct PlaceWithHirId<'tcx> {
/// `HirId` of the expression or pattern producing this value.
pub hir_id: HirId,
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Expand Up @@ -624,6 +624,19 @@ impl<'tcx> TypeckResults<'tcx> {
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
}

/// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
/// by the closure.
pub fn closure_min_captures_flattened(
&self,
closure_def_id: DefId,
) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
self.closure_min_captures
.get(&closure_def_id)
.map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
.into_iter()
.flatten()
}

pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> {
self.upvar_capture_map[&upvar_id]
}
Expand Down
25 changes: 18 additions & 7 deletions compiler/rustc_middle/src/ty/mod.rs
Expand Up @@ -672,15 +672,26 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
#[rustc_diagnostic_item = "Ty"]
pub type Ty<'tcx> = &'tcx TyS<'tcx>;

#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
pub struct UpvarPath {
pub hir_id: hir::HirId,
}

/// Upvars do not get their own `NodeId`. Instead, we use the pair of
/// the original var ID (that is, the root variable that is referenced
/// by the upvar) and the ID of the closure expression.
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct UpvarId {
pub var_path: UpvarPath,
pub closure_expr_id: LocalDefId,
Expand All @@ -692,7 +703,7 @@ impl UpvarId {
}
}

#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)]
#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
ImmBorrow,
Expand Down Expand Up @@ -746,7 +757,7 @@ pub enum BorrowKind {

/// Information describing the capture of an upvar. This is computed
/// during `typeck`, specifically by `regionck`.
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub enum UpvarCapture<'tcx> {
/// Upvar is captured by value. This is always true when the
/// closure is labeled `move`, but can also be true in other cases
Expand All @@ -763,7 +774,7 @@ pub enum UpvarCapture<'tcx> {
ByRef(UpvarBorrow<'tcx>),
}

#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, HashStable)]
#[derive(PartialEq, Clone, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct UpvarBorrow<'tcx> {
/// The kind of borrow: by-ref upvars have access to shared
/// immutable borrows, which are not part of the normal language
Expand All @@ -790,7 +801,7 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis
pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;

/// A `Place` and the corresponding `CaptureInfo`.
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct CapturedPlace<'tcx> {
pub place: HirPlace<'tcx>,
pub info: CaptureInfo<'tcx>,
Expand All @@ -799,7 +810,7 @@ pub struct CapturedPlace<'tcx> {
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
/// for a particular capture as well as identifying the part of the source code
/// that triggered this capture to occur.
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct CaptureInfo<'tcx> {
/// Expr Id pointing to use that resulted in selecting the current capture kind
///
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Expand Up @@ -2174,6 +2174,15 @@ impl<'tcx> TyS<'tcx> {
}
}

/// Get the `i`-th element of a tuple.
/// Panics when called on anything but a tuple.
pub fn tuple_element_ty(&self, i: usize) -> Option<Ty<'tcx>> {
match self.kind() {
Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()),
_ => bug!("tuple_fields called on non-tuple"),
}
}

/// If the type contains variants, returns the valid range of variant indices.
//
// FIXME: This requires the optimized MIR in the case of generators.
Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_mir/src/borrow_check/mod.rs
Expand Up @@ -9,6 +9,7 @@ use rustc_hir::{HirId, Node};
use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
use rustc_middle::mir::{
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
PlaceRef,
Expand Down Expand Up @@ -75,6 +76,7 @@ crate use region_infer::RegionInferenceContext;
crate struct Upvar {
name: Symbol,

// FIXME(project-rfc-2229#8): This should use Place or something similar
var_hir_id: HirId,

/// If true, the capture is behind a reference.
Expand Down Expand Up @@ -155,13 +157,13 @@ fn do_mir_borrowck<'a, 'tcx>(
infcx.set_tainted_by_errors();
}
let upvars: Vec<_> = tables
.closure_captures
.get(&def.did.to_def_id())
.into_iter()
.flat_map(|v| v.values())
.map(|upvar_id| {
let var_hir_id = upvar_id.var_path.hir_id;
let capture = tables.upvar_capture(*upvar_id);
.closure_min_captures_flattened(def.did.to_def_id())
.map(|captured_place| {
let var_hir_id = match captured_place.place.base {
HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
_ => bug!("Expected upvar"),
};
let capture = captured_place.info.capture_kind;
let by_ref = match capture {
ty::UpvarCapture::ByValue(_) => false,
ty::UpvarCapture::ByRef(..) => true,
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_mir/src/borrow_check/type_check/mod.rs
Expand Up @@ -749,7 +749,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
(&adt_def.variants[VariantIdx::new(0)], substs)
}
ty::Closure(_, substs) => {
return match substs.as_closure().upvar_tys().nth(field.index()) {
return match substs
.as_closure()
.tupled_upvars_ty()
.tuple_element_ty(field.index())
{
Some(ty) => Ok(ty),
None => Err(FieldAccessError::OutOfRange {
field_count: substs.as_closure().upvar_tys().count(),
Expand Down

0 comments on commit 5bd9b60

Please sign in to comment.