/// 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
// -------------------------------------------------------------------------
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
// ==========================================================================
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)),
use super::FnCtxt;
-use std::env;
-
use crate::expr_use_visitor as euv;
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
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);
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);
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> {
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);
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(_))
-}
--- /dev/null
+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`.