Skip to content

Commit 8705084

Browse files
committed
Allow SliceIndex to be indexed by ranges.
1 parent 820bfff commit 8705084

File tree

12 files changed

+145
-41
lines changed

12 files changed

+145
-41
lines changed

compiler/rustc_codegen_ssa/src/mir/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::iter;
33
use rustc_index::IndexVec;
44
use rustc_index::bit_set::DenseBitSet;
55
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
6-
use rustc_middle::mir::{UnwindTerminateReason, traversal};
6+
use rustc_middle::mir::{Local, UnwindTerminateReason, traversal};
77
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout};
88
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
99
use rustc_middle::{bug, mir, span_bug};
@@ -240,7 +240,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
240240
let local_values = {
241241
let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals);
242242

243-
let mut allocate_local = |local| {
243+
let mut allocate_local = |local: Local| {
244244
let decl = &mir.local_decls[local];
245245
let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
246246
assert!(!layout.ty.has_erasable_regions());

compiler/rustc_data_structures/src/sorted_map/index_map.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl<I: Idx, K: Ord, V> FromIterator<(K, V)> for SortedIndexMultiMap<I, K, V> {
147147
where
148148
J: IntoIterator<Item = (K, V)>,
149149
{
150-
let items = IndexVec::from_iter(iter);
150+
let items = IndexVec::<I, _>::from_iter(iter);
151151
let mut idx_sorted_by_item_key: Vec<_> = items.indices().collect();
152152

153153
// `sort_by_key` is stable, so insertion order is preserved for duplicate items.

compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ impl ExpectedIdx {
2222
}
2323
}
2424

25+
impl ProvidedIdx {
26+
pub(crate) fn to_expected_idx(self) -> ExpectedIdx {
27+
ExpectedIdx::from_u32(self.as_u32())
28+
}
29+
}
30+
2531
// An issue that might be found in the compatibility matrix
2632
#[derive(Debug)]
2733
enum Issue {

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
773773

774774
// First, check if we just need to wrap some arguments in a tuple.
775775
if let Some((mismatch_idx, terr)) =
776-
compatibility_diagonal.iter().enumerate().find_map(|(i, c)| {
776+
compatibility_diagonal.iter_enumerated().find_map(|(i, c)| {
777777
if let Compatibility::Incompatible(Some(terr)) = c {
778778
Some((i, *terr))
779779
} else {
@@ -785,24 +785,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
785785
// Do we have as many extra provided arguments as the tuple's length?
786786
// If so, we might have just forgotten to wrap some args in a tuple.
787787
if let Some(ty::Tuple(tys)) =
788-
formal_and_expected_inputs.get(mismatch_idx.into()).map(|tys| tys.1.kind())
788+
formal_and_expected_inputs.get(mismatch_idx.to_expected_idx()).map(|tys| tys.1.kind())
789789
// If the tuple is unit, we're not actually wrapping any arguments.
790790
&& !tys.is_empty()
791791
&& provided_arg_tys.len() == formal_and_expected_inputs.len() - 1 + tys.len()
792792
{
793793
// Wrap up the N provided arguments starting at this position in a tuple.
794-
let provided_as_tuple = Ty::new_tup_from_iter(
795-
tcx,
796-
provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx).take(tys.len()),
797-
);
794+
let provided_args_to_tuple = &provided_arg_tys[mismatch_idx..].raw;
795+
let (provided_args_to_tuple, provided_args_after_tuple) =
796+
provided_arg_tys.split_at(tys.len());
797+
let provided_as_tuple =
798+
Ty::new_tup_from_iter(tcx, provided_args_to_tuple.iter().map(|&(ty, _)| ty));
798799

799800
let mut satisfied = true;
800801
// Check if the newly wrapped tuple + rest of the arguments are compatible.
801802
for ((_, expected_ty), provided_ty) in std::iter::zip(
802-
formal_and_expected_inputs.iter().skip(mismatch_idx),
803-
[provided_as_tuple].into_iter().chain(
804-
provided_arg_tys.iter().map(|(ty, _)| *ty).skip(mismatch_idx + tys.len()),
805-
),
803+
formal_and_expected_inputs[mismatch_idx.to_expected_idx()..].iter(),
804+
[provided_as_tuple]
805+
.into_iter()
806+
.chain(provided_args_after_tuple.iter().map(|&(ty, _)| ty)),
806807
) {
807808
if !self.may_coerce(provided_ty, *expected_ty) {
808809
satisfied = false;
@@ -814,10 +815,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
814815
// Take some care with spans, so we don't suggest wrapping a macro's
815816
// innards in parenthesis, for example.
816817
if satisfied
817-
&& let Some((_, lo)) =
818-
provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx))
819-
&& let Some((_, hi)) =
820-
provided_arg_tys.get(ProvidedIdx::from_usize(mismatch_idx + tys.len() - 1))
818+
&& let Some((_, lo)) = provided_arg_tys.get(mismatch_idx)
819+
// Note: `provided_args_to_tuple` is not empty since `tys` is also not empty
820+
&& let Some(&(_, hi)) = provided_args_to_tuple.last()
821821
{
822822
let mut err;
823823
if tys.len() == 1 {
@@ -826,8 +826,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
826826
err = self.err_ctxt().report_and_explain_type_error(
827827
mk_trace(
828828
*lo,
829-
formal_and_expected_inputs[mismatch_idx.into()],
830-
provided_arg_tys[mismatch_idx.into()].0,
829+
formal_and_expected_inputs[mismatch_idx.to_expected_idx()],
830+
provided_arg_tys[mismatch_idx].0,
831831
),
832832
self.param_env,
833833
terr,
@@ -866,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
866866
callee_ty,
867867
call_expr,
868868
None,
869-
Some(mismatch_idx),
869+
Some(mismatch_idx.as_usize()),
870870
&matched_inputs,
871871
&formal_and_expected_inputs,
872872
is_method,
@@ -2648,7 +2648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26482648
}
26492649

26502650
let expected_display_type = self
2651-
.resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1)
2651+
.resolve_vars_if_possible(formal_and_expected_inputs[idx].1)
26522652
.sort_string(self.tcx);
26532653
let label = if idxs_matched == params_with_generics.len() - 1 {
26542654
format!(

compiler/rustc_index/src/idx.rs

+91
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::fmt::Debug;
22
use std::hash::Hash;
3+
use std::ops;
4+
use std::slice::SliceIndex;
35

46
/// Represents some newtyped `usize` wrapper.
57
///
@@ -43,3 +45,92 @@ impl Idx for u32 {
4345
self as usize
4446
}
4547
}
48+
49+
/// Helper trait for indexing operations with a custom index type.
50+
pub trait IntoSliceIdx<I, T: ?Sized> {
51+
type Output: SliceIndex<T>;
52+
fn into_slice_idx(self) -> Self::Output;
53+
}
54+
55+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for I {
56+
type Output = usize;
57+
#[inline]
58+
fn into_slice_idx(self) -> Self::Output {
59+
self.index()
60+
}
61+
}
62+
63+
impl<I, T> IntoSliceIdx<I, [T]> for ops::RangeFull {
64+
type Output = ops::RangeFull;
65+
#[inline]
66+
fn into_slice_idx(self) -> Self::Output {
67+
self
68+
}
69+
}
70+
71+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::Range<I> {
72+
type Output = ops::Range<usize>;
73+
#[inline]
74+
fn into_slice_idx(self) -> Self::Output {
75+
ops::Range { start: self.start.index(), end: self.end.index() }
76+
}
77+
}
78+
79+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeFrom<I> {
80+
type Output = ops::RangeFrom<usize>;
81+
#[inline]
82+
fn into_slice_idx(self) -> Self::Output {
83+
ops::RangeFrom { start: self.start.index() }
84+
}
85+
}
86+
87+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeTo<I> {
88+
type Output = ops::RangeTo<usize>;
89+
#[inline]
90+
fn into_slice_idx(self) -> Self::Output {
91+
..self.end.index()
92+
}
93+
}
94+
95+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeInclusive<I> {
96+
type Output = ops::RangeInclusive<usize>;
97+
#[inline]
98+
fn into_slice_idx(self) -> Self::Output {
99+
ops::RangeInclusive::new(self.start().index(), self.end().index())
100+
}
101+
}
102+
103+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for ops::RangeToInclusive<I> {
104+
type Output = ops::RangeToInclusive<usize>;
105+
#[inline]
106+
fn into_slice_idx(self) -> Self::Output {
107+
..=self.end.index()
108+
}
109+
}
110+
111+
#[cfg(feature = "nightly")]
112+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::Range<I> {
113+
type Output = core::range::Range<usize>;
114+
#[inline]
115+
fn into_slice_idx(self) -> Self::Output {
116+
core::range::Range { start: self.start.index(), end: self.end.index() }
117+
}
118+
}
119+
120+
#[cfg(feature = "nightly")]
121+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeFrom<I> {
122+
type Output = core::range::RangeFrom<usize>;
123+
#[inline]
124+
fn into_slice_idx(self) -> Self::Output {
125+
core::range::RangeFrom { start: self.start.index() }
126+
}
127+
}
128+
129+
#[cfg(feature = "nightly")]
130+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
131+
type Output = core::range::RangeInclusive<usize>;
132+
#[inline]
133+
fn into_slice_idx(self) -> Self::Output {
134+
core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
135+
}
136+
}

compiler/rustc_index/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))]
33
#![cfg_attr(feature = "nightly", allow(internal_features))]
44
#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))]
5+
#![cfg_attr(feature = "nightly", feature(new_range_api))]
56
#![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))]
67
#![warn(unreachable_pub)]
78
// tidy-alphabetical-end
@@ -14,7 +15,7 @@ mod idx;
1415
mod slice;
1516
mod vec;
1617

17-
pub use idx::Idx;
18+
pub use idx::{Idx, IntoSliceIdx};
1819
pub use rustc_index_macros::newtype_index;
1920
pub use slice::IndexSlice;
2021
#[doc(no_inline)]

compiler/rustc_index/src/slice.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
use std::fmt;
12
use std::marker::PhantomData;
23
use std::ops::{Index, IndexMut};
3-
use std::{fmt, slice};
4+
use std::slice::{self, SliceIndex};
45

5-
use crate::{Idx, IndexVec};
6+
use crate::{Idx, IndexVec, IntoSliceIdx};
67

78
/// A view into contiguous `T`s, indexed by `I` rather than by `usize`.
89
///
@@ -99,13 +100,19 @@ impl<I: Idx, T> IndexSlice<I, T> {
99100
}
100101

101102
#[inline]
102-
pub fn get(&self, index: I) -> Option<&T> {
103-
self.raw.get(index.index())
103+
pub fn get<R: IntoSliceIdx<I, [T]>>(
104+
&self,
105+
index: R,
106+
) -> Option<&<R::Output as SliceIndex<[T]>>::Output> {
107+
self.raw.get(index.into_slice_idx())
104108
}
105109

106110
#[inline]
107-
pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
108-
self.raw.get_mut(index.index())
111+
pub fn get_mut<R: IntoSliceIdx<I, [T]>>(
112+
&mut self,
113+
index: R,
114+
) -> Option<&mut <R::Output as SliceIndex<[T]>>::Output> {
115+
self.raw.get_mut(index.into_slice_idx())
109116
}
110117

111118
/// Returns mutable references to two distinct elements, `a` and `b`.
@@ -186,19 +193,19 @@ impl<I: Idx, T: fmt::Debug> fmt::Debug for IndexSlice<I, T> {
186193
}
187194
}
188195

189-
impl<I: Idx, T> Index<I> for IndexSlice<I, T> {
190-
type Output = T;
196+
impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> Index<R> for IndexSlice<I, T> {
197+
type Output = <R::Output as SliceIndex<[T]>>::Output;
191198

192199
#[inline]
193-
fn index(&self, index: I) -> &T {
194-
&self.raw[index.index()]
200+
fn index(&self, index: R) -> &Self::Output {
201+
&self.raw[index.into_slice_idx()]
195202
}
196203
}
197204

198-
impl<I: Idx, T> IndexMut<I> for IndexSlice<I, T> {
205+
impl<I: Idx, T, R: IntoSliceIdx<I, [T]>> IndexMut<R> for IndexSlice<I, T> {
199206
#[inline]
200-
fn index_mut(&mut self, index: I) -> &mut T {
201-
&mut self.raw[index.index()]
207+
fn index_mut(&mut self, index: R) -> &mut Self::Output {
208+
&mut self.raw[index.into_slice_idx()]
202209
}
203210
}
204211

compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
160160
/// empty region. The `expansion` phase will grow this larger.
161161
fn construct_var_data(&self) -> LexicalRegionResolutions<'tcx> {
162162
LexicalRegionResolutions {
163-
values: IndexVec::from_fn_n(
163+
values: IndexVec::<RegionVid, _>::from_fn_n(
164164
|vid| {
165165
let vid_universe = self.var_infos[vid].universe;
166166
VarValue::Empty(vid_universe)

compiler/rustc_mir_transform/src/check_pointers.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ pub(crate) fn check_pointers<'a, 'tcx, F>(
7070
// statements/blocks after. Iterating or visiting the MIR in order would require updating
7171
// our current location after every insertion. By iterating backwards, we dodge this issue:
7272
// The only Locations that an insertion changes have already been handled.
73-
for block in (0..basic_blocks.len()).rev() {
74-
let block = block.into();
73+
for block in basic_blocks.indices().rev() {
7574
for statement_index in (0..basic_blocks[block].statements.len()).rev() {
7675
let location = Location { block, statement_index };
7776
let statement = &basic_blocks[block].statements[statement_index];

compiler/rustc_mir_transform/src/coverage/counters.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn make_node_flow_priority_list(
4747
// A "reloop" node has exactly one out-edge, which jumps back to the top
4848
// of an enclosing loop. Reloop nodes are typically visited more times
4949
// than loop-exit nodes, so try to avoid giving them physical counters.
50-
let is_reloop_node = IndexVec::from_fn_n(
50+
let is_reloop_node = IndexVec::<BasicCoverageBlock, _>::from_fn_n(
5151
|node| match graph.successors[node].as_slice() {
5252
&[succ] => graph.dominates(succ, node),
5353
_ => false,

compiler/rustc_mir_transform/src/coverage/graph.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl CoverageGraph {
4242
// `SwitchInt` to have multiple targets to the same destination `BasicBlock`, so
4343
// de-duplication is required. This is done without reordering the successors.
4444

45-
let successors = IndexVec::from_fn_n(
45+
let successors = IndexVec::<BasicCoverageBlock, _>::from_fn_n(
4646
|bcb| {
4747
let mut seen_bcbs = FxHashSet::default();
4848
let terminator = mir_body[bcbs[bcb].last_bb()].terminator();

compiler/rustc_mir_transform/src/gvn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1259,7 +1259,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
12591259

12601260
let layout = self.ecx.layout_of(lhs_ty).ok()?;
12611261

1262-
let as_bits = |value| {
1262+
let as_bits = |value: VnIndex| {
12631263
let constant = self.evaluated[value].as_ref()?;
12641264
if layout.backend_repr.is_scalar() {
12651265
let scalar = self.ecx.read_scalar(constant).discard_err()?;

0 commit comments

Comments
 (0)