about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAman Arora <me@aman-arora.com>2020-10-11 00:14:11 -0400
committerAman Arora <me@aman-arora.com>2020-11-10 20:58:28 -0500
commit88310cc0ebf4144205743dbb3a65223deffcf8e6 (patch)
tree44ea1014b63661687515c17cc8b74572aad787ca
parent127a6ede1dd9622db20bee435221205b3a61d0ba (diff)
downloadrust-88310cc0ebf4144205743dbb3a65223deffcf8e6.tar.gz
rust-88310cc0ebf4144205743dbb3a65223deffcf8e6.zip
Indroduce feature flag for RFC-2229
Signed-off-by: Aman Arora <me@aman-arora.com>
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs41
-rw-r--r--src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs12
-rw-r--r--src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr21
-rw-r--r--src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout1
7 files changed, 66 insertions, 16 deletions
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 0df67b63eba..a0355079247 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -616,6 +616,9 @@ declare_features! (
     /// Enables `#[cfg(panic = "...")]` config key.
     (active, cfg_panic, "1.49.0", Some(77443), None),
 
+    /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
+    (active, capture_disjoint_fields, "1.49.0", Some(53488), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
@@ -639,6 +642,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::inline_const,
     sym::repr128,
     sym::unsized_locals,
+    sym::capture_disjoint_fields,
 ];
 
 /// Some features are not allowed to be used together at the same time, if
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 5c5cf609ac3..fa8edba629e 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -547,6 +547,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // ==========================================================================
 
     rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)),
+    rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_variance, Normal, template!(Word)),
     rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
     rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ad58f89d87d..3a2a3adce35 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -318,6 +318,7 @@ symbols! {
         call_mut,
         call_once,
         caller_location,
+        capture_disjoint_fields,
         cdylib,
         ceilf32,
         ceilf64,
@@ -909,6 +910,7 @@ symbols! {
         rustc_args_required_const,
         rustc_attrs,
         rustc_builtin_macro,
+        rustc_capture_analysis,
         rustc_clean,
         rustc_const_stable,
         rustc_const_unstable,
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index 24bb7756ef3..a28744c2ece 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -32,8 +32,6 @@
 
 use super::FnCtxt;
 
-use std::env;
-
 use crate::expr_use_visitor as euv;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
@@ -43,8 +41,25 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_infer::infer::UpvarRegion;
 use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId};
 use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts};
+use rustc_span::sym;
 use rustc_span::{Span, Symbol};
 
+macro_rules! log_capture_analysis {
+    ($fcx:expr, $closure_def_id:expr, $fmt:literal) => {
+        if $fcx.should_log_capture_analysis($closure_def_id) {
+            print!("For closure={:?}: ", $closure_def_id);
+            println!($fmt);
+        }
+    };
+
+    ($fcx:expr, $closure_def_id:expr, $fmt:literal, $($args:expr),*) => {
+        if $fcx.should_log_capture_analysis($closure_def_id) {
+            print!("For closure={:?}: ", $closure_def_id);
+            println!($fmt, $($args),*);
+        }
+    };
+}
+
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
         InferBorrowKindVisitor { fcx: self }.visit_body(body);
@@ -115,8 +130,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let local_def_id = closure_def_id.expect_local();
 
         let mut capture_information = FxIndexMap::<Place<'tcx>, ty::CaptureInfo<'tcx>>::default();
-        if !new_capture_analysis() {
-            debug!("Using old-style capture analysis");
+        if self.tcx.features().capture_disjoint_fields {
+            log_capture_analysis!(self, closure_def_id, "Using new-style capture analysis");
+        } else {
+            log_capture_analysis!(self, closure_def_id, "Using old-style capture analysis");
             if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
                 for (&var_hir_id, _) in upvars.iter() {
                     let place = self.place_for_root_variable(local_def_id, var_hir_id);
@@ -325,6 +342,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             projections: Default::default(),
         }
     }
+
+    fn should_log_capture_analysis(&self, closure_def_id: DefId) -> bool {
+        self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
+    }
 }
 
 struct InferBorrowKind<'a, 'tcx> {
@@ -601,10 +622,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
             let expr_id = Some(diag_expr_id);
             let capture_info = ty::CaptureInfo { expr_id, capture_kind };
 
-            if log_capture_analysis() {
-                debug!("capture_info: {:?}", capture_info);
-            }
-
             self.capture_information.insert(place_with_id.place.clone(), capture_info);
         } else {
             debug!("Not upvar: {:?}", place_with_id);
@@ -670,11 +687,3 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
 fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
     tcx.hir().name(var_hir_id)
 }
-
-fn new_capture_analysis() -> bool {
-    matches!(env::var("SG_NEW"), Ok(_))
-}
-
-fn log_capture_analysis() -> bool {
-    matches!(env::var("SG_VERBOSE"), Ok(_))
-}
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
new file mode 100644
index 00000000000..5eab718736c
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
@@ -0,0 +1,12 @@
+#![feature(capture_disjoint_fields)]
+//~^ WARNING the feature `capture_disjoint_fields` is incomplete
+#![feature(rustc_attrs)]
+
+fn main() {
+    let s = format!("s");
+
+    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
new file mode 100644
index 00000000000..4dc1f9a6ab2
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
@@ -0,0 +1,21 @@
+error[E0658]: attributes on expressions are experimental
+  --> $DIR/feature-gate-capture_disjoint_fields.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/feature-gate-capture_disjoint_fields.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/feature-gate-capture_disjoint_fields.stdout b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout
new file mode 100644
index 00000000000..c1fca9afd39
--- /dev/null
+++ b/src/test/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stdout
@@ -0,0 +1 @@
+For closure=DefId(0:4 ~ feature_gate_capture_disjoint_fields[317d]::main::{closure#0}): Using new-style capture analysis