Skip to content

Commit f265997

Browse files
committed
Edition 2021 enables disjoint capture
1 parent 4573a4a commit f265997

File tree

2 files changed

+35
-2
lines changed
  • compiler/rustc_typeck/src/check
  • src/test/ui/closures/2229_closure_analysis/run_pass

2 files changed

+35
-2
lines changed

compiler/rustc_typeck/src/check/upvar.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
177177

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

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

213213
// If we have an origin, store it.
214214
if let Some(origin) = delegate.current_origin.clone() {
215-
let origin = if self.tcx.features().capture_disjoint_fields {
215+
let origin = if enable_precise_capture(self.tcx, span) {
216216
(origin.0, restrict_capture_precision(origin.1))
217217
} else {
218218
(origin.0, Place { projections: vec![], ..origin.1 })
@@ -1924,3 +1924,13 @@ fn determine_place_ancestry_relation(
19241924
PlaceAncestryRelation::Divergent
19251925
}
19261926
}
1927+
1928+
/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
1929+
/// user is using Rust Edition 2021 or higher.
1930+
///
1931+
/// `span` is the span of the closure.
1932+
fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool {
1933+
// We use span here to ensure that if the closure was generated by a macro with a different
1934+
// edition.
1935+
tcx.features().capture_disjoint_fields || span.rust_2021()
1936+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// edition:2021
2+
// run-pass
3+
4+
// Test that edition 2021 enables disjoint capture by default.
5+
6+
struct Point {
7+
x: i32,
8+
y: i32,
9+
}
10+
11+
fn main() {
12+
let mut p = Point { x: 10, y: 10 };
13+
14+
let c = || {
15+
println!("{}", p.x);
16+
};
17+
18+
// `c` should only capture `p.x`, therefore mutating `p.y` is allowed.
19+
let py = &mut p.y;
20+
21+
c();
22+
*py = 20;
23+
}

0 commit comments

Comments
 (0)