about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAman Arora <me@aman-arora.com>2020-10-12 20:16:02 -0400
committerAman Arora <me@aman-arora.com>2020-11-10 20:58:52 -0500
commit58e8f8fd2cac4cfcde6c7a1488dd8657dcacaad8 (patch)
treea4471c80198f459122252b174be087b0659cb133
parent88310cc0ebf4144205743dbb3a65223deffcf8e6 (diff)
downloadrust-58e8f8fd2cac4cfcde6c7a1488dd8657dcacaad8.tar.gz
rust-58e8f8fd2cac4cfcde6c7a1488dd8657dcacaad8.zip
Add initial set of testcases for RFC 2229
Co-authored-by: Dhruv Jauhar <dhruvjhr@gmail.com>
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs7
-rw-r--r--src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs17
-rw-r--r--src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stdout20
-rw-r--r--src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs26
-rw-r--r--src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stdout28
-rw-r--r--src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stdout28
-rw-r--r--src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs3
-rw-r--r--src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout19
-rw-r--r--src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs40
-rw-r--r--src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr28
-rw-r--r--src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stdout32
-rw-r--r--src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs34
-rw-r--r--src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stdout28
-rw-r--r--src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs30
-rw-r--r--src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stdout35
-rw-r--r--src/test/ui/closures/2229_closure_analysis/nested-closure.rs40
-rw-r--r--src/test/ui/closures/2229_closure_analysis/nested-closure.stderr30
-rw-r--r--src/test/ui/closures/2229_closure_analysis/nested-closure.stdout98
-rw-r--r--src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs28
-rw-r--r--src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/path-with-array-access.stdout28
-rw-r--r--src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs33
-rw-r--r--src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stdout45
-rw-r--r--src/test/ui/closures/2229_closure_analysis/slice-pat.rs28
-rw-r--r--src/test/ui/closures/2229_closure_analysis/slice-pat.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/slice-pat.stdout20
34 files changed, 914 insertions, 2 deletions
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index a28744c2ece..9e4e6565361 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -169,6 +169,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         )
         .consume_body(body);
 
