Skip to content

Commit a4a7947

Browse files
committed
Auto merge of #49724 - kennytm:range-inc-start-end-methods, r=Kimundi
Introduce RangeInclusive::{new, start, end} methods and make the fields private. cc #49022
2 parents 0eb68b7 + f70b2eb commit a4a7947

File tree

18 files changed

+139
-54
lines changed

18 files changed

+139
-54
lines changed

src/liballoc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@
122122
#![feature(on_unimplemented)]
123123
#![feature(exact_chunks)]
124124
#![feature(pointer_methods)]
125-
#![feature(inclusive_range_fields)]
125+
#![feature(inclusive_range_methods)]
126126
#![cfg_attr(stage0, feature(generic_param_attrs))]
127127
#![feature(rustc_const_unstable)]
128128

src/liballoc/tests/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#![feature(try_reserve)]
2626
#![feature(unboxed_closures)]
2727
#![feature(exact_chunks)]
28-
#![feature(inclusive_range_fields)]
28+
#![feature(inclusive_range_methods)]
2929

3030
extern crate alloc_system;
3131
extern crate core;

src/libcore/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
#![feature(untagged_unions)]
103103
#![feature(unwind_attributes)]
104104
#![feature(doc_alias)]
105+
#![feature(inclusive_range_methods)]
105106

106107
#![cfg_attr(not(stage0), feature(mmx_target_feature))]
107108
#![cfg_attr(not(stage0), feature(tbm_target_feature))]

src/libcore/ops/range.rs

+76-2
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,9 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
318318
/// # Examples
319319
///
320320
/// ```
321-
/// #![feature(inclusive_range_fields)]
321+
/// #![feature(inclusive_range_methods)]
322322
///
323-
/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 });
323+
/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
324324
/// assert_eq!(3 + 4 + 5, (3..=5).sum());
325325
///
326326
/// let arr = [0, 1, 2, 3];
@@ -331,14 +331,88 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
331331
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
332332
#[stable(feature = "inclusive_range", since = "1.26.0")]
333333
pub struct RangeInclusive<Idx> {
334+
// FIXME: The current representation follows RFC 1980,
335+
// but it is known that LLVM is not able to optimize loops following that RFC.
336+
// Consider adding an extra `bool` field to indicate emptiness of the range.
337+
// See #45222 for performance test cases.
338+
#[cfg(not(stage0))]
339+
pub(crate) start: Idx,
340+
#[cfg(not(stage0))]
341+
pub(crate) end: Idx,
334342
/// The lower bound of the range (inclusive).
343+
#[cfg(stage0)]
335344
#[unstable(feature = "inclusive_range_fields", issue = "49022")]
336345
pub start: Idx,
337346
/// The upper bound of the range (inclusive).
347+
#[cfg(stage0)]
338348
#[unstable(feature = "inclusive_range_fields", issue = "49022")]
339349
pub end: Idx,
340350
}
341351

