Auto merge of #82536 - sexxi-goose:handle-patterns-take-2, r=nikomatsakis
2229: Handle patterns within closures correctly when `capture_disjoint_fields` is enabled This PR fixes several issues related to handling patterns within closures when `capture_disjoint_fields` is enabled. 1. Matching is always considered a use of the place, even with `_` patterns 2. Compiler ICE when capturing fields in closures through `let` assignments To do so, we - Introduced new Fake Reads - Delayed use of `Place` in favor of `PlaceBuilder` - Ensured that `PlaceBuilder` can be resolved before attempting to extract `Place` in any of the pattern matching code Closes rust-lang/project-rfc-2229/issues/27 Closes rust-lang/project-rfc-2229/issues/24 r? `@nikomatsakis`
This commit is contained in:
@@ -47,6 +47,7 @@ use rustc_hir::{
|
||||
};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_middle::mir::FakeReadCause;
|
||||
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
|
||||
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
|
||||
use rustc_session::lint::{Level, Lint};
|
||||
@@ -430,6 +431,30 @@ pub struct TypeckResults<'tcx> {
|
||||
/// see `MinCaptureInformationMap` for more details.
|
||||
pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
|
||||
|
||||
/// Tracks the fake reads required for a closure and the reason for the fake read.
|
||||
/// When performing pattern matching for closures, there are times we don't end up
|
||||
/// reading places that are mentioned in a closure (because of _ patterns). However,
|
||||
/// to ensure the places are initialized, we introduce fake reads.
|
||||
/// Consider these two examples:
|
||||
/// ``` (discriminant matching with only wildcard arm)
|
||||
/// let x: u8;
|
||||
/// let c = || match x { _ => () };
|
||||
/// ```
|
||||
/// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't
|
||||
/// want to capture it. However, we do still want an error here, because `x` should have
|
||||
/// to be initialized at the point where c is created. Therefore, we add a "fake read"
|
||||
/// instead.
|
||||
/// ``` (destructured assignments)
|
||||
/// let c = || {
|
||||
/// let (t1, t2) = t;
|
||||
/// }
|
||||
/// ```
|
||||
/// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but
|
||||
/// we never capture `t`. This becomes an issue when we build MIR as we require
|
||||
/// information on `t` in order to create place `t.0` and `t.1`. We can solve this
|
||||
/// issue by fake reading `t`.
|
||||
pub closure_fake_reads: FxHashMap<DefId, Vec<(HirPlace<'tcx>, FakeReadCause, hir::HirId)>>,
|
||||
|
||||
/// 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: ty::Binder<Vec<GeneratorInteriorTypeCause<'tcx>>>,
|
||||
@@ -464,6 +489,7 @@ impl<'tcx> TypeckResults<'tcx> {
|
||||
concrete_opaque_types: Default::default(),
|
||||
closure_captures: Default::default(),
|
||||
closure_min_captures: Default::default(),
|
||||
closure_fake_reads: Default::default(),
|
||||
generator_interior_types: ty::Binder::dummy(Default::default()),
|
||||
treat_byte_string_as_slice: Default::default(),
|
||||
}
|
||||
@@ -715,6 +741,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
|
||||
ref concrete_opaque_types,
|
||||
ref closure_captures,
|
||||
ref closure_min_captures,
|
||||
ref closure_fake_reads,
|
||||
ref generator_interior_types,
|
||||
ref treat_byte_string_as_slice,
|
||||
} = *self;
|
||||
@@ -750,6 +777,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckResults<'tcx> {
|
||||
concrete_opaque_types.hash_stable(hcx, hasher);
|
||||
closure_captures.hash_stable(hcx, hasher);
|
||||
closure_min_captures.hash_stable(hcx, hasher);
|
||||
closure_fake_reads.hash_stable(hcx, hasher);
|
||||
generator_interior_types.hash_stable(hcx, hasher);
|
||||
treat_byte_string_as_slice.hash_stable(hcx, hasher);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user