+        log_capture_analysis!(
+            self,
+            closure_def_id,
+            "capture information: {:#?}",
+            delegate.capture_information
+        );
+
         if let Some(closure_substs) = infer_kind {
             // Unify the (as yet unbound) type variable in the closure
             // substs with the kind we inferred.
diff --git a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs
new file mode 100644
index 00000000000..a5dd202bc07
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.rs
@@ -0,0 +1,17 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+// Ensure that capture analysis results in arrays being completely captured.
+fn main() {
+    let mut m = [1, 2, 3, 4, 5];
+
+    let mut c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    || {
+        m[0] += 10;
+        m[1] += 40;
+    };
+
+    c();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
new file mode 100644
index 00000000000..3d3912d0796
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/arrays-completely-captured.rs:9:17
+   |
+LL |     let mut c = #[rustc_capture_analysis]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/arrays-completely-captured.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stdout b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stdout
new file mode 100644
index 00000000000..b4142a4fd8e
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/arrays-completely-captured.stdout
@@ -0,0 +1,20 @@
+For closure=DefId(0:4 ~ arrays_completely_captured[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:4 ~ arrays_completely_captured[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: [i32; 5],
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:3 ~ arrays_completely_captured[317d]::main), local_id: 1 };`m`;DefId(0:4 ~ arrays_completely_captured[317d]::main::{closure#0})),
+        ),
+        projections: [],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:3 ~ arrays_completely_captured[317d]::main),
+                local_id: 12,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(MutBorrow, '_#6r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs
new file mode 100644
index 00000000000..a2be21cddb4
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs
@@ -0,0 +1,26 @@
+// FIXME(arora-aman) add run-pass once 2229 is implemented
+
+#![feature(capture_disjoint_fields)]
+//~^ WARNING the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+fn main() {
+    let mut p = Point { x: 10, y: 10 };
+
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    || {
+        println!("{}", p.x);
+    };
+
+    // `c` should only capture `p.x`, therefore mutating `p.y` is allowed.
+    let py = &mut p.y;
+
+    c();
+    *py = 20;
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
new file mode 100644
index 00000000000..9233597c360
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/capture-disjoint-field-struct.rs:15:13
+   |
+LL |     let c = #[rustc_capture_analysis]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/capture-disjoint-field-struct.rs:3:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stdout b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stdout
new file mode 100644
index 00000000000..ab7bd60e48d
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stdout
@@ -0,0 +1,28 @@
+For closure=DefId(0:7 ~ capture_disjoint_field_struct[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:7 ~ capture_disjoint_field_struct[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: Point,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:6 ~ capture_disjoint_field_struct[317d]::main), local_id: 1 };`p`;DefId(0:7 ~ capture_disjoint_field_struct[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: i32,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:6 ~ capture_disjoint_field_struct[317d]::main),
+                local_id: 31,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#35r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs
new file mode 100644
index 00000000000..e06cde73158
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs
@@ -0,0 +1,21 @@
+// FIXME(arora-aman) add run-pass once 2229 is implemented
+
+#![feature(capture_disjoint_fields)]
+//~^ WARNING the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+fn main() {
+    let mut t = (10, 10);
+
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    || {
+        println!("{}", t.0);
+    };
+
+    // `c` only captures t.0, therefore mutating t.1 is allowed.
+    let t1 = &mut t.1;
+
+    c();
+    *t1 = 20;
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
new file mode 100644
index 00000000000..f83487ecce5
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/capture-disjoint-field-tuple.rs:8:13
+   |
+LL |     let c = #[rustc_capture_analysis]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/capture-disjoint-field-tuple.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stdout b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stdout
new file mode 100644
index 00000000000..517d7564c72
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stdout
@@ -0,0 +1,28 @@
+For closure=DefId(0:4 ~ capture_disjoint_field_tuple[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:4 ~ capture_disjoint_field_tuple[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: (i32, i32),
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:3 ~ capture_disjoint_field_tuple[317d]::main), local_id: 1 };`t`;DefId(0:4 ~ capture_disjoint_field_tuple[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: i32,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:3 ~ capture_disjoint_field_tuple[317d]::main),
+                local_id: 28,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#35r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
index 5eab718736c..072ed8eeab6 100644
--- a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
+++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
@@ -5,8 +5,9 @@
 fn main() {
     let s = format!("s");
 
-    let c = #[rustc_capture_analysis] || {
+    let c = #[rustc_capture_analysis]
     //~^ ERROR: attributes on expressions are experimental
+    || {
         println!("This uses new capture analyysis to capture s={}", s);
     };
 }
diff --git a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
index 4dc1f9a6ab2..133de1d13e8 100644
--- a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
@@ -1,7 +1,7 @@
 error[E0658]: attributes on expressions are experimental
   --> $DIR/feature-gate-capture_disjoint_fields.rs:8:13
    |
-LL |     let c = #[rustc_capture_analysis] || {
+LL |     let c = #[rustc_capture_analysis]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
diff --git a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout
index c1fca9afd39..40ac31b4ad9 100644
--- a/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout
+++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout
@@ -1 +1,20 @@
 For closure=DefId(0:4 ~ feature_gate_capture_disjoint_fields[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:4 ~ feature_gate_capture_disjoint_fields[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: std::string::String,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:3 ~ feature_gate_capture_disjoint_fields[317d]::main), local_id: 1 };`s`;DefId(0:4 ~ feature_gate_capture_disjoint_fields[317d]::main::{closure#0})),
+        ),
+        projections: [],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:3 ~ feature_gate_capture_disjoint_fields[317d]::main),
+                local_id: 52,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#50r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs
new file mode 100644
index 00000000000..aa251c4526c
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.rs
@@ -0,0 +1,40 @@
+// FIXME(arora-aman) add run-pass once 2229 is implemented
+
+#![feature(capture_disjoint_fields)]
+//~^ warning the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+struct Filter {
+    div: i32,
+}
+impl Filter {
+    fn allowed(&self, x: i32) -> bool {
+        x % self.div == 1
+    }
+}
+
+struct Data {
+    filter: Filter,
+    list: Vec<i32>,
+}
+impl Data {
+    fn update(&mut self) {
+        // The closure passed to filter only captures self.filter,
+        // therefore mutating self.list is allowed.
+        self.list.retain(
+        //~^ cannot borrow `self.list` as mutable because it is also borrowed as immutable
+            #[rustc_capture_analysis]
+            |v| self.filter.allowed(*v),
+        );
+    }
+}
+
+fn main() {
+    let mut d = Data { filter: Filter { div: 3 }, list: Vec::new() };
+
+    for i in 1..10 {
+        d.list.push(i);
+    }
+
+    d.update();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr
new file mode 100644
index 00000000000..3eb4decdeae
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr
@@ -0,0 +1,28 @@
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/filter-on-struct-member.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error[E0502]: cannot borrow `self.list` as mutable because it is also borrowed as immutable
+  --> $DIR/filter-on-struct-member.rs:22:9
+   |
+LL |           self.list.retain(
+   |           ^         ------ immutable borrow later used by call
+   |  _________|
+   | |
+LL | |
+LL | |             #[rustc_capture_analysis]
+LL | |             |v| self.filter.allowed(*v),
+   | |             --- ---- first borrow occurs due to use of `self` in closure
+   | |             |
+   | |             immutable borrow occurs here
+LL | |         );
+   | |_________^ mutable borrow occurs here
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stdout b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stdout
new file mode 100644
index 00000000000..560b2aa3b57
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/filter-on-struct-member.stdout
@@ -0,0 +1,32 @@
+For closure=DefId(0:12 ~ filter_on_struct_member[317d]::{impl#1}::update::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:12 ~ filter_on_struct_member[317d]::{impl#1}::update::{closure#0}): capture information: {
+    Place {
+        base_ty: &mut Data,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:11 ~ filter_on_struct_member[317d]::{impl#1}::update), local_id: 1 };`self`;DefId(0:12 ~ filter_on_struct_member[317d]::{impl#1}::update::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: Data,
+                kind: Deref,
+            },
+            Projection {
+                ty: Filter,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:11 ~ filter_on_struct_member[317d]::{impl#1}::update),
+                local_id: 13,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#7r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs
new file mode 100644
index 00000000000..bd8d52d6a3c
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.rs
@@ -0,0 +1,34 @@
+#![feature(capture_disjoint_fields)]
+//~^ warning the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+#![allow(unused)]
+
+struct Point {
+    x: i32,
+    y: i32,
+}
+struct Wrapper {
+    p: Point,
+}
+
+fn main() {
+    let mut w = Wrapper { p: Point { x: 10, y: 10 } };
+
+    // Only paths that appears within the closure that directly start off
+    // a variable defined outside the closure are captured.
+    //
+    // Therefore `w.p` is captured
+    // Note that `wp.x` doesn't start off a variable defined outside the closure.
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    || {
+        let wp = &w.p;
+        println!("{}", wp.x);
+    };
+
+    // Since `c` captures `w.p` by an ImmBorrow, `w.p.y` can't be mutated.
+    let py = &mut w.p.y;
+    c();
+
+    *py = 20
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr
new file mode 100644
index 00000000000..bd339a68fa0
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/multilevel-path-1.rs:22:13
+   |
+LL |     let c = #[rustc_capture_analysis]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/multilevel-path-1.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stdout b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stdout
new file mode 100644
index 00000000000..525366cb964
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-1.stdout
@@ -0,0 +1,28 @@
+For closure=DefId(0:9 ~ multilevel_path_1[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:9 ~ multilevel_path_1[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: Wrapper,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:8 ~ multilevel_path_1[317d]::main), local_id: 1 };`w`;DefId(0:9 ~ multilevel_path_1[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: Point,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:8 ~ multilevel_path_1[317d]::main),
+                local_id: 20,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#37r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs
new file mode 100644
index 00000000000..a8aca53bc73
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.rs
@@ -0,0 +1,30 @@
+// FIXME(arora-aman) add run-pass once 2229 is implemented
+
+#![feature(capture_disjoint_fields)]
+//~^ warning the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+#![allow(unused)]
+
+struct Point {
+    x: i32,
+    y: i32,
+}
+struct Wrapper {
+    p: Point,
+}
+
+fn main() {
+    let mut w = Wrapper { p: Point { x: 10, y: 10 } };
+
+    let c = #[rustc_capture_analysis]
+        //~^ ERROR: attributes on expressions are experimental
+    || {
+        println!("{}", w.p.x);
+    };
+
+    // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`.
+    let py = &mut w.p.y;
+    c();
+
+    *py = 20
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
new file mode 100644
index 00000000000..772dfd643ea
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/multilevel-path-2.rs:19:13
+   |
+LL |     let c = #[rustc_capture_analysis]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/multilevel-path-2.rs:3:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stdout b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stdout
new file mode 100644
index 00000000000..f89670c8b7f
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/multilevel-path-2.stdout
@@ -0,0 +1,35 @@
+For closure=DefId(0:9 ~ multilevel_path_2[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:9 ~ multilevel_path_2[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: Wrapper,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:8 ~ multilevel_path_2[317d]::main), local_id: 1 };`w`;DefId(0:9 ~ multilevel_path_2[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: Point,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+            Projection {
+                ty: i32,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:8 ~ multilevel_path_2[317d]::main),
+                local_id: 35,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#35r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/nested-closure.rs b/src/test/ui/closures/2229_closure_analysis/nested-closure.rs
new file mode 100644
index 00000000000..64b69af0f0c
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/nested-closure.rs
@@ -0,0 +1,40 @@
+// FIXME(arora-aman) add run-pass once 2229 is implemented
+
+#![feature(capture_disjoint_fields)]
+//~^ warning the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+// This testcase ensures that nested closures are handles properly
+// - The nested closure is analyzed first.
+// - The capture kind of the nested closure is accounted for by the enclosing closure
+// - Any captured path by the nested closure that starts off a local variable in the enclosing
+// closure is not listed as a capture of the enclosing closure.
+
+fn main() {
+    let mut p = Point { x: 5, y: 20 };
+
+    let mut c1 = #[rustc_capture_analysis]
+        //~^ ERROR: attributes on expressions are experimental
+    || {
+        println!("{}", p.x);
+        let incr = 10;
+        let mut c2 = #[rustc_capture_analysis]
+        //~^ ERROR: attributes on expressions are experimental
+        || p.y += incr;
+        c2();
+        println!("{}", p.y);
+    };
+
+    c1();
+
+    let px = &p.x;
+
+    println!("{}", px);
+
+    c1();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr b/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr
new file mode 100644
index 00000000000..dbd9e3655a3
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/nested-closure.stderr
@@ -0,0 +1,30 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/nested-closure.rs:19:18
+   |
+LL |     let mut c1 = #[rustc_capture_analysis]
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/nested-closure.rs:24:22
+   |
+LL |         let mut c2 = #[rustc_capture_analysis]
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/nested-closure.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/nested-closure.stdout b/src/test/ui/closures/2229_closure_analysis/nested-closure.stdout
new file mode 100644
index 00000000000..84d87a75bda
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/nested-closure.stdout
@@ -0,0 +1,98 @@
+For closure=DefId(0:8 ~ nested_closure[317d]::main::{closure#0}::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:8 ~ nested_closure[317d]::main::{closure#0}::{closure#0}): capture information: {
+    Place {
+        base_ty: Point,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:6 ~ nested_closure[317d]::main), local_id: 1 };`p`;DefId(0:8 ~ nested_closure[317d]::main::{closure#0}::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: i32,
+                kind: Field(
+                    1,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:6 ~ nested_closure[317d]::main),
+                local_id: 70,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(MutBorrow, '_#109r),
+        ),
+    },
+    Place {
+        base_ty: i32,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:6 ~ nested_closure[317d]::main), local_id: 5 };`incr`;DefId(0:8 ~ nested_closure[317d]::main::{closure#0}::{closure#0})),
+        ),
+        projections: [],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:6 ~ nested_closure[317d]::main),
+                local_id: 72,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#110r),
+        ),
+    },
+}
+For closure=DefId(0:7 ~ nested_closure[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:7 ~ nested_closure[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: Point,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:6 ~ nested_closure[317d]::main), local_id: 1 };`p`;DefId(0:7 ~ nested_closure[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: i32,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:6 ~ nested_closure[317d]::main),
+                local_id: 37,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#114r),
+        ),
+    },
+    Place {
+        base_ty: Point,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:6 ~ nested_closure[317d]::main), local_id: 1 };`p`;DefId(0:7 ~ nested_closure[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: i32,
+                kind: Field(
+                    1,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:6 ~ nested_closure[317d]::main),
+                local_id: 70,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(MutBorrow, '_#115r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs
new file mode 100644
index 00000000000..c967c0b72d4
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.rs
@@ -0,0 +1,28 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+struct Point {
+    x: f32,
+    y: f32,
+}
+
+struct Pentagon {
+    points: [Point; 5],
+}
+
+fn main() {
+    let p1 = Point { x: 10.0, y: 10.0 };
+    let p2 = Point { x: 7.5, y: 12.5 };
+    let p3 = Point { x: 15.0, y: 15.0 };
+    let p4 = Point { x: 12.5, y: 12.5 };
+    let p5 = Point { x: 20.0, y: 10.0 };
+
+    let pent = Pentagon { points: [p1, p2, p3, p4, p5] };
+
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+    || {
+        println!("{}", pent.points[5].x);
+    };
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr
new file mode 100644
index 00000000000..84bcc55d99c
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/path-with-array-access.rs:23:13
+   |
+LL |     let c = #[rustc_capture_analysis]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-with-array-access.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stdout b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stdout
new file mode 100644
index 00000000000..b843b0494b9
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/path-with-array-access.stdout
@@ -0,0 +1,28 @@
+For closure=DefId(0:10 ~ path_with_array_access[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:10 ~ path_with_array_access[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: Pentagon,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:9 ~ path_with_array_access[317d]::main), local_id: 6 };`pent`;DefId(0:10 ~ path_with_array_access[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: [Point; 5],
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:9 ~ path_with_array_access[317d]::main),
+                local_id: 83,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#34r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs
new file mode 100644
index 00000000000..27ab9d6b735
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs
@@ -0,0 +1,33 @@
+// FIXME(arora-aman) add run-pass once 2229 is implemented
+
+#![feature(capture_disjoint_fields)]
+//~^ WARNING the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+// Test to ensure that min analysis meets capture kind for all paths captured.
+
+#[derive(Debug)]
+struct Point {
+    x: i32,
+    y: i32,
+}
+
+fn main() {
+    let mut p = Point { x: 10, y: 20 };
+
+    //
+    // Requirements:
+    // p.x -> MutBoorrow
+    // p   -> ImmBorrow
+    //
+    // Requirements met when p is captured via MutBorrow
+    //
+    let mut c = #[rustc_capture_analysis]
+        //~^ ERROR: attributes on expressions are experimental
+    || {
+        p.x += 10;
+        println!("{:?}", p);
+    };
+
+    c();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
new file mode 100644
index 00000000000..002d2aaab89
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/simple-struct-min-capture.rs:25:17
+   |
+LL |     let mut c = #[rustc_capture_analysis]
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/simple-struct-min-capture.rs:3:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stdout b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stdout
new file mode 100644
index 00000000000..02129f1acb5
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/simple-struct-min-capture.stdout
@@ -0,0 +1,45 @@
+For closure=DefId(0:4 ~ simple_struct_min_capture[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:4 ~ simple_struct_min_capture[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: Point,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:3 ~ simple_struct_min_capture[317d]::main), local_id: 1 };`p`;DefId(0:4 ~ simple_struct_min_capture[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: i32,
+                kind: Field(
+                    0,
+                    0,
+                ),
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:3 ~ simple_struct_min_capture[317d]::main),
+                local_id: 15,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(MutBorrow, '_#34r),
+        ),
+    },
+    Place {
+        base_ty: Point,
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:3 ~ simple_struct_min_capture[317d]::main), local_id: 1 };`p`;DefId(0:4 ~ simple_struct_min_capture[317d]::main::{closure#0})),
+        ),
+        projections: [],
+    }: CaptureInfo {
+        expr_id: Some(
+            HirId {
+                owner: DefId(0:3 ~ simple_struct_min_capture[317d]::main),
+                local_id: 35,
+            },
+        ),
+        capture_kind: ByRef(
+            UpvarBorrow(ImmBorrow, '_#35r),
+        ),
+    },
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/slice-pat.rs b/src/test/ui/closures/2229_closure_analysis/slice-pat.rs
new file mode 100644
index 00000000000..fc966c4193e
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/slice-pat.rs
@@ -0,0 +1,28 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+// Test to ensure Index projections are handled properly during capture analysis
+//
+// The array should be moved in entirety, even though only some elements are used.
+
+fn main() {
+    let arr : [String; 5] = [
+        format!("A"),
+        format!("B"),
+        format!("C"),
+        format!("D"),
+        format!("E")
+    ];
+
+    let c = #[rustc_capture_analysis]
+    //~^ ERROR: attributes on expressions are experimental
+        || {
+            let [a, b, .., e] = arr;
+            assert_eq!(a, "A");
+            assert_eq!(b, "B");
+            assert_eq!(e, "E");
+        };
+
+    c();
+}
diff --git a/src/test/ui/closures/2229_closure_analysis/slice-pat.stderr b/src/test/ui/closures/2229_closure_analysis/slice-pat.stderr
new file mode 100644
index 00000000000..5c6b505d64f
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/slice-pat.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/slice-pat.rs:18:13
+   |
+LL |     let c = #[rustc_capture_analysis]
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+   = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/slice-pat.rs:1:12
+   |
+LL | #![feature(capture_disjoint_fields)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #53488 <https://github.com/rust-lang/rust/issues/53488> for more information
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/closures/2229_closure_analysis/slice-pat.stdout b/src/test/ui/closures/2229_closure_analysis/slice-pat.stdout
new file mode 100644
index 00000000000..ba9b2bca196
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/slice-pat.stdout
@@ -0,0 +1,20 @@
+For closure=DefId(0:5 ~ slice_pat[317d]::main::{closure#0}): Using new-style capture analysis
+For closure=DefId(0:5 ~ slice_pat[317d]::main::{closure#0}): capture information: {
+    Place {
+        base_ty: [std::string::String; 5],
+        base: Upvar(
+            UpvarId(HirId { owner: DefId(0:3 ~ slice_pat[317d]::main), local_id: 1 };`arr`;DefId(0:5 ~ slice_pat[317d]::main::{closure#0})),
+        ),
+        projections: [
+            Projection {
+                ty: std::string::String,
+                kind: Index,
+            },
+        ],
+    }: CaptureInfo {
+        expr_id: None,
+        capture_kind: ByValue(
+            None,
+        ),
+    },
+}