Skip to content

Commit 5bd9b60

Browse files
committed
Auto merge of #79553 - sexxi-goose:mir_min_cap_writeback, r=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`
2 parents 9eb3a7c + 01df563 commit 5bd9b60

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1483
-233
lines changed

compiler/rustc_middle/src/hir/place.rs

+38-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@ use crate::ty::Ty;
44
use rustc_hir::HirId;
55
use rustc_target::abi::VariantIdx;
66

7-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
7+
#[derive(
8+
Clone,
9+
Copy,
10+
Debug,
11+
PartialEq,
12+
Eq,
13+
Hash,
14+
TyEncodable,
15+
TyDecodable,
16+
TypeFoldable,
17+
HashStable
18+
)]
819
pub enum PlaceBase {
920
/// A temporary variable
1021
Rvalue,
@@ -16,7 +27,18 @@ pub enum PlaceBase {
1627
Upvar(ty::UpvarId),
1728
}
1829

19-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
30+
#[derive(
31+
Clone,
32+
Copy,
33+
Debug,
34+
PartialEq,
35+
Eq,
36+
Hash,
37+
TyEncodable,
38+
TyDecodable,
39+
TypeFoldable,
40+
HashStable
41+
)]
2042
pub enum ProjectionKind {
2143
/// A dereference of a pointer, reference or `Box<T>` of the given type
2244
Deref,
@@ -36,7 +58,18 @@ pub enum ProjectionKind {
3658
Subslice,
3759
}
3860

39-
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
61+
#[derive(
62+
Clone,
63+
Copy,
64+
Debug,
65+
PartialEq,
66+
Eq,
67+
Hash,
68+
TyEncodable,
69+
TyDecodable,
70+
TypeFoldable,
71+
HashStable
72+
)]
4073
pub struct Projection<'tcx> {
4174
/// Type after the projection is being applied.
4275
pub ty: Ty<'tcx>,
@@ -48,7 +81,7 @@ pub struct Projection<'tcx> {
4881
/// A `Place` represents how a value is located in memory.
4982
///
5083
/// This is an HIR version of `mir::Place`
51-
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
84+
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
5285
pub struct Place<'tcx> {
5386
/// The type of the `PlaceBase`
5487
pub base_ty: Ty<'tcx>,
@@ -61,7 +94,7 @@ pub struct Place<'tcx> {
6194
/// A `PlaceWithHirId` represents how a value is located in memory.
6295
///
6396
/// This is an HIR version of `mir::Place`
64-
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
97+
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
6598
pub struct PlaceWithHirId<'tcx> {
6699
/// `HirId` of the expression or pattern producing this value.
67100
pub hir_id: HirId,

compiler/rustc_middle/src/ty/context.rs

+13
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,19 @@ impl<'tcx> TypeckResults<'tcx> {
624624
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
625625
}
626626

627+
/// For a given closure, returns the iterator of `ty::CapturedPlace`s that are captured
628+
/// by the closure.
629+
pub fn closure_min_captures_flattened(
630+
&self,
631+
closure_def_id: DefId,
632+
) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
633+
self.closure_min_captures
634+
.get(&closure_def_id)
635+
.map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
636+
.into_iter()
637+
.flatten()
638+
}
639+
627640
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> {
628641
self.upvar_capture_map[&upvar_id]
629642
}

compiler/rustc_middle/src/ty/mod.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -672,15 +672,26 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TyS<'tcx> {
672672
#[rustc_diagnostic_item = "Ty"]
673673
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
674674

675-
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
675+
#[derive(
676+
Clone,
677+
Copy,
678+
Debug,
679+
PartialEq,
680+
Eq,
681+
Hash,
682+
TyEncodable,
683+
TyDecodable,
684+
TypeFoldable,
685+
HashStable
686+
)]
676687
pub struct UpvarPath {
677688
pub hir_id: hir::HirId,
678689
}
679690

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

695-
#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)]
706+
#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)]
696707
pub enum BorrowKind {
697708
/// Data must be immutable and is aliasable.
698709
ImmBorrow,
@@ -746,7 +757,7 @@ pub enum BorrowKind {
746757

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

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

792803
/// A `Place` and the corresponding `CaptureInfo`.
793-
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
804+
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
794805
pub struct CapturedPlace<'tcx> {
795806
pub place: HirPlace<'tcx>,
796807
pub info: CaptureInfo<'tcx>,
@@ -799,7 +810,7 @@ pub struct CapturedPlace<'tcx> {
799810
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
800811
/// for a particular capture as well as identifying the part of the source code
801812
/// that triggered this capture to occur.
802-
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
813+
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
803814
pub struct CaptureInfo<'tcx> {
804815
/// Expr Id pointing to use that resulted in selecting the current capture kind
805816
///

compiler/rustc_middle/src/ty/sty.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,15 @@ impl<'tcx> TyS<'tcx> {
21742174
}
21752175
}
21762176

2177+
/// Get the `i`-th element of a tuple.
2178+
/// Panics when called on anything but a tuple.
2179+
pub fn tuple_element_ty(&self, i: usize) -> Option<Ty<'tcx>> {
2180+
match self.kind() {
2181+
Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()),
2182+
_ => bug!("tuple_fields called on non-tuple"),
2183+
}
2184+
}
2185+
21772186
/// If the type contains variants, returns the valid range of variant indices.
21782187
//
21792188
// FIXME: This requires the optimized MIR in the case of generators.

compiler/rustc_mir/src/borrow_check/mod.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_hir::{HirId, Node};
99
use rustc_index::bit_set::BitSet;
1010
use rustc_index::vec::IndexVec;
1111
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
12+
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
1213
use rustc_middle::mir::{
1314
traversal, Body, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem,
1415
PlaceRef,
@@ -75,6 +76,7 @@ crate use region_infer::RegionInferenceContext;
7576
crate struct Upvar {
7677
name: Symbol,
7778

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

8082
/// If true, the capture is behind a reference.
@@ -155,13 +157,13 @@ fn do_mir_borrowck<'a, 'tcx>(
155157
infcx.set_tainted_by_errors();
156158
}
157159
let upvars: Vec<_> = tables
158-
.closure_captures
159-
.get(&def.did.to_def_id())
160-
.into_iter()
161-
.flat_map(|v| v.values())
162-
.map(|upvar_id| {
163-
let var_hir_id = upvar_id.var_path.hir_id;
164-
let capture = tables.upvar_capture(*upvar_id);
160+
.closure_min_captures_flattened(def.did.to_def_id())
161+
.map(|captured_place| {
162+
let var_hir_id = match captured_place.place.base {
163+
HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
164+
_ => bug!("Expected upvar"),
165+
};
166+
let capture = captured_place.info.capture_kind;
165167
let by_ref = match capture {
166168
ty::UpvarCapture::ByValue(_) => false,
167169
ty::UpvarCapture::ByRef(..) => true,

compiler/rustc_mir/src/borrow_check/type_check/mod.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
749749
(&adt_def.variants[VariantIdx::new(0)], substs)
750750
}
751751
ty::Closure(_, substs) => {
752-
return match substs.as_closure().upvar_tys().nth(field.index()) {
752+
return match substs
753+
.as_closure()
754+
.tupled_upvars_ty()
755+
.tuple_element_ty(field.index())
756+
{
753757
Some(ty) => Ok(ty),
754758
None => Err(FieldAccessError::OutOfRange {
755759
field_count: substs.as_closure().upvar_tys().count(),

0 commit comments

Comments
 (0)