Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Places to express closure captures #24

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4201,6 +4201,7 @@ dependencies = [
name = "rustc_typeck"
version = "0.0.0"
dependencies = [
"indexmap",
"rustc_arena",
"rustc_ast",
"rustc_attr",
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,9 @@ declare_features! (
/// Allows `#[instruction_set(_)]` attribute
(active, isa_attribute, "1.48.0", Some(74727), 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
// -------------------------------------------------------------------------
Expand All @@ -618,6 +621,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
sym::const_trait_bound_opt_out,
sym::lazy_normalization_consts,
sym::specialization,
sym::capture_disjoint_fields,
];

/// Some features are not allowed to be used together at the same time, if
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,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)),
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,10 @@ pub struct TypeckResults<'tcx> {
/// entire variable.
pub closure_captures: ty::UpvarListMap,

/// Given the closure ID this map provides the list of
/// `Place`s and how/why are they captured by the closure.
pub closure_capture_information: ty::CaptureInformationMap<'tcx>,

/// Stores the type, expression, span and optional scope span of all types
/// that are live across the yield of this generator (if a generator).
pub generator_interior_types: Vec<GeneratorInteriorTypeCause<'tcx>>,
Expand Down Expand Up @@ -442,6 +446,7 @@ impl<'tcx> TypeckResults<'tcx> {
tainted_by_errors: None,
concrete_opaque_types: Default::default(),
closure_captures: Default::default(),
closure_capture_information: Default::default(),
generator_interior_types: Default::default(),
}
}
Expand Down Expand Up @@ -676,6 +681,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
tainted_by_errors,
ref concrete_opaque_types,
ref closure_captures,
ref closure_capture_information,
ref generator_interior_types,
} = *self;

Expand Down Expand Up @@ -709,6 +715,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
tainted_by_errors.hash_stable(hcx, hasher);
concrete_opaque_types.hash_stable(hcx, hasher);
closure_captures.hash_stable(hcx, hasher);
closure_capture_information.hash_stable(hcx, hasher);
generator_interior_types.hash_stable(hcx, hasher);
})
}
Expand Down
54 changes: 54 additions & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use self::IntVarValue::*;
pub use self::Variance::*;

use crate::hir::exports::ExportMap;
use crate::hir::place::Place as HirPlace;
use crate::ich::StableHashingContext;
use crate::middle::cstore::CrateStoreDyn;
use crate::middle::resolve_lifetime::ObjectLifetimeDefault;
Expand Down Expand Up @@ -669,6 +670,12 @@ pub struct UpvarId {
pub closure_expr_id: LocalDefId,
}

impl UpvarId {
pub fn new(var_hir_id: hir::HirId, closure_def_id: LocalDefId) -> UpvarId {
UpvarId { var_path: UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_def_id }
}
}

#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
Expand Down Expand Up @@ -751,9 +758,56 @@ pub struct UpvarBorrow<'tcx> {
pub region: ty::Region<'tcx>,
}

#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
pub struct CaptureInfo<'tcx> {
/// Expr Id pointing to use that resulting in selecting the current capture kind
///
/// If the user doesn't enable feature `capture_disjoint_fields` (RFC 2229) then, it is
/// possible that we don't see the use of a particular place resulting in expr_id being
/// None. In such case we fallback on uvpars_mentioned for span.
///
/// Eg:
/// ```rust
/// let x = ...;
///
/// let c = || {
/// let _ = x
/// }
/// ```
///
/// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured,
/// but we won't see it being used during capture analysis, since it's essentially a discard.
pub expr_id: Option<hir::HirId>,

/// Capture mode that was selected
pub capture_kind: UpvarCapture<'tcx>,
}

pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;

/// Consider closure where s.str1 is captured via an ImmutableBorrow and s.str2 via a MutableBorrow
///
/// ```rust
/// // Assume that thte HirId for the variable definition is `V1`
/// let mut s = SomeStruct { str1: format!("s1"), str2: format!("s2") }
///
/// let fix_s = |new_s2| {
/// // Assume that the HirId for the expression `s.str1` is `E1`
/// println!("Updating SomeStruct with str1=", s.str1);
/// // Assume that the HirId for the expression `*s.str2` is `E2`
/// s.str2 = new_s2;
/// }
/// ```
///
/// For closure `fix_s`, (at a high level) the IndexMap will contain:
///
/// Place { V1, [ProjectionKind::Field(Index=0, Variant=0)] } : CaptureKind { E1, ImmutableBorrow }
/// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
///
pub type CaptureInformationMap<'tcx> =
FxHashMap<DefId, FxIndexMap<HirPlace<'tcx>, CaptureInfo<'tcx>>>;

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum IntVarValue {
IntType(ast::IntTy),
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_mir_build/src/thir/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,9 @@ fn make_mirror_unadjusted<'a, 'tcx>(
}
};
let upvars = cx
.tcx
.upvars_mentioned(def_id)
.typeck_results()
.closure_captures
.get(&def_id)
.iter()
.flat_map(|upvars| upvars.iter())
.zip(substs.upvar_tys())
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ symbols! {
call_mut,
call_once,
caller_location,
capture_disjoint_fields,
cdylib,
ceilf32,
ceilf64,
Expand Down Expand Up @@ -895,6 +896,7 @@ symbols! {
rustc_args_required_const,
rustc_attrs,
rustc_builtin_macro,
rustc_capture_analysis,
rustc_clean,
rustc_const_stable,
rustc_const_unstable,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_typeck/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ test = false
doctest = false

[dependencies]
indexmap = "1.5.1"
rustc_arena = { path = "../rustc_arena" }
tracing = "0.1"
rustc_macros = { path = "../rustc_macros" }
Expand Down
Loading