Skip to content

Commit a631623

Browse files
authored
Unrolled build for #144765
Rollup merge of #144765 - Qelxiros:range-inclusive-last, r=jhpratt inclusive `Range`s: change `end` to `last` Tracking issue: #125687 ACP: rust-lang/libs-team#511
2 parents 7ad23f4 + 8d0c07f commit a631623

File tree

20 files changed

+245
-53
lines changed

20 files changed

+245
-53
lines changed

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,7 +1536,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
15361536
hir::LangItem::Range
15371537
}
15381538
}
1539-
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
1539+
(None, Some(..), Closed) => {
1540+
if self.tcx.features().new_range() {
1541+
hir::LangItem::RangeToInclusiveCopy
1542+
} else {
1543+
hir::LangItem::RangeToInclusive
1544+
}
1545+
}
15401546
(Some(e1), Some(e2), Closed) => {
15411547
if self.tcx.features().new_range() {
15421548
hir::LangItem::RangeInclusiveCopy
@@ -1560,13 +1566,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
15601566
};
15611567

15621568
let fields = self.arena.alloc_from_iter(
1563-
e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map(
1564-
|(s, e)| {
1569+
e1.iter()
1570+
.map(|e| (sym::start, e))
1571+
.chain(e2.iter().map(|e| {
1572+
(
1573+
if matches!(
1574+
lang_item,
1575+
hir::LangItem::RangeInclusiveCopy | hir::LangItem::RangeToInclusiveCopy
1576+
) {
1577+
sym::last
1578+
} else {
1579+
sym::end
1580+
},
1581+
e,
1582+
)
1583+
}))
1584+
.map(|(s, e)| {
15651585
let expr = self.lower_expr(e);
15661586
let ident = Ident::new(s, self.lower_span(e.span));
15671587
self.expr_field(ident, expr, e.span)
1568-
},
1569-
),
1588+
}),
15701589
);
15711590

15721591
hir::ExprKind::Struct(

compiler/rustc_hir/src/hir.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2614,6 +2614,18 @@ impl Expr<'_> {
26142614
StructTailExpr::None,
26152615
),
26162616
)
2617+
| (
2618+
ExprKind::Struct(
2619+
QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
2620+
[val1],
2621+
StructTailExpr::None,
2622+
),
2623+
ExprKind::Struct(
2624+
QPath::LangItem(LangItem::RangeToInclusiveCopy, _),
2625+
[val2],
2626+
StructTailExpr::None,
2627+
),
2628+
)
26172629
| (
26182630
ExprKind::Struct(
26192631
QPath::LangItem(LangItem::RangeFrom, _),
@@ -2705,7 +2717,8 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
27052717
| LangItem::RangeToInclusive
27062718
| LangItem::RangeCopy
27072719
| LangItem::RangeFromCopy
2708-
| LangItem::RangeInclusiveCopy,
2720+
| LangItem::RangeInclusiveCopy
2721+
| LangItem::RangeToInclusiveCopy,
27092722
..
27102723
)
27112724
),