352+
impl<Idx> RangeInclusive<Idx> {
353+
/// Creates a new inclusive range. Equivalent to writing `start..=end`.
354+
///
355+
/// # Examples
356+
///
357+
/// ```
358+
/// #![feature(inclusive_range_methods)]
359+
/// use std::ops::RangeInclusive;
360+
///
361+
/// assert_eq!(3..=5, RangeInclusive::new(3, 5));
362+
/// ```
363+
#[unstable(feature = "inclusive_range_methods", issue = "49022")]
364+
#[inline]
365+
pub const fn new(start: Idx, end: Idx) -> Self {
366+
Self { start, end }
367+
}
368+
369+
/// Returns the lower bound of the range (inclusive).
370+
///
371+
/// When using an inclusive range for iteration, the values of `start()` and
372+
/// [`end()`] are unspecified after the iteration ended. To determine
373+
/// whether the inclusive range is empty, use the [`is_empty()`] method
374+
/// instead of comparing `start() > end()`.
375+
///
376+
/// [`end()`]: #method.end
377+
/// [`is_empty()`]: #method.is_empty
378+
///
379+
/// # Examples
380+
///
381+
/// ```
382+
/// #![feature(inclusive_range_methods)]
383+
///
384+
/// assert_eq!((3..=5).start(), &3);
385+
/// ```
386+
#[unstable(feature = "inclusive_range_methods", issue = "49022")]
387+
#[inline]
388+
pub fn start(&self) -> &Idx {
389+
&self.start
390+
}
391+
392+
/// Returns the upper bound of the range (inclusive).
393+
///
394+
/// When using an inclusive range for iteration, the values of [`start()`]
395+
/// and `end()` are unspecified after the iteration ended. To determine
396+
/// whether the inclusive range is empty, use the [`is_empty()`] method
397+
/// instead of comparing `start() > end()`.
398+
///
399+
/// [`start()`]: #method.start
400+
/// [`is_empty()`]: #method.is_empty
401+
///
402+
/// # Examples
403+
///
404+
/// ```
405+
/// #![feature(inclusive_range_methods)]
406+
///
407+
/// assert_eq!((3..=5).end(), &5);
408+
/// ```
409+
#[unstable(feature = "inclusive_range_methods", issue = "49022")]
410+
#[inline]
411+
pub fn end(&self) -> &Idx {
412+
&self.end
413+
}
414+
}
415+
342416
#[stable(feature = "inclusive_range", since = "1.26.0")]
343417
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
344418
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {

src/libcore/tests/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
#![feature(exact_chunks)]
4545
#![cfg_attr(stage0, feature(atomic_nand))]
4646
#![feature(reverse_bits)]
47-
#![feature(inclusive_range_fields)]
47+
#![feature(inclusive_range_methods)]
4848
#![feature(iterator_find_map)]
4949

5050
extern crate core;

src/libcore/tests/ops.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,21 @@ fn test_full_range() {
5050

5151
#[test]
5252
fn test_range_inclusive() {
53-
let mut r = RangeInclusive { start: 1i8, end: 2 };
53+
let mut r = RangeInclusive::new(1i8, 2);
5454
assert_eq!(r.next(), Some(1));
5555
assert_eq!(r.next(), Some(2));
5656
assert_eq!(r.next(), None);
5757

58-
r = RangeInclusive { start: 127i8, end: 127 };
58+
r = RangeInclusive::new(127i8, 127);
5959
assert_eq!(r.next(), Some(127));
6060
assert_eq!(r.next(), None);
6161

62-
r = RangeInclusive { start: -128i8, end: -128 };
62+
r = RangeInclusive::new(-128i8, -128);
6363
assert_eq!(r.next_back(), Some(-128));
6464
assert_eq!(r.next_back(), None);
6565

6666
// degenerate
67-
r = RangeInclusive { start: 1, end: -1 };
67+
r = RangeInclusive::new(1, -1);
6868
assert_eq!(r.size_hint(), (0, Some(0)));
6969
assert_eq!(r.next(), None);
7070
}

src/librustc/hir/lowering.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -3119,6 +3119,20 @@ impl<'a> LoweringContext<'a> {
31193119
ExprKind::Index(ref el, ref er) => {
31203120
hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
31213121
}
3122+
// Desugar `<start>..=<end>` to `std::ops::RangeInclusive::new(<start>, <end>)`
3123+
ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
3124+
// FIXME: Use head_sp directly after RangeInclusive::new() is stabilized in stage0.
3125+
let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
3126+
let id = self.lower_node_id(e.id);
3127+
let e1 = self.lower_expr(e1);
3128+
let e2 = self.lower_expr(e2);
3129+
let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], false));
3130+
let ty = self.ty_path(id, span, hir::QPath::Resolved(None, ty_path));
3131+
let new_seg = P(hir::PathSegment::from_name(Symbol::intern("new")));
3132+
let new_path = hir::QPath::TypeRelative(ty, new_seg);
3133+
let new = P(self.expr(span, hir::ExprPath(new_path), ThinVec::new()));
3134+
hir::ExprCall(new, hir_vec![e1, e2])
3135+
}
31223136
ExprKind::Range(ref e1, ref e2, lims) => {
31233137
use syntax::ast::RangeLimits::*;
31243138

@@ -3128,7 +3142,7 @@ impl<'a> LoweringContext<'a> {
31283142
(&None, &Some(..), HalfOpen) => "RangeTo",
31293143
(&Some(..), &Some(..), HalfOpen) => "Range",
31303144
(&None, &Some(..), Closed) => "RangeToInclusive",
3131-
(&Some(..), &Some(..), Closed) => "RangeInclusive",
3145+
(&Some(..), &Some(..), Closed) => unreachable!(),
31323146
(_, &None, Closed) => self.diagnostic()
31333147
.span_fatal(e.span, "inclusive range with no end")
31343148
.raise(),

src/librustc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
#![feature(trusted_len)]
7070
#![feature(catch_expr)]
7171
#![feature(test)]
72-
#![feature(inclusive_range_fields)]
72+
#![feature(inclusive_range_methods)]
7373

7474
#![recursion_limit="512"]
7575

src/librustc/ty/layout.rs

+20-24
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use std::cmp;
1919
use std::fmt;
2020
use std::i128;
2121
use std::mem;
22-
use std::ops::RangeInclusive;
2322

2423
use ich::StableHashingContext;
2524
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -492,7 +491,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
492491
ty::TyFloat(FloatTy::F64) => scalar(F64),
493492
ty::TyFnPtr(_) => {
494493
let mut ptr = scalar_unit(Pointer);
495-
ptr.valid_range.start = 1;
494+
ptr.valid_range = 1..=*ptr.valid_range.end();
496495
tcx.intern_layout(LayoutDetails::scalar(self, ptr))
497496
}
498497

@@ -506,7 +505,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
506505
ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
507506
let mut data_ptr = scalar_unit(Pointer);
508507
if !ty.is_unsafe_ptr() {
509-
data_ptr.valid_range.start = 1;
508+
data_ptr.valid_range = 1..=*data_ptr.valid_range.end();
510509
}
511510

512511
let pointee = tcx.normalize_erasing_regions(param_env, pointee);
@@ -524,7 +523,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
524523
}
525524
ty::TyDynamic(..) => {
526525
let mut vtable = scalar_unit(Pointer);
527-
vtable.valid_range.start = 1;
526+
vtable.valid_range = 1..=*vtable.valid_range.end();
528527
vtable
529528
}
530529
_ => return Err(LayoutError::Unknown(unsized_part))
@@ -751,8 +750,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
751750
match st.abi {
752751
Abi::Scalar(ref mut scalar) |
753752
Abi::ScalarPair(ref mut scalar, _) => {
754-
if scalar.valid_range.start == 0 {
755-
scalar.valid_range.start = 1;
753+
if *scalar.valid_range.start() == 0 {
754+
scalar.valid_range = 1..=*scalar.valid_range.end();
756755
}
757756
}
758757
_ => {}
@@ -788,18 +787,15 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
788787
}
789788
}
790789
}
791-
if niche_variants.start > v {
792-
niche_variants.start = v;
793-
}
794-
niche_variants.end = v;
790+
niche_variants = *niche_variants.start().min(&v)..=v;
795791
}
796792

