Skip to content

Commit

Permalink
Edition 2021 enables disjoint capture
Browse files Browse the repository at this point in the history
  • Loading branch information
arora-aman committed Jun 22, 2021
1 parent 4573a4a commit f265997
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
14 changes: 12 additions & 2 deletions compiler/rustc_typeck/src/check/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// We now fake capture information for all variables that are mentioned within the closure
// We do this after handling migrations so that min_captures computes before
if !self.tcx.features().capture_disjoint_fields {
if !enable_precise_capture(self.tcx, span) {
let mut capture_information: InferredCaptureInformation<'tcx> = Default::default();

if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
Expand Down Expand Up @@ -212,7 +212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// If we have an origin, store it.
if let Some(origin) = delegate.current_origin.clone() {
let origin = if self.tcx.features().capture_disjoint_fields {
let origin = if enable_precise_capture(self.tcx, span) {
(origin.0, restrict_capture_precision(origin.1))
} else {
(origin.0, Place { projections: vec![], ..origin.1 })
Expand Down Expand Up @@ -1924,3 +1924,13 @@ fn determine_place_ancestry_relation(
PlaceAncestryRelation::Divergent
}
}

/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
/// user is using Rust Edition 2021 or higher.
///
/// `span` is the span of the closure.
fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool {
// We use span here to ensure that if the closure was generated by a macro with a different
// edition.
tcx.features().capture_disjoint_fields || span.rust_2021()
}
23 changes: 23 additions & 0 deletions src/test/ui/closures/2229_closure_analysis/run_pass/edition.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// edition:2021
// run-pass

// Test that edition 2021 enables disjoint capture by default.

struct Point {
x: i32,
y: i32,
}

fn main() {
let mut p = Point { x: 10, y: 10 };

let c = || {
println!("{}", p.x);
};

// `c` should only capture `p.x`, therefore mutating `p.y` is allowed.
let py = &mut p.y;

c();
*py = 20;
}

0 comments on commit f265997

Please sign in to comment.