compiler/rustc_hir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ language_item_table! {
422422
RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
423423
RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None;
424424
RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
425+
RangeToInclusiveCopy, sym::RangeToInclusiveCopy, range_to_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
425426

426427
String, sym::String, string, Target::Struct, GenericRequirement::None;
427428
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;

compiler/rustc_index/src/idx.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,22 @@ impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeFrom<I> {
130130
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
131131
type Output = core::range::RangeInclusive<usize>;
132132
#[inline]
133+
#[cfg(bootstrap)]
133134
fn into_slice_idx(self) -> Self::Output {
134135
core::range::RangeInclusive { start: self.start.index(), end: self.end.index() }
135136
}
137+
#[inline]
138+
#[cfg(not(bootstrap))]
139+
fn into_slice_idx(self) -> Self::Output {
140+
core::range::RangeInclusive { start: self.start.index(), last: self.last.index() }
141+
}
142+
}
143+
144+
#[cfg(all(feature = "nightly", not(bootstrap)))]
145+
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeToInclusive<I> {
146+
type Output = core::range::RangeToInclusive<usize>;
147+
#[inline]
148+
fn into_slice_idx(self) -> Self::Output {
149+
core::range::RangeToInclusive { last: self.last.index() }
150+
}
136151
}

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ symbols! {
326326
RangeSub,
327327
RangeTo,
328328
RangeToInclusive,
329+
RangeToInclusiveCopy,
329330
Rc,
330331
RcWeak,
331332
Ready,
@@ -1280,6 +1281,7 @@ symbols! {
12801281
lang,
12811282
lang_items,
12821283
large_assignments,
1284+
last,
12831285
lateout,
12841286
lazy_normalization_consts,
12851287
lazy_type_alias,

library/core/src/range.rs

Lines changed: 121 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
3131
#[doc(inline)]
3232
pub use crate::iter::Step;
3333
#[doc(inline)]
34-
pub use crate::ops::{
35-
Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive,
36-
};
34+
pub use crate::ops::{Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo};
3735

3836
/// A (half-open) range bounded inclusively below and exclusively above
3937
/// (`start..end` in a future edition).
@@ -209,20 +207,20 @@ impl<T> const From<legacy::Range<T>> for Range<T> {
209207
}
210208
}
211209

212-
/// A range bounded inclusively below and above (`start..=end`).
210+
/// A range bounded inclusively below and above (`start..=last`).
213211
///
214-
/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
215-
/// and `x <= end`. It is empty unless `start <= end`.
212+
/// The `RangeInclusive` `start..=last` contains all values with `x >= start`
213+
/// and `x <= last`. It is empty unless `start <= last`.
216214
///
217215
/// # Examples
218216
///
219-
/// The `start..=end` syntax is a `RangeInclusive`:
217+
/// The `start..=last` syntax is a `RangeInclusive`:
220218
///
221219
/// ```
222220
/// #![feature(new_range_api)]
223221
/// use core::range::RangeInclusive;
224222
///
225-
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
223+
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
226224
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
227225
/// ```
228226
#[lang = "RangeInclusiveCopy"]
@@ -234,15 +232,15 @@ pub struct RangeInclusive<Idx> {
234232
pub start: Idx,
235233
/// The upper bound of the range (inclusive).
236234
#[unstable(feature = "new_range_api", issue = "125687")]
237-
pub end: Idx,
235+
pub last: Idx,
238236
}
239237

240238
#[unstable(feature = "new_range_api", issue = "125687")]
241239
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
242240
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
243241
self.start.fmt(fmt)?;
244242
write!(fmt, "..=")?;
245-
self.end.fmt(fmt)?;
243+
self.last.fmt(fmt)?;
246244
Ok(())
247245
}
248246
}
@@ -306,7 +304,7 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
306304
#[unstable(feature = "new_range_api", issue = "125687")]
307305
#[inline]
308306
pub fn is_empty(&self) -> bool {
309-
!(self.start <= self.end)
307+
!(self.start <= self.last)
310308
}
311309
}
312310

@@ -335,10 +333,10 @@ impl<Idx: Step> RangeInclusive<Idx> {
335333

336334
impl RangeInclusive<usize> {
337335
/// Converts to an exclusive `Range` for `SliceIndex` implementations.
338-
/// The caller is responsible for dealing with `end == usize::MAX`.
336+
/// The caller is responsible for dealing with `last == usize::MAX`.
339337
#[inline]
340338
pub(crate) const fn into_slice_range(self) -> Range<usize> {
341-
Range { start: self.start, end: self.end + 1 }
339+
Range { start: self.start, end: self.last + 1 }
342340
}
343341
}
344342

@@ -348,7 +346,7 @@ impl<T> RangeBounds<T> for RangeInclusive<T> {
348346
Included(&self.start)
349347
}
350348
fn end_bound(&self) -> Bound<&T> {
351-
Included(&self.end)
349+
Included(&self.last)
352350
}
353351
}
354352

@@ -364,15 +362,15 @@ impl<T> RangeBounds<T> for RangeInclusive<&T> {
364362
Included(self.start)
365363
}
366364
fn end_bound(&self) -> Bound<&T> {
367-
Included(self.end)
365+
Included(self.last)
368366
}
369367
}
370368

371369
// #[unstable(feature = "range_into_bounds", issue = "136903")]
372370
#[unstable(feature = "new_range_api", issue = "125687")]
373371
impl<T> IntoBounds<T> for RangeInclusive<T> {
374372
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
375-
(Included(self.start), Included(self.end))
373+
(Included(self.start), Included(self.last))
376374
}
377375
}
378376

@@ -381,7 +379,7 @@ impl<T> IntoBounds<T> for RangeInclusive<T> {
381379
impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
382380
#[inline]
383381
fn from(value: RangeInclusive<T>) -> Self {
384-
Self::new(value.start, value.end)
382+
Self::new(value.start, value.last)
385383
}
386384
}
387385
#[unstable(feature = "new_range_api", issue = "125687")]
@@ -394,8 +392,8 @@ impl<T> const From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
394392
"attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
395393
);
396394

397-
let (start, end) = value.into_inner();
398-
RangeInclusive { start, end }
395+
let (start, last) = value.into_inner();
396+
RangeInclusive { start, last }
399397
}
400398
}
401399

