Skip to content
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

Rollup of 9 pull requests #81559

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
12014d2
Add Box::downcast() for dyn Any + Send + Sync
sdroege Jan 12, 2021
8db2782
refactor: moved new out of ZipImpl
DeveloperC286 Dec 16, 2020
bfb0e4a
refactor: moved next_back out of ZipImpl
DeveloperC286 Dec 16, 2020
0597339
refactor: removed ZipImpl
DeveloperC286 Dec 16, 2020
f2bb202
refactor: updated zip nth() to iterator nth()
DeveloperC286 Dec 16, 2020
a398994
Account for existing `_` field pattern when suggesting `..`
estebank Jan 27, 2021
3f679fe
Fix rustc sysroot in systems using CAS
rcvalle Nov 21, 2020
5d73918
Clone entire `TokenCursor` when collecting tokens
Aaron1011 Jan 28, 2021
ada714d
Optimize udiv_1e19() function
Kogia-sima Jan 28, 2021
152f500
refactor: removing redundant variables
DeveloperC286 Jan 28, 2021
b421cd5
Restrict precision of captures with `capture_disjoint_fields` set
arora-aman Dec 4, 2020
3488082
Compute mutability of closure captures
arora-aman Dec 2, 2020
1373f98
Test cases for handling mutable references
arora-aman Dec 13, 2020
0897db5
Test for restricting capture precision
arora-aman Dec 14, 2020
604cbdc
Fix unused 'mut' warning for capture's root variable
arora-aman Dec 16, 2020
c748f32
Fix incorrect use mut diagnostics
arora-aman Dec 13, 2020
ffd5327
Add fixme for precise path diagnostics
arora-aman Jan 12, 2021
fadf03e
Fix typos
arora-aman Jan 29, 2021
0f4bab2
Fixme for closure origin when reborrow is implemented
arora-aman Jan 29, 2021
56c2736
Replace predecessor with range in collections documentation
KamilaBorowska Jan 30, 2021
7e32178
Balance sidebar `Deref` cycle check with main content
jryans Jan 28, 2021
2ad8c2f
Rollup merge of #79173 - DeveloperC286:zip_nth_cleanup, r=kennytm
jonas-schievink Jan 30, 2021
950c10c
Rollup merge of #79253 - rcvalle:fix-rustc-sysroot-cas, r=nagisa
jonas-schievink Jan 30, 2021
93dbd0f
Rollup merge of #80092 - sexxi-goose:restrict_precision, r=nikomatsakis
jonas-schievink Jan 30, 2021
7a718eb
Rollup merge of #80945 - sdroege:downcast-send-sync, r=m-ou-se
jonas-schievink Jan 30, 2021
3a61c21
Rollup merge of #81422 - estebank:dotdot_sugg, r=davidtwco
jonas-schievink Jan 30, 2021
022eada
Rollup merge of #81472 - Aaron1011:fix/revert-cursor-clone, r=petroch…
jonas-schievink Jan 30, 2021
6f67e2f
Rollup merge of #81484 - Kogia-sima:perf/optimize-udiv_1e19, r=nagisa
jonas-schievink Jan 30, 2021
23643ad
Rollup merge of #81491 - jryans:rustdoc-deref-ice-81395, r=GuillaumeG…
jonas-schievink Jan 30, 2021
de95341
Rollup merge of #81550 - xfix:replace-mention-of-predecessor, r=jonas…
jonas-schievink Jan 30, 2021
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
Prev Previous commit
Next Next commit
Compute mutability of closure captures
When `capture_disjoint_fields` is not enabled, checking if the root variable
binding is mutable would suffice.

However with the feature enabled, the captured place might be mutable
because it dereferences a mutable reference.

This PR computes the mutability of each capture after capture analysis
in rustc_typeck. We store this in `ty::CapturedPlace` and then use
`ty::CapturedPlace::mutability` in mir_build and borrow_check.
  • Loading branch information
arora-aman committed Jan 29, 2021
commit 34880825828260fad0a74621e4a13fe7da9a4a9d
8 changes: 7 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,11 +661,17 @@ pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<hir::HirId, MinCaptureLis
/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.
pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;

/// A `Place` and the corresponding `CaptureInfo`.
/// A composite describing a `Place` that is captured by a closure.
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
pub struct CapturedPlace<'tcx> {
/// The `Place` that is captured.
pub place: HirPlace<'tcx>,

