Skip to content

Commit eca8b74

Browse files
arora-amanChrisPardylogmosier
committed
Initial work for doing minimum capture analysis for RFC-2229
Co-authored-by: Chris Pardy <[email protected]> Co-authored-by: Logan Mosier <[email protected]>
1 parent 3ef79c4 commit eca8b74

File tree

5 files changed

+374
-115
lines changed

5 files changed

+374
-115
lines changed

compiler/rustc_middle/src/ty/context.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,10 @@ pub struct TypeckResults<'tcx> {
415415
/// entire variable.
416416
pub closure_captures: ty::UpvarListMap,
417417

418-
/// Given the closure ID this map provides the list of
419-
/// `Place`s and how/why are they captured by the closure.
420-
pub closure_capture_information: ty::CaptureInformationMap<'tcx>,
418+
/// Given the closure DefId this map provides a map of
419+
/// root variables to minimum set of `Place`s (and how) that need to be tracked
420+
/// to support all captures of that closure.
421+
pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
421422

422423
/// Stores the type, expression, span and optional scope span of all types
423424
/// that are live across the yield of this generator (if a generator).
@@ -446,7 +447,7 @@ impl<'tcx> TypeckResults<'tcx> {
446447
tainted_by_errors: None,
447448
concrete_opaque_types: Default::default(),
448449
closure_captures: Default::default(),
449-
closure_capture_information: Default::default(),
450+
closure_min_captures: Default::default(),
450451
generator_interior_types: Default::default(),
451452
}
452453
}
@@ -681,7 +682,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
681682
tainted_by_errors,
682683
ref concrete_opaque_types,
683684
ref closure_captures,
684-
ref closure_capture_information,
685+
ref closure_min_captures,
685686
ref generator_interior_types,
686687
} = *self;
687688

@@ -715,7 +716,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
715716
tainted_by_errors.hash_stable(hcx, hasher);
716717
concrete_opaque_types.hash_stable(hcx, hasher);
717718
closure_captures.hash_stable(hcx, hasher);
718-
closure_capture_information.hash_stable(hcx, hasher);
719+
closure_min_captures.hash_stable(hcx, hasher);
719720
generator_interior_types.hash_stable(hcx, hasher);
720721
})
721722
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -788,30 +788,18 @@ pub struct CaptureInfo<'tcx> {
788788
pub capture_kind: UpvarCapture<'tcx>,
789789
}
790790

791+
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
792+
pub struct CapturedPlace<'tcx> {
793+
pub place: HirPlace<'tcx>,
794+
pub info: CaptureInfo<'tcx>,
795+
}
796+
791797
pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
792798
pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
793799

794-
/// Consider closure where s.str1 is captured via an ImmutableBorrow and s.str2 via a MutableBorrow
795-
///
796-
/// ```rust
797-
/// // Assume that thte HirId for the variable definition is `V1`
798-
/// let mut s = SomeStruct { str1: format!("s1"), str2: format!("s2") }
799-
///
800-
/// let fix_s = |new_s2| {
801-
/// // Assume that the HirId for the expression `s.str1` is `E1`
802-
/// println!("Updating SomeStruct with str1=", s.str1);
803-
/// // Assume that the HirId for the expression `*s.str2` is `E2`
804-
/// s.str2 = new_s2;
805-
/// }
806-
/// ```
807-
///
808-
/// For closure `fix_s`, (at a high level) the IndexMap will contain:
809-
///
810-
/// Place { V1, [ProjectionKind::Field(Index=0, Variant=0)] } : CaptureKind { E1, ImmutableBorrow }
811-
/// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
812-
///
813-
pub type CaptureInformationMap<'tcx> =
814-
FxHashMap<DefId, FxIndexMap<HirPlace<'tcx>, CaptureInfo<'tcx>>>;
800+
pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
801+
pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureList<'tcx>>;
802+
pub type MinCaptureInformationMap<'tcx> = FxHashMap<DefId, RootVariableMinCaptureList<'tcx>>;
815803

816804
#[derive(Clone, Copy, PartialEq, Eq)]
817805
pub enum IntVarValue {

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -383,16 +383,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
383383
self.describe_field_from_ty(&ty, field, variant_index)
384384
}
385385
ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => {
386-
// `tcx.upvars_mentioned(def_id)` returns an `Option`, which is `None` in case
387-
// the closure comes from another crate. But in that case we wouldn't
388-
// be borrowck'ing it, so we can just unwrap:
389-
let (&var_id, _) = self
390-
.infcx
391-
.tcx
392-
.upvars_mentioned(def_id)
393-
.unwrap()
394-
.get_index(field.index())
395-
.unwrap();
386+
// We won't be borrowck'ing here if the closure came from another crate,
387+
// so it's safe to call `expect_local`.
388+
//
389+
// We know the field exists so it's safe to call operator[] and `unwrap` here.
390+
let (&var_id, _) =
391+
self.infcx.tcx.typeck(def_id.expect_local()).closure_captures[&def_id]
392+
.get_index(field.index())
393+
.unwrap();
396394

397395
self.infcx.tcx.hir().name(var_id).to_string()
398396
}
@@ -967,9 +965,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
967965
let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind;
968966
debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
969967
if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr {
970-
for ((upvar_hir_id, upvar), place) in
971-
self.infcx.tcx.upvars_mentioned(def_id)?.iter().zip(places)
968+
for (upvar_hir_id, place) in
969+
self.infcx.tcx.typeck(def_id.expect_local()).closure_captures[&def_id]
970+
.keys()
971+
.zip(places)
972972
{
973+
let span = self.infcx.tcx.upvars_mentioned(local_did)?[upvar_hir_id].span;
973974
match place {
974975
Operand::Copy(place) | Operand::Move(place)
975976
if target_place == place.as_ref() =>
@@ -991,7 +992,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
991992
let usage_span =
992993
match self.infcx.tcx.typeck(local_did).upvar_capture(upvar_id) {
993994
ty::UpvarCapture::ByValue(Some(span)) => span,
994-
_ => upvar.span,
995+
_ => span,
995996
};
996997
return Some((*args_span, generator_kind, usage_span));
997998
}

0 commit comments

Comments
 (0)