@@ -544,3 +542,107 @@ impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
544542
Self { start: value.start }
545543
}
546544
}
545+
546+
/// A range only bounded inclusively above (`..=last`).
547+
///
548+
/// The `RangeToInclusive` `..=last` contains all values with `x <= last`.
549+
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
550+
///
551+
/// # Examples
552+
///
553+
/// The `..=last` syntax is a `RangeToInclusive`:
554+
///
555+
/// ```
556+
/// #![feature(new_range_api)]
557+
/// #![feature(new_range)]
558+
/// assert_eq!((..=5), std::range::RangeToInclusive{ last: 5 });
559+
/// ```
560+
///
561+
/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
562+
/// `for` loop directly. This won't compile:
563+
///
564+
/// ```compile_fail,E0277
565+
/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
566+
/// // std::iter::Iterator` is not satisfied
567+
/// for i in ..=5 {
568+
/// // ...
569+
/// }
570+
/// ```
571+
///
572+
/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
573+
/// array elements up to and including the index indicated by `last`.
574+
///
575+
/// ```
576+
/// let arr = [0, 1, 2, 3, 4];
577+
/// assert_eq!(arr[ .. ], [0, 1, 2, 3, 4]);
578+
/// assert_eq!(arr[ .. 3], [0, 1, 2 ]);
579+
/// assert_eq!(arr[ ..=3], [0, 1, 2, 3 ]); // This is a `RangeToInclusive`
580+
/// assert_eq!(arr[1.. ], [ 1, 2, 3, 4]);
581+
/// assert_eq!(arr[1.. 3], [ 1, 2 ]);
582+
/// assert_eq!(arr[1..=3], [ 1, 2, 3 ]);
583+
/// ```
584+
///
585+
/// [slicing index]: crate::slice::SliceIndex
586+
#[lang = "RangeToInclusiveCopy"]
587+
#[doc(alias = "..=")]
588+
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
589+
#[unstable(feature = "new_range_api", issue = "125687")]
590+
pub struct RangeToInclusive<Idx> {
591+
/// The upper bound of the range (inclusive)
592+
#[unstable(feature = "new_range_api", issue = "125687")]
593+
pub last: Idx,
594+
}
595+
596+
#[unstable(feature = "new_range_api", issue = "125687")]
597+
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
598+
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
599+
write!(fmt, "..=")?;
600+
self.last.fmt(fmt)?;
601+
Ok(())
602+
}
603+
}
604+
605+
impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
606+
/// Returns `true` if `item` is contained in the range.
607+
///
608+
/// # Examples
609+
///
610+
/// ```
611+
/// assert!( (..=5).contains(&-1_000_000_000));
612+
/// assert!( (..=5).contains(&5));
613+
/// assert!(!(..=5).contains(&6));
614+
///
615+
/// assert!( (..=1.0).contains(&1.0));
616+
/// assert!(!(..=1.0).contains(&f32::NAN));
617+
/// assert!(!(..=f32::NAN).contains(&0.5));
618+
/// ```
619+
#[inline]
620+
#[unstable(feature = "new_range_api", issue = "125687")]
621+
pub fn contains<U>(&self, item: &U) -> bool
622+
where
623+
Idx: PartialOrd<U>,
624+
U: ?Sized + PartialOrd<Idx>,
625+
{
626+
<Self as RangeBounds<Idx>>::contains(self, item)
627+
}
628+
}
629+
630+
// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
631+
// because underflow would be possible with (..0).into()
632+
633+
#[unstable(feature = "new_range_api", issue = "125687")]
634+
impl<T> RangeBounds<T> for RangeToInclusive<T> {
635+
fn start_bound(&self) -> Bound<&T> {
636+
Unbounded
637+
}
638+
fn end_bound(&self) -> Bound<&T> {
639+
Included(&self.last)
640+
}
641+
}
642+
643+
#[unstable(feature = "range_into_bounds", issue = "136903")]
644+
impl<T> IntoBounds<T> for RangeToInclusive<T> {
645+
fn into_bounds(self) -> (Bound<T>, Bound<T>) {
646+
(Unbounded, Included(self.last))
647+
}
648+
}

library/core/src/range/iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl<A: Step> IterRangeInclusive<A> {
164164
return None;
165165
}
166166

167-
Some(RangeInclusive { start: self.0.start, end: self.0.end })
167+
Some(RangeInclusive { start: self.0.start, last: self.0.end })
168168
}
169169
}
170170

library/core/src/range/legacy.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! # Legacy range types
22
//!
33
//! The types within this module will be replaced by the types
4-
//! [`Range`], [`RangeInclusive`], and [`RangeFrom`] in the parent
4+
//! [`Range`], [`RangeInclusive`], [`RangeToInclusive`], and [`RangeFrom`] in the parent
55
//! module, [`core::range`].
66
//!
77
//! The types here are equivalent to those in [`core::ops`].
88
99
#[doc(inline)]
10-
pub use crate::ops::{Range, RangeFrom, RangeInclusive};
10+
pub use crate::ops::{Range, RangeFrom, RangeInclusive, RangeToInclusive};

0 commit comments

Comments
 (0)