Rollup merge of #136610 - Jarcho:range_idx, r=Noratrieb
Allow `IndexSlice` to be indexed by ranges. This comes with some annoyances as the index type can no longer inferred from indexing expressions. The biggest offender for this is `IndexVec::from_fn_n(|idx| ..., n)` where the index type won't be inferred from the call site or any index expressions inside the closure. My main use case for this is mapping a `Place` to `Range<Idx>` for value tracking where the range represents all the values the place contains.
This commit is contained in:
commit
6aa015ae9d
12 changed files with 144 additions and 42 deletions
|
@ -3,7 +3,7 @@ use std::iter;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_index::bit_set::DenseBitSet;
|
use rustc_index::bit_set::DenseBitSet;
|
||||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||||
use rustc_middle::mir::{UnwindTerminateReason, traversal};
|
use rustc_middle::mir::{Local, UnwindTerminateReason, traversal};
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
|
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
|
||||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
|
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
|
||||||
use rustc_middle::{bug, mir, span_bug};
|
use rustc_middle::{bug, mir, span_bug};
|
||||||
|
@ -240,7 +240,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
let local_values = {
|
let local_values = {
|
||||||
let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals);
|
let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals);
|
||||||
|
|
||||||
let mut allocate_local = |local| {
|
let mut allocate_local = |local: Local| {
|
||||||
let decl = &mir.local_decls[local];
|
let decl = &mir.local_decls[local];
|
||||||
let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
|
let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
|
||||||
assert!(!layout.ty.has_erasable_regions());
|
assert!(!layout.ty.has_erasable_regions());
|
||||||
|
|
|
@ -147,7 +147,7 @@ impl<I: Idx, K: Ord, V> FromIterator<(K, V)> for SortedIndexMultiMap<I, K, V> {
|
||||||
where
|
where
|
||||||
J: IntoIterator<Item = (K, V)>,
|
J: IntoIterator<Item = (K, V)>,
|
||||||
{
|
{
|
||||||
let items = IndexVec::from_iter(iter);
|
let items = IndexVec::<I, _>::from_iter(iter);
|
||||||
let mut idx_sorted_by_item_key: Vec<_> = items.indices().collect();
|
let mut idx_sorted_by_item_key: Vec<_> = items.indices().collect();
|
||||||
|
|
||||||
// `sort_by_key` is stable, so insertion order is preserved for duplicate items.
|
// `sort_by_key` is stable, so insertion order is preserved for duplicate items.
|
||||||
|
|
|
@ -22,6 +22,12 @@ impl ExpectedIdx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ProvidedIdx {
|
||||||
|
pub(crate) fn to_expected_idx(self) -> ExpectedIdx {
|
||||||
|
ExpectedIdx::from_u32(self.as_u32())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// An issue that might be found in the compatibility matrix
|
// An issue that might be found in the compatibility matrix
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Issue {
|
enum Issue {
|
||||||
|
|
|
@ -775,7 +775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
// First, check if we just need to wrap some arguments in a tuple.
|
// First, check if we just need to wrap some arguments in a tuple.
|
||||||
if let Some((mismatch_idx, terr)) =
|
if let Some((mismatch_idx, terr)) =
|
||||||
compatibility_diagonal.iter().enumerate().find_map(|(i, c)| {
|
compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
|
||||||
if let Compatibility::Incompatible(Some(terr)) = c {
|
if let Compatibility::Incompatible(Some(terr)) = c {
|
||||||
Some((i, *terr))
|
Some((i, *terr))
|
||||||
} else {
|
} else {
|
||||||
|
@ -787,24 +787,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Do we have as many extra provided arguments as the tuple's length?
|
// Do we have as many extra provided arguments as the tuple's length?
|
||||||
// If so, we might have just forgotten to wrap some args in a tuple.
|
// If so, we might have just forgotten to wrap some args in a tuple.
|
||||||
if let Some(ty::Tuple(tys)) =
|
if let Some(ty::Tuple(tys)) =
|
||||||
formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
|
formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
|
||||||
// If the tuple is unit, we're not actually wrapping any arguments.
|
// If the tuple is unit, we're not actually wrapping any arguments.
|
||||||
&& !tys.is_empty()
|
&& !tys.is_empty()
|
||||||
&& provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
|
&& provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
|
||||||
{
|
{
|
||||||
// Wrap up the N provided arguments starting at this position in a tuple.
|
// Wrap up the N provided arguments starting at this position in a tuple.
|
||||||
let provided_as_tuple = Ty::new_tup_from_iter(
|
let provided_args_to_tuple = &provided_arg_tys[mismatch_idx..];
|
||||||
tcx,
|
let (provided_args_to_tuple, provided_args_after_tuple) =
|
||||||
provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()),
|
provided_args_to_tuple.split_at(tys.len());
|
||||||
);
|
let provided_as_tuple =
|
||||||
|
Ty::new_tup_from_iter(tcx, provided_args_to_tuple.iter().map(|&(ty, _)| ty));
|
||||||
|
|
||||||
let mut satisfied = true;
|
let mut satisfied = true;
|
||||||
// Check if the newly wrapped tuple + rest of the arguments are compatible.
|
// Check if the newly wrapped tuple + rest of the arguments are compatible.
|
||||||
for ((_, expected_ty), provided_ty) in std::iter::zip(
|
for ((_, expected_ty), provided_ty) in std::iter::zip(
|
||||||
formal_and_expected_inputs.iter().skip(mismatch_idx),
|
formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
|
||||||
[provided_as_tuple].into_iter().chain(
|
[provided_as_tuple]
|
||||||
provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
|
.into_iter()
|
||||||
),
|
.chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
|
||||||
) {
|
) {
|
||||||
if !self.may_coerce(provided_ty, *expected_ty) {
|
if !self.may_coerce(provided_ty, *expected_ty) {
|
||||||
satisfied = false;
|
satisfied = false;
|
||||||
|
@ -816,10 +817,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// Take some care with spans, so we don't suggest wrapping a macro's
|
// Take some care with spans, so we don't suggest wrapping a macro's
|
||||||
// innards in parenthesis, for example.
|
// innards in parenthesis, for example.
|
||||||
if satisfied
|
if satisfied
|
||||||
&& let Some((_, lo)) =
|
&& let &[(_, hi @ lo)] | &[(_, lo), .., (_, hi)] = provided_args_to_tuple
|
||||||
provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx))
|
|
||||||
&& let Some((_, hi)) =
|
|
||||||
provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx + tys.len() - 1))
|
|
||||||
{
|
{
|
||||||
let mut err;
|
let mut err;
|
||||||
if tys.len() == 1 {
|
if tys.len() == 1 {
|
||||||
|
@ -827,9 +825,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// so don't do anything special here.
|
// so don't do anything special here.
|
||||||
err = self.err_ctxt().report_and_explain_type_error(
|
err = self.err_ctxt().report_and_explain_type_error(
|
||||||
mk_trace(
|
mk_trace(
|
||||||
*lo,
|
lo,
|
||||||
formal_and_expected_inputs[mismatch_idx.into()],
|
formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
|
||||||
provided_arg_tys[mismatch_idx.into()].0,
|
provided_arg_tys[mismatch_idx].0,
|
||||||
),
|
),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
terr,
|
terr,
|
||||||
|
@ -868,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
callee_ty,
|
callee_ty,
|
||||||
call_expr,
|
call_expr,
|
||||||
None,
|
None,
|
||||||
Some(mismatch_idx),
|
Some(mismatch_idx.as_usize()),
|
||||||
&matched_inputs,
|
&matched_inputs,
|
||||||
&formal_and_expected_inputs,
|
&formal_and_expected_inputs,
|
||||||
is_method,
|
is_method,
|
||||||
|
@ -2615,7 +2613,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let expected_display_type = self
|
let expected_display_type = self
|
||||||
.resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
|
.resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
|
||||||
.sort_string(self.tcx);
|
.sort_string(self.tcx);
|
||||||
let label = if idxs_matched == params_with_generics.len() - 1 {
|
let label = if idxs_matched == params_with_generics.len() - 1 {
|
||||||
format!(
|
format!(
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::ops;
|
||||||
|
use std::slice::SliceIndex;
|
||||||
|
|
||||||
/// Represents some newtyped `usize` wrapper.
|
/// Represents some newtyped `usize` wrapper.
|
||||||
///
|
///
|
||||||
|
@ -43,3 +45,92 @@ impl Idx for u32 {
|
||||||
self as usize
|
self as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper trait for indexing operations with a custom index type.
|
||||||
|
pub trait IntoSliceIdx<I, T: ?Sized> {
|
||||||
|
type Output: SliceIndex<T>;
|
||||||
|
fn into_slice_idx(self) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for I {
|
||||||
|
type Output = usize;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
self.index()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, T> IntoSliceIdx<I, [T]> for ops::RangeFull {
|
||||||
|
type Output = ops::RangeFull;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::Range<I> {
|
||||||
|
type Output = ops::Range<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
ops::Range { start: self.start.index(), end: self.end.index() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeFrom<I> {
|
||||||
|
type Output = ops::RangeFrom<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
ops::RangeFrom { start: self.start.index() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeTo<I> {
|
||||||
|
type Output = ops::RangeTo<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
..self.end.index()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeInclusive<I> {
|
||||||
|
type Output = ops::RangeInclusive<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
ops::RangeInclusive::new(self.start().index(), self.end().index())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeToInclusive<I> {
|
||||||
|
type Output = ops::RangeToInclusive<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
..=self.end.index()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "nightly")]
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::Range<I> {
|
||||||
|
type Output = core::range::Range<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
core::range::Range { start: self.start.index(), end: self.end.index() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "nightly")]
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeFrom<I> {
|
||||||
|
type Output = core::range::RangeFrom<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
core::range::RangeFrom { start: self.start.index() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "nightly")]
|
||||||
|
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
|
||||||
|
type Output = core::range::RangeInclusive<usize>;
|
||||||
|
#[inline]
|
||||||
|
fn into_slice_idx(self) -> Self::Output {
|
||||||
|
core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))]
|
#![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))]
|
||||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||||
#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))]
|
#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))]
|
||||||
|
#![cfg_attr(feature = "nightly", feature(new_range_api))]
|
||||||
#![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))]
|
#![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))]
|
||||||
#![warn(unreachable_pub)]
|
#![warn(unreachable_pub)]
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
|
@ -14,7 +15,7 @@ mod idx;
|
||||||
mod slice;
|
mod slice;
|
||||||
mod vec;
|
mod vec;
|
||||||
|
|
||||||
pub use idx::Idx;
|
pub use idx::{Idx, IntoSliceIdx};
|
||||||
pub use rustc_index_macros::newtype_index;
|
pub use rustc_index_macros::newtype_index;
|
||||||
pub use slice::IndexSlice;
|
pub use slice::IndexSlice;
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::{fmt, slice};
|
use std::slice::{self, SliceIndex};
|
||||||
|
|
||||||
use crate::{Idx, IndexVec};
|
use crate::{Idx, IndexVec, IntoSliceIdx};
|
||||||
|
|
||||||
/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
|
/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
|
||||||
///
|
///
|
||||||
|
@ -97,13 +98,19 @@ impl<I: Idx, T> IndexSlice<I, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get(&self, index: I) -> Option<&T> {
|
pub fn get<R: IntoSliceIdx<I, [T]>>(
|
||||||
self.raw.get(index.index())
|
&self,
|
||||||
|
index: R,
|
||||||
|
) -> Option<&<R::Output as SliceIndex<[T]>>::Output> {
|
||||||
|
self.raw.get(index.into_slice_idx())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
|
pub fn get_mut<R: IntoSliceIdx<I, [T]>>(
|
||||||
self.raw.get_mut(index.index())
|
&mut self,
|
||||||
|
index: R,
|
||||||
|
) -> Option<&mut <R::Output as SliceIndex<[T]>>::Output> {
|
||||||
|
self.raw.get_mut(index.into_slice_idx())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns mutable references to two distinct elements, `a` and `b`.
|
/// Returns mutable references to two distinct elements, `a` and `b`.
|
||||||
|
@ -184,19 +191,19 @@ impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
|
impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> Index<R> for IndexSlice<I, T> {
|
||||||
type Output = T;
|
type Output = <R::Output as SliceIndex<[T]>>::Output;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: I) -> &T {
|
fn index(&self, index: R) -> &Self::Output {
|
||||||
&self.raw[index.index()]
|
&self.raw[index.into_slice_idx()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
|
impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> IndexMut<R> for IndexSlice<I, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index_mut(&mut self, index: I) -> &mut T {
|
fn index_mut(&mut self, index: R) -> &mut Self::Output {
|
||||||
&mut self.raw[index.index()]
|
&mut self.raw[index.into_slice_idx()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||||
/// empty region. The `expansion` phase will grow this larger.
|
/// empty region. The `expansion` phase will grow this larger.
|
||||||
fn construct_var_data(&self) -> LexicalRegionResolutions<'tcx> {
|
fn construct_var_data(&self) -> LexicalRegionResolutions<'tcx> {
|
||||||
LexicalRegionResolutions {
|
LexicalRegionResolutions {
|
||||||
values: IndexVec::from_fn_n(
|
values: IndexVec::<RegionVid, _>::from_fn_n(
|
||||||
|vid| {
|
|vid| {
|
||||||
let vid_universe = self.var_infos[vid].universe;
|
let vid_universe = self.var_infos[vid].universe;
|
||||||
VarValue::Empty(vid_universe)
|
VarValue::Empty(vid_universe)
|
||||||
|
|
|
@ -71,8 +71,7 @@ pub(crate) fn check_pointers<'tcx, F>(
|
||||||
// statements/blocks after. Iterating or visiting the MIR in order would require updating
|
// statements/blocks after. Iterating or visiting the MIR in order would require updating
|
||||||
// our current location after every insertion. By iterating backwards, we dodge this issue:
|
// our current location after every insertion. By iterating backwards, we dodge this issue:
|
||||||
// The only Locations that an insertion changes have already been handled.
|
// The only Locations that an insertion changes have already been handled.
|
||||||
for block in (0..basic_blocks.len()).rev() {
|
for block in basic_blocks.indices().rev() {
|
||||||
let block = block.into();
|
|
||||||
for statement_index in (0..basic_blocks[block].statements.len()).rev() {
|
for statement_index in (0..basic_blocks[block].statements.len()).rev() {
|
||||||
let location = Location { block, statement_index };
|
let location = Location { block, statement_index };
|
||||||
let statement = &basic_blocks[block].statements[statement_index];
|
let statement = &basic_blocks[block].statements[statement_index];
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn make_node_flow_priority_list(
|
||||||
// A "reloop" node has exactly one out-edge, which jumps back to the top
|
// A "reloop" node has exactly one out-edge, which jumps back to the top
|
||||||
// of an enclosing loop. Reloop nodes are typically visited more times
|
// of an enclosing loop. Reloop nodes are typically visited more times
|
||||||
// than loop-exit nodes, so try to avoid giving them physical counters.
|
// than loop-exit nodes, so try to avoid giving them physical counters.
|
||||||
let is_reloop_node = IndexVec::from_fn_n(
|
let is_reloop_node = IndexVec::<BasicCoverageBlock, _>::from_fn_n(
|
||||||
|node| match graph.successors[node].as_slice() {
|
|node| match graph.successors[node].as_slice() {
|
||||||
&[succ] => graph.dominates(succ, node),
|
&[succ] => graph.dominates(succ, node),
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl CoverageGraph {
|
||||||
// `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so
|
// `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so
|
||||||
// de-duplication is required. This is done without reordering the successors.
|
// de-duplication is required. This is done without reordering the successors.
|
||||||
|
|
||||||
let successors = IndexVec::from_fn_n(
|
let successors = IndexVec::<BasicCoverageBlock, _>::from_fn_n(
|
||||||
|bcb| {
|
|bcb| {
|
||||||
let mut seen_bcbs = FxHashSet::default();
|
let mut seen_bcbs = FxHashSet::default();
|
||||||
let terminator = mir_body[bcbs[bcb].last_bb()].terminator();
|
let terminator = mir_body[bcbs[bcb].last_bb()].terminator();
|
||||||
|
|
|
@ -1259,7 +1259,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||||
|
|
||||||
let layout = self.ecx.layout_of(lhs_ty).ok()?;
|
let layout = self.ecx.layout_of(lhs_ty).ok()?;
|
||||||
|
|
||||||
let as_bits = |value| {
|
let as_bits = |value: VnIndex| {
|
||||||
let constant = self.evaluated[value].as_ref()?;
|
let constant = self.evaluated[value].as_ref()?;
|
||||||
if layout.backend_repr.is_scalar() {
|
if layout.backend_repr.is_scalar() {
|
||||||
let scalar = self.ecx.read_scalar(constant).discard_err()?;
|
let scalar = self.ecx.read_scalar(constant).discard_err()?;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue