Skip to content
/ rust Public
forked from rust-lang/rust

Commit

Permalink
Rollup merge of rust-lang#136167 - pitaj:new_range, r=Nadrieril
Browse files Browse the repository at this point in the history
Implement unstable `new_range` feature

Switches `a..b`, `a..`, and `a..=b` to resolve to the new range types.

For rust-lang/rfcs#3550
Tracking issue rust-lang#123741

also adds the re-export that was missed in the original implementation of `new_range_api`
  • Loading branch information
jhpratt authored Feb 4, 2025
2 parents 648fd0e + f530a29 commit d31e137
Show file tree
Hide file tree
Showing 29 changed files with 252 additions and 54 deletions.
35 changes: 28 additions & 7 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Index(el, er, brackets_span) => {
hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er), *brackets_span)
}
ExprKind::Range(Some(e1), Some(e2), RangeLimits::Closed) => {
self.lower_expr_range_closed(e.span, e1, e2)
}
ExprKind::Range(e1, e2, lims) => {
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
}
Expand Down Expand Up @@ -1512,15 +1509,39 @@ impl<'hir> LoweringContext<'_, 'hir> {

let lang_item = match (e1, e2, lims) {
(None, None, HalfOpen) => hir::LangItem::RangeFull,
(Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
(Some(..), None, HalfOpen) => {
if self.tcx.features().new_range() {
hir::LangItem::RangeFromCopy
} else {
hir::LangItem::RangeFrom
}
}
(None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
(Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
(Some(..), Some(..), HalfOpen) => {
if self.tcx.features().new_range() {
hir::LangItem::RangeCopy
} else {
hir::LangItem::Range
}
}
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
(Some(..), Some(..), Closed) => unreachable!(),
(Some(e1), Some(e2), Closed) => {
if self.tcx.features().new_range() {
hir::LangItem::RangeInclusiveCopy
} else {
return self.lower_expr_range_closed(span, e1, e2);
}
}
(start, None, Closed) => {
self.dcx().emit_err(InclusiveRangeWithNoEnd { span });
match start {
Some(..) => hir::LangItem::RangeFrom,
Some(..) => {
if self.tcx.features().new_range() {
hir::LangItem::RangeFromCopy
} else {
hir::LangItem::RangeFrom
}
}
None => hir::LangItem::RangeFull,
}
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,8 @@ declare_features! (
(unstable, never_type, "1.13.0", Some(35121)),
/// Allows diverging expressions to fall back to `!` rather than `()`.
(unstable, never_type_fallback, "1.41.0", Some(65992)),
/// Switch `..` syntax to use the new (`Copy + IntoIterator`) range types.
(unstable, new_range, "CURRENT_RUSTC_VERSION", Some(123741)),
/// Allows `#![no_core]`.
(unstable, no_core, "1.3.0", Some(29639)),
/// Allows the use of `no_sanitize` attribute.
Expand Down
41 changes: 40 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2313,6 +2313,18 @@ impl Expr<'_> {
[val2],
StructTailExpr::None,
),
)
| (
ExprKind::Struct(
QPath::LangItem(LangItem::RangeFromCopy, _),
[val1],
StructTailExpr::None,
),
ExprKind::Struct(
QPath::LangItem(LangItem::RangeFromCopy, _),
[val2],
StructTailExpr::None,
),
) => val1.expr.equivalent_for_indexing(val2.expr),
(
ExprKind::Struct(
Expand All @@ -2325,6 +2337,30 @@ impl Expr<'_> {
[val2, val4],
StructTailExpr::None,
),
)
| (
ExprKind::Struct(
QPath::LangItem(LangItem::RangeCopy, _),
[val1, val3],
StructTailExpr::None,
),
ExprKind::Struct(
QPath::LangItem(LangItem::RangeCopy, _),
[val2, val4],
StructTailExpr::None,
),
)
| (
ExprKind::Struct(
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
[val1, val3],
StructTailExpr::None,
),
ExprKind::Struct(
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
[val2, val4],
StructTailExpr::None,
),
) => {
val1.expr.equivalent_for_indexing(val2.expr)
&& val3.expr.equivalent_for_indexing(val4.expr)
Expand Down Expand Up @@ -2354,7 +2390,10 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
| LangItem::RangeTo
| LangItem::RangeFrom
| LangItem::RangeFull
| LangItem::RangeToInclusive,
| LangItem::RangeToInclusive
| LangItem::RangeCopy
| LangItem::RangeFromCopy
| LangItem::RangeInclusiveCopy,
..
)
),
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ language_item_table! {
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;

// `new_range` types that are `Copy + IntoIterator`
RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None;
RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None;

String, sym::String, string, Target::Struct, GenericRequirement::None;
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2395,6 +2395,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let lang_item = match parent_expr.kind {
ExprKind::Struct(qpath, _, _) => match *qpath {
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
QPath::LangItem(LangItem::RangeCopy, ..) => Some(LangItem::RangeCopy),
QPath::LangItem(LangItem::RangeInclusiveCopy, ..) => {
Some(LangItem::RangeInclusiveCopy)
}
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
Some(LangItem::RangeToInclusive)
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,12 @@ symbols! {
ProceduralMasqueradeDummyType,
Range,
RangeBounds,
RangeCopy,
RangeFrom,
RangeFromCopy,
RangeFull,
RangeInclusive,
RangeInclusiveCopy,
RangeTo,
RangeToInclusive,
Rc,
Expand Down Expand Up @@ -1364,6 +1367,7 @@ symbols! {
new_lower_hex,
new_octal,
new_pointer,
new_range,
new_unchecked,
new_upper_exp,
new_upper_hex,
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, Rang
/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
/// ```
#[cfg_attr(not(bootstrap), lang = "RangeCopy")]
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
#[unstable(feature = "new_range_api", issue = "125687")]
pub struct Range<Idx> {
Expand Down Expand Up @@ -205,6 +206,7 @@ impl<T> From<legacy::Range<T>> for Range<T> {
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
/// ```
#[cfg_attr(not(bootstrap), lang = "RangeInclusiveCopy")]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[unstable(feature = "new_range_api", issue = "125687")]
pub struct RangeInclusive<Idx> {
Expand Down Expand Up @@ -388,6 +390,7 @@ impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
/// ```
#[cfg_attr(not(bootstrap), lang = "RangeFromCopy")]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[unstable(feature = "new_range_api", issue = "125687")]
pub struct RangeFrom<Idx> {
Expand Down
2 changes: 2 additions & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,8 @@ pub use core::option;
pub use core::pin;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::ptr;
#[unstable(feature = "new_range_api", issue = "125687")]
pub use core::range;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::result;
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
9 changes: 9 additions & 0 deletions src/doc/unstable-book/src/language-features/new-range.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# `new_range`

The tracking issue for this feature is: [#123741]

[#123741]: https://github.com/rust-lang/rust/issues/123741

---

Switch the syntaxes `a..`, `a..b`, and `a..=b` to resolve the new range types.
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
scope 2 {
debug x => _9;
}
scope 5 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
scope 5 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
}
}
scope 3 (inlined RangeInclusive::<u32>::new) {
scope 3 (inlined std::ops::RangeInclusive::<u32>::new) {
}
scope 4 (inlined <RangeInclusive<u32> as IntoIterator>::into_iter) {
scope 4 (inlined <std::ops::RangeInclusive<u32> as IntoIterator>::into_iter) {
}

bb0: {
_4 = RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
_4 = std::ops::RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
StorageLive(_5);
_5 = copy _4;
goto -> bb1;
Expand All @@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
bb1: {
StorageLive(_7);
_6 = &mut _5;
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
_7 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
}

bb2: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
scope 2 {
debug x => _9;
}
scope 5 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
scope 5 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
}
}
scope 3 (inlined RangeInclusive::<u32>::new) {
scope 3 (inlined std::ops::RangeInclusive::<u32>::new) {
}
scope 4 (inlined <RangeInclusive<u32> as IntoIterator>::into_iter) {
scope 4 (inlined <std::ops::RangeInclusive<u32> as IntoIterator>::into_iter) {
}

bb0: {
_4 = RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
_4 = std::ops::RangeInclusive::<u32> { start: copy _1, end: copy _2, exhausted: const false };
StorageLive(_5);
_5 = copy _4;
goto -> bb1;
Expand All @@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
bb1: {
StorageLive(_7);
_6 = &mut _5;
_7 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
_7 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
}

bb2: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// MIR for `range_inclusive_iter_next` after PreCodegen

fn range_inclusive_iter_next(_1: &mut RangeInclusive<u32>) -> Option<u32> {
fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive<u32>) -> Option<u32> {
debug it => _1;
let mut _0: std::option::Option<u32>;
scope 1 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
scope 1 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
}

bb0: {
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
_0 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
}

bb1: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// MIR for `range_inclusive_iter_next` after PreCodegen

fn range_inclusive_iter_next(_1: &mut RangeInclusive<u32>) -> Option<u32> {
fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive<u32>) -> Option<u32> {
debug it => _1;
let mut _0: std::option::Option<u32>;
scope 1 (inlined iter::range::<impl Iterator for RangeInclusive<u32>>::next) {
scope 1 (inlined iter::range::<impl Iterator for std::ops::RangeInclusive<u32>>::next) {
}

bb0: {
_0 = <RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
_0 = <std::ops::RangeInclusive<u32> as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
}

bb1: {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/const-generics/std/const-generics-range.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0741]: `std::ops::Range<usize>` must implement `ConstParamTy` to be used
LL | struct _Range<const R: std::ops::Range<usize>>;
| ^^^^^^^^^^^^^^^^^^^^^^

error[E0741]: `RangeFrom<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
error[E0741]: `std::ops::RangeFrom<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/const-generics-range.rs:13:28
|
LL | struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
Expand All @@ -16,7 +16,7 @@ error[E0741]: `RangeFull` must implement `ConstParamTy` to be used as the type o
LL | struct _RangeFull<const R: std::ops::RangeFull>;
| ^^^^^^^^^^^^^^^^^^^

error[E0741]: `RangeInclusive<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
error[E0741]: `std::ops::RangeInclusive<usize>` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/const-generics-range.rs:24:33
|
LL | struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/const-generics/std/const-generics-range.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|

error: `RangeFrom<usize>` is forbidden as the type of a const generic parameter
error: `std::ops::RangeFrom<usize>` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:13:28
|
LL | struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
Expand All @@ -34,7 +34,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|

error: `RangeInclusive<usize>` is forbidden as the type of a const generic parameter
error: `std::ops::RangeInclusive<usize>` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:24:33
|
LL | struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/const-generics/std/const-generics-range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const RANGE : _Range<{ 0 .. 1000 }> = _Range;

// `RangeFrom` should be usable within const generics:
struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
//[min]~^ ERROR `RangeFrom<usize>` is forbidden
//[min]~^ ERROR `std::ops::RangeFrom<usize>` is forbidden
const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom;

// `RangeFull` should be usable within const generics:
Expand All @@ -22,7 +22,7 @@ const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull;
// Regression test for #70155
// `RangeInclusive` should be usable within const generics:
struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
//[min]~^ ERROR `RangeInclusive<usize>` is forbidden
//[min]~^ ERROR `std::ops::RangeInclusive<usize>` is forbidden
const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive;

// `RangeTo` should be usable within const generics:
Expand Down
10 changes: 10 additions & 0 deletions tests/ui/feature-gates/feature-gate-new_range.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![feature(new_range_api)]

fn main() {
let a: core::range::RangeFrom<u8> = 1..;
//~^ mismatched types
let b: core::range::Range<u8> = 2..3;
//~^ mismatched types
let c: core::range::RangeInclusive<u8> = 4..=5;
//~^ mismatched types
}
Loading

0 comments on commit d31e137

Please sign in to comment.