/// `CaptureKind` and expression(s) that resulted in such capture of `place`.
pub info: CaptureInfo<'tcx>,

/// Represents if `place` can be mutated or not.
pub mutability: hir::Mutability,
}

pub fn place_to_string_for_capture(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
Expand Down
9 changes: 2 additions & 7 deletions compiler/rustc_mir/src/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,12 @@ fn do_mir_borrowck<'a, 'tcx>(
ty::UpvarCapture::ByValue(_) => false,
ty::UpvarCapture::ByRef(..) => true,
};
let mut upvar = Upvar {
Upvar {
name: tcx.hir().name(var_hir_id),
var_hir_id,
by_ref,
mutability: Mutability::Not,
};
let bm = *tables.pat_binding_modes().get(var_hir_id).expect("missing binding mode");
if bm == ty::BindByValue(hir::Mutability::Mut) {
upvar.mutability = Mutability::Mut;
mutability: captured_place.mutability,
}
upvar
})
.collect();

Expand Down
11 changes: 1 addition & 10 deletions compiler/rustc_mir_build/src/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,22 +851,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
_ => bug!("Expected an upvar")
};

let mut mutability = Mutability::Not;
let mutability = captured_place.mutability;

// FIXME(project-rfc-2229#8): Store more precise information
let mut name = kw::Empty;
if let Some(Node::Binding(pat)) = tcx_hir.find(var_id) {
if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
name = ident.name;
match hir_typeck_results
.extract_binding_mode(tcx.sess, pat.hir_id, pat.span)
{
Some(ty::BindByValue(hir::Mutability::Mut)) => {
mutability = Mutability::Mut;
}
Some(_) => mutability = Mutability::Not,
_ => {}
}
}
}

Expand Down
54 changes: 50 additions & 4 deletions compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let capture = captured_place.info.capture_kind;

debug!(
"place={:?} upvar_ty={:?} capture={:?}",
captured_place.place, upvar_ty, capture
"final_upvar_tys: place={:?} upvar_ty={:?} capture={:?}, mutability={:?}",
captured_place.place, upvar_ty, capture, captured_place.mutability,
);

match capture {
Expand Down Expand Up @@ -423,7 +423,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) {
None => {
let min_cap_list = vec![ty::CapturedPlace { place, info: capture_info }];
let mutability = self.determine_capture_mutability(&place);
let min_cap_list =
vec![ty::CapturedPlace { place, info: capture_info, mutability }];
root_var_min_capture_list.insert(var_hir_id, min_cap_list);
continue;
}
Expand Down Expand Up @@ -486,8 +488,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// Only need to insert when we don't have an ancestor in the existing min capture list
if !ancestor_found {
let mutability = self.determine_capture_mutability(&place);
let captured_place =
ty::CapturedPlace { place: place.clone(), info: updated_capture_info };
ty::CapturedPlace { place, info: updated_capture_info, mutability };
min_cap_list.push(captured_place);
}
}
Expand Down Expand Up @@ -607,6 +610,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}

/// A captured place is mutable if
/// 1. Projections don't include a Deref of an immut-borrow, **and**
/// 2. PlaceBase is mut or projections include a Deref of a mut-borrow.
fn determine_capture_mutability(&self, place: &Place<'tcx>) -> hir::Mutability {
let var_hir_id = match place.base {
PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
_ => unreachable!(),
};

let bm = *self
.typeck_results
.borrow()
.pat_binding_modes()
.get(var_hir_id)
.expect("missing binding mode");

let mut is_mutbl = match bm {
ty::BindByValue(mutability) => mutability,
ty::BindByReference(_) => hir::Mutability::Not,
};

for pointer_ty in place.deref_tys() {
match pointer_ty.kind() {
// We don't capture derefs of raw ptrs
ty::RawPtr(_) => unreachable!(),

// Derefencing a mut-ref allows us to mut the Place if we don't deref
// an immut-ref after on top of this.
ty::Ref(.., hir::Mutability::Mut) => is_mutbl = hir::Mutability::Mut,

// The place isn't mutable once we dereference a immutable reference.
ty::Ref(.., hir::Mutability::Not) => return hir::Mutability::Not,

// Dereferencing a box doesn't change mutability
ty::Adt(def, ..) if def.is_box() => {}

unexpected_ty => bug!("deref of unexpected pointer type {:?}", unexpected_ty),
}
}

is_mutbl
}
}

struct InferBorrowKind<'a, 'tcx> {
Expand Down