Indroduce feature flag for RFC-2229
Signed-off-by: Aman Arora <me@aman-arora.com>
This commit is contained in:
parent
127a6ede1d
commit
88310cc0eb
7 changed files with 66 additions and 16 deletions
|
@ -616,6 +616,9 @@ declare_features! (
|
||||||
/// Enables `#[cfg(panic = "...")]` config key.
|
/// Enables `#[cfg(panic = "...")]` config key.
|
||||||
(active, cfg_panic, "1.49.0", Some(77443), None),
|
(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
|
// feature-group-end: actual feature gates
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
@ -639,6 +642,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
|
||||||
sym::inline_const,
|
sym::inline_const,
|
||||||
sym::repr128,
|
sym::repr128,
|
||||||
sym::unsized_locals,
|
sym::unsized_locals,
|
||||||
|
sym::capture_disjoint_fields,
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Some features are not allowed to be used together at the same time, if
|
/// Some features are not allowed to be used together at the same time, if
|
||||||
|
|
|
@ -547,6 +547,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
|
||||||
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)),
|
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_variance, Normal, template!(Word)),
|
||||||
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
|
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
|
||||||
rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),
|
rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),
|
||||||
|
|
|
@ -318,6 +318,7 @@ symbols! {
|
||||||
call_mut,
|
call_mut,
|
||||||
call_once,
|
call_once,
|
||||||
caller_location,
|
caller_location,
|
||||||
|
capture_disjoint_fields,
|
||||||
cdylib,
|
cdylib,
|
||||||
ceilf32,
|
ceilf32,
|
||||||
ceilf64,
|
ceilf64,
|
||||||
|
@ -909,6 +910,7 @@ symbols! {
|
||||||
rustc_args_required_const,
|
rustc_args_required_const,
|
||||||
rustc_attrs,
|
rustc_attrs,
|
||||||
rustc_builtin_macro,
|
rustc_builtin_macro,
|
||||||
|
rustc_capture_analysis,
|
||||||
rustc_clean,
|
rustc_clean,
|
||||||
rustc_const_stable,
|
rustc_const_stable,
|
||||||
rustc_const_unstable,
|
rustc_const_unstable,
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
|
|
||||||
use super::FnCtxt;
|
use super::FnCtxt;
|
||||||
|
|
||||||
use std::env;
|
|
||||||
|
|
||||||
use crate::expr_use_visitor as euv;
|
use crate::expr_use_visitor as euv;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -43,8 +41,25 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_infer::infer::UpvarRegion;
|
use rustc_infer::infer::UpvarRegion;
|
||||||
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId};
|
use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts};
|
use rustc_middle::ty::{self, Ty, TyCtxt, UpvarSubsts};
|
||||||
|
use rustc_span::sym;
|
||||||
use rustc_span::{Span, Symbol};
|
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> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
|
pub fn closure_analyze(&self, body: &'tcx hir::Body<'tcx>) {
|
||||||
InferBorrowKindVisitor { fcx: self }.visit_body(body);
|
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 local_def_id = closure_def_id.expect_local();
|
||||||
|
|
||||||
let mut capture_information = FxIndexMap::<Place<'tcx>, ty::CaptureInfo<'tcx>>::default();
|
let mut capture_information = FxIndexMap::<Place<'tcx>, ty::CaptureInfo<'tcx>>::default();
|
||||||
if !new_capture_analysis() {
|
if self.tcx.features().capture_disjoint_fields {
|
||||||
debug!("Using old-style capture analysis");
|
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) {
|
if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
|
||||||
for (&var_hir_id, _) in upvars.iter() {
|
for (&var_hir_id, _) in upvars.iter() {
|
||||||
let place = self.place_for_root_variable(local_def_id, var_hir_id);
|
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(),
|
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> {
|
struct InferBorrowKind<'a, 'tcx> {
|
||||||
|
@ -601,10 +622,6 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
|
||||||
let expr_id = Some(diag_expr_id);
|
let expr_id = Some(diag_expr_id);
|
||||||
let capture_info = ty::CaptureInfo { expr_id, capture_kind };
|
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);
|
self.capture_information.insert(place_with_id.place.clone(), capture_info);
|
||||||
} else {
|
} else {
|
||||||
debug!("Not upvar: {:?}", place_with_id);
|
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 {
|
fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
|
||||||
tcx.hir().name(var_hir_id)
|
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(_))
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
|
@ -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`.
|
|
@ -0,0 +1 @@
|
||||||
|
For closure=DefId(0:4 ~ feature_gate_capture_disjoint_fields[317d]::main::{closure#0}): Using new-style capture analysis
|
Loading…
Add table
Add a link
Reference in a new issue