rustc_mir_build: use IndexMap in TestKind::SwitchInt
This commit is contained in:
parent
c61f1c8bfa
commit
4efc7e92fa
2 changed files with 17 additions and 23 deletions
|
@ -11,7 +11,7 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||||
use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
|
use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
|
||||||
use crate::thir::{self, *};
|
use crate::thir::{self, *};
|
||||||
use rustc_data_structures::{
|
use rustc_data_structures::{
|
||||||
fx::{FxHashMap, FxHashSet},
|
fx::{FxHashSet, FxIndexMap},
|
||||||
stack::ensure_sufficient_stack,
|
stack::ensure_sufficient_stack,
|
||||||
};
|
};
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
|
@ -817,9 +817,7 @@ enum TestKind<'tcx> {
|
||||||
///
|
///
|
||||||
/// For `bool` we always generate two edges, one for `true` and one for
|
/// For `bool` we always generate two edges, one for `true` and one for
|
||||||
/// `false`.
|
/// `false`.
|
||||||
options: Vec<u128>,
|
options: FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
|
||||||
/// Reverse map used to ensure that the values in `options` are unique.
|
|
||||||
indices: FxHashMap<&'tcx ty::Const<'tcx>, usize>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Test for equality with value, possibly after an unsizing coercion to
|
/// Test for equality with value, possibly after an unsizing coercion to
|
||||||
|
@ -1396,14 +1394,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// may want to add cases based on the candidates that are
|
// may want to add cases based on the candidates that are
|
||||||
// available
|
// available
|
||||||
match test.kind {
|
match test.kind {
|
||||||
TestKind::SwitchInt { switch_ty, ref mut options, ref mut indices } => {
|
TestKind::SwitchInt { switch_ty, ref mut options } => {
|
||||||
for candidate in candidates.iter() {
|
for candidate in candidates.iter() {
|
||||||
if !self.add_cases_to_switch(
|
if !self.add_cases_to_switch(
|
||||||
&match_place,
|
&match_place,
|
||||||
candidate,
|
candidate,
|
||||||
switch_ty,
|
switch_ty,
|
||||||
options,
|
options,
|
||||||
indices,
|
|
||||||
) {
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::build::matches::{Candidate, MatchPair, Test, TestKind};
|
||||||
use crate::build::Builder;
|
use crate::build::Builder;
|
||||||
use crate::thir::pattern::compare_const_vals;
|
use crate::thir::pattern::compare_const_vals;
|
||||||
use crate::thir::*;
|
use crate::thir::*;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
use rustc_hir::RangeEnd;
|
use rustc_hir::RangeEnd;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
|
@ -44,8 +44,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
// these maps are empty to start; cases are
|
// these maps are empty to start; cases are
|
||||||
// added below in add_cases_to_switch
|
// added below in add_cases_to_switch
|
||||||
options: vec![],
|
options: Default::default(),
|
||||||
indices: Default::default(),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,8 +82,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
test_place: &Place<'tcx>,
|
test_place: &Place<'tcx>,
|
||||||
candidate: &Candidate<'pat, 'tcx>,
|
candidate: &Candidate<'pat, 'tcx>,
|
||||||
switch_ty: Ty<'tcx>,
|
switch_ty: Ty<'tcx>,
|
||||||
options: &mut Vec<u128>,
|
options: &mut FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
|
||||||
indices: &mut FxHashMap<&'tcx ty::Const<'tcx>, usize>,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
|
||||||
Some(match_pair) => match_pair,
|
Some(match_pair) => match_pair,
|
||||||
|
@ -95,9 +93,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
match *match_pair.pattern.kind {
|
match *match_pair.pattern.kind {
|
||||||
PatKind::Constant { value } => {
|
PatKind::Constant { value } => {
|
||||||
indices.entry(value).or_insert_with(|| {
|
options.entry(value).or_insert_with(|| {
|
||||||
options.push(value.eval_bits(self.hir.tcx(), self.hir.param_env, switch_ty));
|
value.eval_bits(self.hir.tcx(), self.hir.param_env, switch_ty)
|
||||||
options.len() - 1
|
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -106,7 +103,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
PatKind::Range(range) => {
|
PatKind::Range(range) => {
|
||||||
// Check that none of the switch values are in the range.
|
// Check that none of the switch values are in the range.
|
||||||
self.values_not_contained_in_range(range, indices).unwrap_or(false)
|
self.values_not_contained_in_range(range, options).unwrap_or(false)
|
||||||
}
|
}
|
||||||
PatKind::Slice { .. }
|
PatKind::Slice { .. }
|
||||||
| PatKind::Array { .. }
|
| PatKind::Array { .. }
|
||||||
|
@ -216,7 +213,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TestKind::SwitchInt { switch_ty, ref options, indices: _ } => {
|
TestKind::SwitchInt { switch_ty, ref options } => {
|
||||||
let target_blocks = make_target_blocks(self);
|
let target_blocks = make_target_blocks(self);
|
||||||
let terminator = if switch_ty.kind == ty::Bool {
|
let terminator = if switch_ty.kind == ty::Bool {
|
||||||
assert!(!options.is_empty() && options.len() <= 2);
|
assert!(!options.is_empty() && options.len() <= 2);
|
||||||
|
@ -236,7 +233,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
TerminatorKind::SwitchInt {
|
TerminatorKind::SwitchInt {
|
||||||
discr: Operand::Copy(place),
|
discr: Operand::Copy(place),
|
||||||
switch_ty,
|
switch_ty,
|
||||||
values: options.clone().into(),
|
values: options.values().copied().collect(),
|
||||||
targets: target_blocks,
|
targets: target_blocks,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -532,20 +529,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// FIXME(#29623) we could use PatKind::Range to rule
|
// FIXME(#29623) we could use PatKind::Range to rule
|
||||||
// things out here, in some cases.
|
// things out here, in some cases.
|
||||||
(
|
(
|
||||||
&TestKind::SwitchInt { switch_ty: _, options: _, ref indices },
|
&TestKind::SwitchInt { switch_ty: _, ref options },
|
||||||
&PatKind::Constant { ref value },
|
&PatKind::Constant { ref value },
|
||||||
) if is_switch_ty(match_pair.pattern.ty) => {
|
) if is_switch_ty(match_pair.pattern.ty) => {
|
||||||
let index = indices[value];
|
let index = options.get_index_of(value).unwrap();
|
||||||
self.candidate_without_match_pair(match_pair_index, candidate);
|
self.candidate_without_match_pair(match_pair_index, candidate);
|
||||||
Some(index)
|
Some(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
(
|
||||||
&TestKind::SwitchInt { switch_ty: _, ref options, ref indices },
|
&TestKind::SwitchInt { switch_ty: _, ref options },
|
||||||
&PatKind::Range(range),
|
&PatKind::Range(range),
|
||||||
) => {
|
) => {
|
||||||
let not_contained =
|
let not_contained =
|
||||||
self.values_not_contained_in_range(range, indices).unwrap_or(false);
|
self.values_not_contained_in_range(range, options).unwrap_or(false);
|
||||||
|
|
||||||
if not_contained {
|
if not_contained {
|
||||||
// No switch values are contained in the pattern range,
|
// No switch values are contained in the pattern range,
|
||||||
|
@ -777,9 +774,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fn values_not_contained_in_range(
|
fn values_not_contained_in_range(
|
||||||
&self,
|
&self,
|
||||||
range: PatRange<'tcx>,
|
range: PatRange<'tcx>,
|
||||||
indices: &FxHashMap<&'tcx ty::Const<'tcx>, usize>,
|
options: &FxIndexMap<&'tcx ty::Const<'tcx>, u128>,
|
||||||
) -> Option<bool> {
|
) -> Option<bool> {
|
||||||
for &val in indices.keys() {
|
for &val in options.keys() {
|
||||||
if self.const_range_contains(range, val)? {
|
if self.const_range_contains(range, val)? {
|
||||||
return Some(false);
|
return Some(false);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue