mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 16:54:01 +00:00
Delay use of Place in favor of PlaceBuilder
This commit is contained in:
parent
ec10b71d42
commit
d4f8729c89
@ -94,6 +94,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
)
|
||||
);
|
||||
}
|
||||
// ROX:
|
||||
//
|
||||
// Where the handling of destructure patterns start
|
||||
//
|
||||
// let (a, b, c, _ ) = something
|
||||
//
|
||||
// (a, b, c, _) is the pattern
|
||||
// something is the initializer
|
||||
StmtKind::Let { remainder_scope, init_scope, pattern, initializer, lint_level } => {
|
||||
let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
|
||||
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
|
||||
@ -125,6 +133,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
ArmHasGuard(false),
|
||||
Some((None, initializer_span)),
|
||||
);
|
||||
// This is where we get into pattern handling of the let
|
||||
// statement
|
||||
this.expr_into_pattern(block, pattern.clone(), init)
|
||||
})
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ use rustc_middle::hir::place::ProjectionKind as HirProjectionKind;
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::AssertKind::BoundsCheck;
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::AdtDef;
|
||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::VariantIdx;
|
||||
@ -17,7 +18,7 @@ use rustc_target::abi::VariantIdx;
|
||||
use rustc_index::vec::Idx;
|
||||
|
||||
/// The "outermost" place that holds this value.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
crate enum PlaceBase {
|
||||
/// Denotes the start of a `Place`.
|
||||
Local(Local),
|
||||
@ -67,7 +68,7 @@ crate enum PlaceBase {
|
||||
///
|
||||
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
|
||||
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
crate struct PlaceBuilder<'tcx> {
|
||||
base: PlaceBase,
|
||||
projection: Vec<PlaceElem<'tcx>>,
|
||||
@ -292,6 +293,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// ROX: Function that will be called when we really do need a place
|
||||
fn expect_upvars_resolved<'a>(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -319,15 +321,22 @@ impl<'tcx> PlaceBuilder<'tcx> {
|
||||
self.project(PlaceElem::Field(f, ty))
|
||||
}
|
||||
|
||||
fn deref(self) -> Self {
|
||||
crate fn deref(self) -> Self {
|
||||
self.project(PlaceElem::Deref)
|
||||
}
|
||||
|
||||
crate fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Self {
|
||||
self.project(PlaceElem::Downcast(
|
||||
Some(adt_def.variants[variant_index].ident.name),
|
||||
variant_index,
|
||||
))
|
||||
}
|
||||
|
||||
fn index(self, index: Local) -> Self {
|
||||
self.project(PlaceElem::Index(index))
|
||||
}
|
||||
|
||||
fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
|
||||
crate fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
|
||||
self.projection.push(elem);
|
||||
self
|
||||
}
|
||||
@ -367,6 +376,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block.and(place_builder.into_place(self.tcx, self.typeck_results))
|
||||
}
|
||||
|
||||
// ROX: As place builder
|
||||
/// This is used when constructing a compound `Place`, so that we can avoid creating
|
||||
/// intermediate `Place` values until we know the full set of projections.
|
||||
crate fn as_place_builder(
|
||||
@ -613,13 +623,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// The "retagging" transformation (for Stacked Borrows) relies on this.
|
||||
let idx = unpack!(block = self.as_temp(block, temp_lifetime, index, Mutability::Not,));
|
||||
|
||||
block = self.bounds_check(
|
||||
block,
|
||||
base_place.clone().into_place(self.tcx, self.typeck_results),
|
||||
idx,
|
||||
expr_span,
|
||||
source_info,
|
||||
);
|
||||
block = self.bounds_check(block, base_place.clone(), idx, expr_span, source_info);
|
||||
|
||||
if is_outermost_index {
|
||||
self.read_fake_borrows(block, fake_borrow_temps, source_info)
|
||||
@ -640,7 +644,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn bounds_check(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
slice: Place<'tcx>,
|
||||
slice: PlaceBuilder<'tcx>,
|
||||
index: Local,
|
||||
expr_span: Span,
|
||||
source_info: SourceInfo,
|
||||
@ -652,7 +656,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let lt = self.temp(bool_ty, expr_span);
|
||||
|
||||
// len = len(slice)
|
||||
self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice));
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
len,
|
||||
Rvalue::Len(slice.clone().into_place(self.tcx, self.typeck_results)),
|
||||
);
|
||||
// lt = idx < len
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
|
@ -280,6 +280,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let field_names: Vec<_> =
|
||||
(0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect();
|
||||
|
||||
// ROX: This is probably here the function record/struct update pattern is done.
|
||||
let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
|
||||
let place_builder = unpack!(block = this.as_place_builder(block, base));
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
||||
|
||||
mod as_constant;
|
||||
mod as_operand;
|
||||
mod as_place;
|
||||
pub mod as_place;
|
||||
mod as_rvalue;
|
||||
mod as_temp;
|
||||
mod category;
|
||||
|
@ -1,3 +1,6 @@
|
||||
// ROX: this folder contains all code for handling patterns, including exhaustiveness checking etc.
|
||||
// We want to be careful ^^'
|
||||
|
||||
//! Code related to match expressions. These are sufficiently complex to
|
||||
//! warrant their own module and submodules. :) This main module includes the
|
||||
//! high-level algorithm, the submodules contain the details.
|
||||
@ -5,6 +8,7 @@
|
||||
//! This also includes code for pattern bindings in `let` statements and
|
||||
//! function parameters.
|
||||
|
||||
use crate::build::expr::as_place::PlaceBuilder;
|
||||
use crate::build::scope::DropKind;
|
||||
use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
|
||||
use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||
@ -96,7 +100,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let scrutinee_place =
|
||||
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,));
|
||||
|
||||
let mut arm_candidates = self.create_match_candidates(scrutinee_place, &arms);
|
||||
let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
|
||||
|
||||
let match_has_guard = arms.iter().any(|arm| arm.guard.is_some());
|
||||
let mut candidates =
|
||||
@ -121,8 +125,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
mut block: BasicBlock,
|
||||
scrutinee: &Expr<'_, 'tcx>,
|
||||
scrutinee_span: Span,
|
||||
) -> BlockAnd<Place<'tcx>> {
|
||||
let scrutinee_place = unpack!(block = self.as_place(block, scrutinee));
|
||||
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||
let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee));
|
||||
let scrutinee_place =
|
||||
scrutinee_place_builder.clone().into_place(self.tcx, self.typeck_results);
|
||||
// Matching on a `scrutinee_place` with an uninhabited type doesn't
|
||||
// generate any memory reads by itself, and so if the place "expression"
|
||||
// contains unsafe operations like raw pointer dereferences or union
|
||||
@ -142,13 +148,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let source_info = self.source_info(scrutinee_span);
|
||||
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
|
||||
|
||||
block.and(scrutinee_place)
|
||||
block.and(scrutinee_place_builder)
|
||||
}
|
||||
|
||||
/// Create the initial `Candidate`s for a `match` expression.
|
||||
fn create_match_candidates<'pat>(
|
||||
&mut self,
|
||||
scrutinee: Place<'tcx>,
|
||||
scrutinee: PlaceBuilder<'tcx>,
|
||||
arms: &'pat [Arm<'pat, 'tcx>],
|
||||
) -> Vec<(&'pat Arm<'pat, 'tcx>, Candidate<'pat, 'tcx>)> {
|
||||
// Assemble a list of candidates: there is one candidate per pattern,
|
||||
@ -156,7 +162,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
arms.iter()
|
||||
.map(|arm| {
|
||||
let arm_has_guard = arm.guard.is_some();
|
||||
let arm_candidate = Candidate::new(scrutinee, &arm.pattern, arm_has_guard);
|
||||
let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard);
|
||||
(arm, arm_candidate)
|
||||
})
|
||||
.collect()
|
||||
@ -222,7 +228,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn lower_match_arms(
|
||||
&mut self,
|
||||
destination: Place<'tcx>,
|
||||
scrutinee_place: Place<'tcx>,
|
||||
scrutinee_place: PlaceBuilder<'tcx>,
|
||||
scrutinee_span: Span,
|
||||
arm_candidates: Vec<(&'_ Arm<'_, 'tcx>, Candidate<'_, 'tcx>)>,
|
||||
outer_source_info: SourceInfo,
|
||||
@ -241,7 +247,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
arm.span,
|
||||
&arm.pattern,
|
||||
ArmHasGuard(arm.guard.is_some()),
|
||||
Some((Some(&scrutinee_place), scrutinee_span)),
|
||||
Some((
|
||||
Some(
|
||||
&scrutinee_place.clone().into_place(this.tcx, this.typeck_results),
|
||||
),
|
||||
scrutinee_span,
|
||||
)),
|
||||
);
|
||||
|
||||
let arm_block = this.bind_pattern(
|
||||
@ -446,8 +457,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
_ => {
|
||||
let place = unpack!(block = self.as_place(block, initializer));
|
||||
self.place_into_pattern(block, irrefutable_pat, place, true)
|
||||
// Converts the destruct pattern into a place
|
||||
//
|
||||
// We don't want to convert to a place right away
|
||||
// because in case of such pattern inside a closure, the projections matching a
|
||||
// captured place might have not been applied.
|
||||
// [FIXME] Need to find where this is happening and make the necessary changes there once
|
||||
// Candidate is modified
|
||||
//
|
||||
// We want to use a place builder; Maybe use `as_place_builder`
|
||||
let place_builder = unpack!(block = self.as_place_builder(block, initializer));
|
||||
self.place_into_pattern(block, irrefutable_pat, place_builder, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,9 +476,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
irrefutable_pat: Pat<'tcx>,
|
||||
initializer: Place<'tcx>,
|
||||
initializer: PlaceBuilder<'tcx>,
|
||||
set_match_place: bool,
|
||||
) -> BlockAnd<()> {
|
||||
let place = initializer.clone().into_place(self.tcx, self.typeck_results);
|
||||
let mut candidate = Candidate::new(initializer, &irrefutable_pat, false);
|
||||
|
||||
let fake_borrow_temps =
|
||||
@ -478,7 +499,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
|
||||
)))) = self.local_decls[local].local_info
|
||||
{
|
||||
*match_place = Some(initializer);
|
||||
*match_place = Some(place);
|
||||
} else {
|
||||
bug!("Let binding to non-user variable.")
|
||||
}
|
||||
@ -717,7 +738,7 @@ struct Candidate<'pat, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
|
||||
fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self {
|
||||
fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self {
|
||||
Candidate {
|
||||
span: pattern.span,
|
||||
has_guard,
|
||||
@ -791,7 +812,7 @@ struct Ascription<'tcx> {
|
||||
#[derive(Clone, Debug)]
|
||||
crate struct MatchPair<'pat, 'tcx> {
|
||||
// this place...
|
||||
place: Place<'tcx>,
|
||||
place: PlaceBuilder<'tcx>,
|
||||
|
||||
// ... must match this pattern.
|
||||
pattern: &'pat Pat<'tcx>,
|
||||
@ -1198,7 +1219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
&mut otherwise,
|
||||
pats,
|
||||
or_span,
|
||||
place,
|
||||
place.clone(),
|
||||
fake_borrows,
|
||||
);
|
||||
});
|
||||
@ -1224,12 +1245,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
otherwise: &mut Option<BasicBlock>,
|
||||
pats: &'pat [Pat<'tcx>],
|
||||
or_span: Span,
|
||||
place: Place<'tcx>,
|
||||
place: PlaceBuilder<'tcx>,
|
||||
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>,
|
||||
) {
|
||||
debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats);
|
||||
let mut or_candidates: Vec<_> =
|
||||
pats.iter().map(|pat| Candidate::new(place, pat, candidate.has_guard)).collect();
|
||||
let mut or_candidates: Vec<_> = pats
|
||||
.iter()
|
||||
.map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
|
||||
.collect();
|
||||
let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect();
|
||||
let otherwise = if candidate.otherwise_block.is_some() {
|
||||
&mut candidate.otherwise_block
|
||||
@ -1412,7 +1435,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// extract the match-pair from the highest priority candidate
|
||||
let match_pair = &candidates.first().unwrap().match_pairs[0];
|
||||
let mut test = self.test(match_pair);
|
||||
let match_place = match_pair.place;
|
||||
let match_place = match_pair.place.clone();
|
||||
|
||||
// most of the time, the test to perform is simply a function
|
||||
// of the main candidate; but for a test like SwitchInt, we
|
||||
@ -1428,7 +1451,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
TestKind::Switch { adt_def: _, ref mut variants } => {
|
||||
for candidate in candidates.iter() {
|
||||
if !self.add_variants_to_switch(&match_place, candidate, variants) {
|
||||
if !self.add_variants_to_switch(&match_place.clone(), candidate, variants) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1438,7 +1461,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
// Insert a Shallow borrow of any places that is switched on.
|
||||
if let Some(fb) = fake_borrows {
|
||||
fb.insert(match_place);
|
||||
fb.insert(match_place.clone().into_place(self.tcx, self.typeck_results));
|
||||
}
|
||||
|
||||
// perform the test, branching to one of N blocks. For each of
|
||||
@ -1456,7 +1479,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// encounter a candidate where the test is not relevant; at
|
||||
// that point, we stop sorting.
|
||||
while let Some(candidate) = candidates.first_mut() {
|
||||
if let Some(idx) = self.sort_candidate(&match_place, &test, candidate) {
|
||||
if let Some(idx) = self.sort_candidate(&match_place.clone(), &test, candidate) {
|
||||
let (candidate, rest) = candidates.split_first_mut().unwrap();
|
||||
target_candidates[idx].push(candidate);
|
||||
candidates = rest;
|
||||
@ -1519,7 +1542,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
target_blocks
|
||||
};
|
||||
|
||||
self.perform_test(block, match_place, &test, make_target_blocks);
|
||||
self.perform_test(block, match_place.clone(), &test, make_target_blocks);
|
||||
}
|
||||
|
||||
/// Determine the fake borrows that are needed from a set of places that
|
||||
@ -1753,11 +1776,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
Guard::IfLet(pat, scrutinee) => {
|
||||
let scrutinee_span = scrutinee.span;
|
||||
let scrutinee_place =
|
||||
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span));
|
||||
let mut guard_candidate = Candidate::new(scrutinee_place, &pat, false);
|
||||
let scrutinee_place = unpack!(
|
||||
block = self.lower_scrutinee(block, scrutinee.clone(), scrutinee_span)
|
||||
);
|
||||
let mut guard_candidate = Candidate::new(scrutinee_place.clone(), &pat, false);
|
||||
let wildcard = Pat::wildcard_from_ty(pat.ty);
|
||||
let mut otherwise_candidate = Candidate::new(scrutinee_place, &wildcard, false);
|
||||
let mut otherwise_candidate =
|
||||
Candidate::new(scrutinee_place.clone(), &wildcard, false);
|
||||
let fake_borrow_temps = self.lower_match_tree(
|
||||
block,
|
||||
pat.span,
|
||||
@ -1769,7 +1794,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pat.span.to(arm_span.unwrap()),
|
||||
pat,
|
||||
ArmHasGuard(false),
|
||||
Some((Some(&scrutinee_place), scrutinee.span)),
|
||||
Some((
|
||||
Some(&scrutinee_place.clone().into_place(tcx, self.typeck_results)),
|
||||
scrutinee.span,
|
||||
)),
|
||||
);
|
||||
let post_guard_block = self.bind_pattern(
|
||||
self.source_info(pat.span),
|
||||
|
@ -12,11 +12,11 @@
|
||||
//! sort of test: for example, testing which variant an enum is, or
|
||||
//! testing a value against a constant.
|
||||
|
||||
use crate::build::expr::as_place::PlaceBuilder;
|
||||
use crate::build::matches::{Ascription, Binding, Candidate, MatchPair};
|
||||
use crate::build::Builder;
|
||||
use crate::thir::{self, *};
|
||||
use rustc_hir::RangeEnd;
|
||||
use rustc_middle::mir::Place;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::IntegerExt;
|
||||
use rustc_target::abi::{Integer, Size};
|
||||
@ -68,11 +68,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let match_pairs = mem::take(&mut candidate.match_pairs);
|
||||
|
||||
if let [MatchPair { pattern: Pat { kind: box PatKind::Or { pats }, .. }, place }] =
|
||||
*match_pairs
|
||||
&*match_pairs.clone()
|
||||
{
|
||||
existing_bindings.extend_from_slice(&new_bindings);
|
||||
mem::swap(&mut candidate.bindings, &mut existing_bindings);
|
||||
candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
|
||||
candidate.subcandidates =
|
||||
self.create_or_subcandidates(candidate, place.clone(), pats);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -125,12 +126,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fn create_or_subcandidates<'pat>(
|
||||
&mut self,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
place: Place<'tcx>,
|
||||
place: PlaceBuilder<'tcx>,
|
||||
pats: &'pat [Pat<'tcx>],
|
||||
) -> Vec<Candidate<'pat, 'tcx>> {
|
||||
pats.iter()
|
||||
.map(|pat| {
|
||||
let mut candidate = Candidate::new(place, pat, candidate.has_guard);
|
||||
let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard);
|
||||
self.simplify_candidate(&mut candidate);
|
||||
candidate
|
||||
})
|
||||
@ -148,6 +149,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
) -> Result<(), MatchPair<'pat, 'tcx>> {
|
||||
let tcx = self.tcx;
|
||||
// Generate place to be used in Ascription
|
||||
// Generate place to be used in Binding
|
||||
let place = match_pair.place.clone().into_place(tcx, self.typeck_results);
|
||||
match *match_pair.pattern.kind {
|
||||
PatKind::AscribeUserType {
|
||||
ref subpattern,
|
||||
@ -158,7 +162,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
candidate.ascriptions.push(Ascription {
|
||||
span: user_ty_span,
|
||||
user_ty,
|
||||
source: match_pair.place,
|
||||
source: place,
|
||||
variance,
|
||||
});
|
||||
|
||||
@ -177,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
name,
|
||||
mutability,
|
||||
span: match_pair.pattern.span,
|
||||
source: match_pair.place,
|
||||
source: place,
|
||||
var_id: var,
|
||||
var_ty: ty,
|
||||
binding_mode: mode,
|
||||
@ -264,8 +268,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}) && (adt_def.did.is_local()
|
||||
|| !adt_def.is_variant_list_non_exhaustive());
|
||||
if irrefutable {
|
||||
let place = tcx.mk_place_downcast(match_pair.place, adt_def, variant_index);
|
||||
candidate.match_pairs.extend(self.field_match_pairs(place, subpatterns));
|
||||
let place_builder = match_pair.place.downcast(adt_def, variant_index);
|
||||
candidate
|
||||
.match_pairs
|
||||
.extend(self.field_match_pairs(place_builder, subpatterns));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(match_pair)
|
||||
@ -290,8 +296,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
PatKind::Deref { ref subpattern } => {
|
||||
let place = tcx.mk_place_deref(match_pair.place);
|
||||
candidate.match_pairs.push(MatchPair::new(place, subpattern));
|
||||
let place_builder = match_pair.place.deref();
|
||||
candidate.match_pairs.push(MatchPair::new(place_builder, subpattern));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
// identify what tests are needed, perform the tests, and then filter
|
||||
// the candidates based on the result.
|
||||
|
||||
use crate::build::expr::as_place::PlaceBuilder;
|
||||
use crate::build::matches::{Candidate, MatchPair, Test, TestKind};
|
||||
use crate::build::Builder;
|
||||
use crate::thir::pattern::compare_const_vals;
|
||||
@ -81,7 +82,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
pub(super) fn add_cases_to_switch<'pat>(
|
||||
&mut self,
|
||||
test_place: &Place<'tcx>,
|
||||
test_place: &PlaceBuilder<'tcx>,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
switch_ty: Ty<'tcx>,
|
||||
options: &mut FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
|
||||
@ -123,7 +124,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
|
||||
pub(super) fn add_variants_to_switch<'pat>(
|
||||
&mut self,
|
||||
test_place: &Place<'tcx>,
|
||||
test_place: &PlaceBuilder<'tcx>,
|
||||
candidate: &Candidate<'pat, 'tcx>,
|
||||
variants: &mut BitSet<VariantIdx>,
|
||||
) -> bool {
|
||||
@ -151,10 +152,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
pub(super) fn perform_test(
|
||||
&mut self,
|
||||
block: BasicBlock,
|
||||
place: Place<'tcx>,
|
||||
place_builder: PlaceBuilder<'tcx>,
|
||||
test: &Test<'tcx>,
|
||||
make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
|
||||
) {
|
||||
let place = place_builder.clone().into_place(self.tcx, self.typeck_results);
|
||||
debug!(
|
||||
"perform_test({:?}, {:?}: {:?}, {:?})",
|
||||
block,
|
||||
@ -481,7 +483,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
/// tighter match code if we do something a bit different.
|
||||
pub(super) fn sort_candidate<'pat>(
|
||||
&mut self,
|
||||
test_place: &Place<'tcx>,
|
||||
test_place: &PlaceBuilder<'tcx>,
|
||||
test: &Test<'tcx>,
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
) -> Option<usize> {
|
||||
@ -728,7 +730,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
candidate: &mut Candidate<'pat, 'tcx>,
|
||||
) {
|
||||
let match_pair = candidate.match_pairs.remove(match_pair_index);
|
||||
let tcx = self.tcx;
|
||||
|
||||
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
|
||||
// we want to create a set of derived match-patterns like
|
||||
@ -737,10 +738,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
Some(adt_def.variants[variant_index].ident.name),
|
||||
variant_index,
|
||||
);
|
||||
let downcast_place = tcx.mk_place_elem(match_pair.place, elem); // `(x as Variant)`
|
||||
let downcast_place = match_pair.place.project(elem); // `(x as Variant)`
|
||||
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
|
||||
// e.g., `(x as Variant).0`
|
||||
let place = tcx.mk_place_field(downcast_place, subpattern.field, subpattern.pattern.ty);
|
||||
let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);
|
||||
// e.g., `(x as Variant).0 @ P1`
|
||||
MatchPair::new(place, &subpattern.pattern)
|
||||
});
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::build::expr::as_place::PlaceBuilder;
|
||||
use crate::build::matches::MatchPair;
|
||||
use crate::build::Builder;
|
||||
use crate::thir::*;
|
||||
@ -9,13 +10,13 @@ use std::convert::TryInto;
|
||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
crate fn field_match_pairs<'pat>(
|
||||
&mut self,
|
||||
place: Place<'tcx>,
|
||||
place: PlaceBuilder<'tcx>,
|
||||
subpatterns: &'pat [FieldPat<'tcx>],
|
||||
) -> Vec<MatchPair<'pat, 'tcx>> {
|
||||
subpatterns
|
||||
.iter()
|
||||
.map(|fieldpat| {
|
||||
let place = self.tcx.mk_place_field(place, fieldpat.field, fieldpat.pattern.ty);
|
||||
let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty);
|
||||
MatchPair::new(place, &fieldpat.pattern)
|
||||
})
|
||||
.collect()
|
||||
@ -24,13 +25,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
crate fn prefix_slice_suffix<'pat>(
|
||||
&mut self,
|
||||
match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
|
||||
place: &Place<'tcx>,
|
||||
place: &PlaceBuilder<'tcx>,
|
||||
prefix: &'pat [Pat<'tcx>],
|
||||
opt_slice: Option<&'pat Pat<'tcx>>,
|
||||
suffix: &'pat [Pat<'tcx>],
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let (min_length, exact_size) = match place.ty(&self.local_decls, tcx).ty.kind() {
|
||||
let (min_length, exact_size) = match place
|
||||
.clone()
|
||||
.into_place(tcx, self.typeck_results)
|
||||
.ty(&self.local_decls, tcx)
|
||||
.ty
|
||||
.kind()
|
||||
{
|
||||
ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
|
||||
_ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
|
||||
};
|
||||
@ -38,20 +45,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
|
||||
let elem =
|
||||
ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
|
||||
let place = tcx.mk_place_elem(*place, elem);
|
||||
let place = place.clone().project(elem);
|
||||
MatchPair::new(place, subpattern)
|
||||
}));
|
||||
|
||||
if let Some(subslice_pat) = opt_slice {
|
||||
let suffix_len = suffix.len() as u64;
|
||||
let subslice = tcx.mk_place_elem(
|
||||
*place,
|
||||
ProjectionElem::Subslice {
|
||||
from: prefix.len() as u64,
|
||||
to: if exact_size { min_length - suffix_len } else { suffix_len },
|
||||
from_end: !exact_size,
|
||||
},
|
||||
);
|
||||
let subslice = place.clone().project(ProjectionElem::Subslice {
|
||||
from: prefix.len() as u64,
|
||||
to: if exact_size { min_length - suffix_len } else { suffix_len },
|
||||
from_end: !exact_size,
|
||||
});
|
||||
match_pairs.push(MatchPair::new(subslice, subslice_pat));
|
||||
}
|
||||
|
||||
@ -62,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
min_length,
|
||||
from_end: !exact_size,
|
||||
};
|
||||
let place = tcx.mk_place_elem(*place, elem);
|
||||
let place = place.clone().project(elem);
|
||||
MatchPair::new(place, subpattern)
|
||||
}));
|
||||
}
|
||||
@ -91,7 +95,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||
crate fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
|
||||
crate fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
|
||||
MatchPair { place, pattern }
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::build;
|
||||
use crate::build::expr::as_place::PlaceBuilder;
|
||||
use crate::build::scope::DropKind;
|
||||
use crate::thir::{build_thir, Arena, BindingMode, Expr, LintLevel, Pat, PatKind};
|
||||
use rustc_attr::{self as attr, UnwindAttr};
|
||||
@ -1004,7 +1005,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
matches::ArmHasGuard(false),
|
||||
Some((Some(&place), span)),
|
||||
);
|
||||
unpack!(block = self.place_into_pattern(block, pattern, place, false));
|
||||
let place_builder = PlaceBuilder::from(local);
|
||||
unpack!(
|
||||
block = self.place_into_pattern(block, pattern, place_builder, false)
|
||||
);
|
||||
}
|
||||
}
|
||||
self.source_scope = original_source_scope;
|
||||
|
Loading…
Reference in New Issue
Block a user