797-
if niche_variants.start > niche_variants.end {
793+
if niche_variants.start() > niche_variants.end() {
798794
dataful_variant = None;
799795
}
800796

801797
if let Some(i) = dataful_variant {
802-
let count = (niche_variants.end - niche_variants.start + 1) as u128;
798+
let count = (niche_variants.end() - niche_variants.start() + 1) as u128;
803799
for (field_index, &field) in variants[i].iter().enumerate() {
804800
let (offset, niche, niche_start) =
805801
match self.find_niche(field, count)? {
@@ -1659,22 +1655,22 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
16591655
let max_value = !0u128 >> (128 - bits);
16601656

16611657
// Find out how many values are outside the valid range.
1662-
let niches = if v.start <= v.end {
1663-
v.start + (max_value - v.end)
1658+
let niches = if v.start() <= v.end() {
1659+
v.start() + (max_value - v.end())
16641660
} else {
1665-
v.start - v.end - 1
1661+
v.start() - v.end() - 1
16661662
};
16671663

16681664
// Give up if we can't fit `count` consecutive niches.
16691665
if count > niches {
16701666
return None;
16711667
}
16721668

1673-
let niche_start = v.end.wrapping_add(1) & max_value;
1674-
let niche_end = v.end.wrapping_add(count) & max_value;
1669+
let niche_start = v.end().wrapping_add(1) & max_value;
1670+
let niche_end = v.end().wrapping_add(count) & max_value;
16751671
Some((offset, Scalar {
16761672
value,
1677-
valid_range: v.start..=niche_end
1673+
valid_range: *v.start()..=niche_end
16781674
}, niche_start))
16791675
};
16801676

@@ -1744,14 +1740,14 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
17441740
}
17451741
NicheFilling {
17461742
dataful_variant,
1747-
niche_variants: RangeInclusive { start, end },
1743+
ref niche_variants,
17481744
ref niche,
17491745
niche_start,
17501746
ref variants,
17511747
} => {
17521748
dataful_variant.hash_stable(hcx, hasher);
1753-
start.hash_stable(hcx, hasher);
1754-
end.hash_stable(hcx, hasher);
1749+
niche_variants.start().hash_stable(hcx, hasher);
1750+
niche_variants.end().hash_stable(hcx, hasher);
17551751
niche.hash_stable(hcx, hasher);
17561752
niche_start.hash_stable(hcx, hasher);
17571753
variants.hash_stable(hcx, hasher);
@@ -1814,10 +1810,10 @@ impl<'a> HashStable<StableHashingContext<'a>> for Scalar {
18141810
fn hash_stable<W: StableHasherResult>(&self,
18151811
hcx: &mut StableHashingContext<'a>,
18161812
hasher: &mut StableHasher<W>) {
1817-
let Scalar { value, valid_range: RangeInclusive { start, end } } = *self;
1813+
let Scalar { value, ref valid_range } = *self;
18181814
value.hash_stable(hcx, hasher);
1819-
start.hash_stable(hcx, hasher);
1820-
end.hash_stable(hcx, hasher);
1815+
valid_range.start().hash_stable(hcx, hasher);
1816+
valid_range.end().hash_stable(hcx, hasher);
18211817
}
18221818
}
18231819

src/librustc_mir/interpret/eval_context.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -917,8 +917,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
917917
niche_start,
918918
..
919919
} => {
920-
let variants_start = niche_variants.start as u128;
921-
let variants_end = niche_variants.end as u128;
920+
let variants_start = *niche_variants.start() as u128;
921+
let variants_end = *niche_variants.end() as u128;
922922
match raw_discr {
923923
PrimVal::Ptr(_) => {
924924
assert!(niche_start == 0);
@@ -984,7 +984,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
984984
if variant_index != dataful_variant {
985985
let (niche_dest, niche) =
986986
self.place_field(dest, mir::Field::new(0), layout)?;
987-
let niche_value = ((variant_index - niche_variants.start) as u128)
987+
let niche_value = ((variant_index - niche_variants.start()) as u128)
988988
.wrapping_add(niche_start);
989989
self.write_primval(niche_dest, PrimVal::Bytes(niche_value), niche.ty)?;
990990
}

src/librustc_mir/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
3131
#![feature(range_contains)]
3232
#![feature(rustc_diagnostic_macros)]
3333
#![feature(nonzero)]
34-
#![feature(inclusive_range_fields)]
34+
#![feature(inclusive_range_methods)]
3535
#![feature(crate_visibility_modifier)]
3636
#![feature(never_type)]
3737
#![cfg_attr(stage0, feature(try_trait))]

src/librustc_target/abi/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,8 @@ impl Scalar {
555555
let bits = self.value.size(cx).bits();
556556
assert!(bits <= 128);
557557
let mask = !0u128 >> (128 - bits);
558-
let start = self.valid_range.start;
559-
let end = self.valid_range.end;
558+
let start = *self.valid_range.start();
559+
let end = *self.valid_range.end();
560560
assert_eq!(start, start & mask);
561561
assert_eq!(end, end & mask);
562562
start..(end.wrapping_add(1) & mask)

src/librustc_target/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#![feature(const_fn)]
3030
#![feature(fs_read_write)]
3131
#![feature(inclusive_range)]
32-
#![feature(inclusive_range_fields)]
32+
#![feature(inclusive_range_methods)]
3333
#![feature(slice_patterns)]
3434

3535
#[macro_use]

src/librustc_trans/abi.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
388388
return;
389389
}
390390

391-
if scalar.valid_range.start < scalar.valid_range.end {
392-
if scalar.valid_range.start > 0 {
391+
if scalar.valid_range.start() < scalar.valid_range.end() {
392+
if *scalar.valid_range.start() > 0 {
393393
attrs.set(ArgAttribute::NonNull);
394394
}
395395
}

src/librustc_trans/debuginfo/metadata.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1236,7 +1236,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
12361236
self.layout,
12371237
self.layout.fields.offset(0),
12381238
self.layout.field(cx, 0).size);
1239-
name.push_str(&adt.variants[niche_variants.start].name.as_str());
1239+
name.push_str(&adt.variants[*niche_variants.start()].name.as_str());
12401240

12411241
// Create the (singleton) list of descriptions of union members.
12421242
vec![

0 commit comments

Comments
 (0)