From 95eaadc773eb4adab8f46cd77083d1d503fd5bff Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Sun, 26 Jan 2025 13:27:34 -0700
Subject: [PATCH 1/2] std::range
---
library/std/src/lib.rs | 2 ++
...ter.inclusive_loop.PreCodegen.after.panic-abort.mir | 10 +++++-----
...er.inclusive_loop.PreCodegen.after.panic-unwind.mir | 10 +++++-----
...nclusive_iter_next.PreCodegen.after.panic-abort.mir | 6 +++---
...clusive_iter_next.PreCodegen.after.panic-unwind.mir | 6 +++---
.../std/const-generics-range.full.stderr | 4 ++--
.../const-generics/std/const-generics-range.min.stderr | 4 ++--
tests/ui/const-generics/std/const-generics-range.rs | 4 ++--
tests/ui/issues/issue-76191.stderr | 4 ++--
...closure-arg-type-mismatch-issue-45727.current.fixed | 2 +-
.../closure-arg-type-mismatch-issue-45727.next.stderr | 8 ++++----
.../closure-arg-type-mismatch-issue-45727.rs | 2 +-
tests/ui/never_type/issue-52443.stderr | 4 ++--
tests/ui/range/issue-54505-no-literals.stderr | 8 ++++----
tests/ui/range/issue-54505.stderr | 4 ++--
tests/ui/range/range-1.stderr | 2 +-
.../unnecessary_dot_for_floating_point_literal.stderr | 2 +-
17 files changed, 42 insertions(+), 40 deletions(-)
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index acb3a0578e505..7c18226874cc8 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -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")]
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
index 60c0b8afa5343..3f000dcafb035 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
@@ -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::>::next) {
+ scope 5 (inlined iter::range::>::next) {
}
}
- scope 3 (inlined RangeInclusive::::new) {
+ scope 3 (inlined std::ops::RangeInclusive::::new) {
}
- scope 4 (inlined as IntoIterator>::into_iter) {
+ scope 4 (inlined as IntoIterator>::into_iter) {
}
bb0: {
- _4 = RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
+ _4 = std::ops::RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
StorageLive(_5);
_5 = copy _4;
goto -> bb1;
@@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
bb1: {
StorageLive(_7);
_6 = &mut _5;
- _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
+ _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
}
bb2: {
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
index 7145da58ce18c..2353717362711 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
@@ -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::>::next) {
+ scope 5 (inlined iter::range::>::next) {
}
}
- scope 3 (inlined RangeInclusive::::new) {
+ scope 3 (inlined std::ops::RangeInclusive::::new) {
}
- scope 4 (inlined as IntoIterator>::into_iter) {
+ scope 4 (inlined as IntoIterator>::into_iter) {
}
bb0: {
- _4 = RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
+ _4 = std::ops::RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
StorageLive(_5);
_5 = copy _4;
goto -> bb1;
@@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
bb1: {
StorageLive(_7);
_6 = &mut _5;
- _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
+ _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
}
bb2: {
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir
index 8e038246fa2d7..13969e5d23858 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir
@@ -1,13 +1,13 @@
// MIR for `range_inclusive_iter_next` after PreCodegen
-fn range_inclusive_iter_next(_1: &mut RangeInclusive) -> Option {
+fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive) -> Option {
debug it => _1;
let mut _0: std::option::Option;
- scope 1 (inlined iter::range::>::next) {
+ scope 1 (inlined iter::range::>::next) {
}
bb0: {
- _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
+ _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
}
bb1: {
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir
index f54d003c662f6..98cd58284dfaf 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir
@@ -1,13 +1,13 @@
// MIR for `range_inclusive_iter_next` after PreCodegen
-fn range_inclusive_iter_next(_1: &mut RangeInclusive) -> Option {
+fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive) -> Option {
debug it => _1;
let mut _0: std::option::Option;
- scope 1 (inlined iter::range::>::next) {
+ scope 1 (inlined iter::range::>::next) {
}
bb0: {
- _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
+ _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
}
bb1: {
diff --git a/tests/ui/const-generics/std/const-generics-range.full.stderr b/tests/ui/const-generics/std/const-generics-range.full.stderr
index 5bf48ad738587..2b5c63e6643d8 100644
--- a/tests/ui/const-generics/std/const-generics-range.full.stderr
+++ b/tests/ui/const-generics/std/const-generics-range.full.stderr
@@ -4,7 +4,7 @@ error[E0741]: `std::ops::Range` must implement `ConstParamTy` to be used
LL | struct _Range>;
| ^^^^^^^^^^^^^^^^^^^^^^
-error[E0741]: `RangeFrom` must implement `ConstParamTy` to be used as the type of a const generic parameter
+error[E0741]: `std::ops::RangeFrom` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/const-generics-range.rs:13:28
|
LL | struct _RangeFrom>;
@@ -16,7 +16,7 @@ error[E0741]: `RangeFull` must implement `ConstParamTy` to be used as the type o
LL | struct _RangeFull;
| ^^^^^^^^^^^^^^^^^^^
-error[E0741]: `RangeInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter
+error[E0741]: `std::ops::RangeInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/const-generics-range.rs:24:33
|
LL | struct _RangeInclusive>;
diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr
index fd23b9b248a06..04e3fe744534f 100644
--- a/tests/ui/const-generics/std/const-generics-range.min.stderr
+++ b/tests/ui/const-generics/std/const-generics-range.min.stderr
@@ -10,7 +10,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|
-error: `RangeFrom` is forbidden as the type of a const generic parameter
+error: `std::ops::RangeFrom` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:13:28
|
LL | struct _RangeFrom>;
@@ -34,7 +34,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|
-error: `RangeInclusive` is forbidden as the type of a const generic parameter
+error: `std::ops::RangeInclusive` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:24:33
|
LL | struct _RangeInclusive>;
diff --git a/tests/ui/const-generics/std/const-generics-range.rs b/tests/ui/const-generics/std/const-generics-range.rs
index f959f1e2949a8..3a238ed177e0f 100644
--- a/tests/ui/const-generics/std/const-generics-range.rs
+++ b/tests/ui/const-generics/std/const-generics-range.rs
@@ -11,7 +11,7 @@ const RANGE : _Range<{ 0 .. 1000 }> = _Range;
// `RangeFrom` should be usable within const generics:
struct _RangeFrom>;
-//[min]~^ ERROR `RangeFrom` is forbidden
+//[min]~^ ERROR `std::ops::RangeFrom` is forbidden
const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom;
// `RangeFull` should be usable within const generics:
@@ -22,7 +22,7 @@ const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull;
// Regression test for #70155
// `RangeInclusive` should be usable within const generics:
struct _RangeInclusive>;
-//[min]~^ ERROR `RangeInclusive` is forbidden
+//[min]~^ ERROR `std::ops::RangeInclusive` is forbidden
const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive;
// `RangeTo` should be usable within const generics:
diff --git a/tests/ui/issues/issue-76191.stderr b/tests/ui/issues/issue-76191.stderr
index 3702bfb776991..3b89ec7cb9c97 100644
--- a/tests/ui/issues/issue-76191.stderr
+++ b/tests/ui/issues/issue-76191.stderr
@@ -21,7 +21,7 @@ LL | RANGE => {}
| `RANGE` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
- found struct `RangeInclusive`
+ found struct `std::ops::RangeInclusive`
help: you may want to move the range into the match block
|
LL | 0..=255 => {}
@@ -43,7 +43,7 @@ LL | RANGE2 => {}
| `RANGE2` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
- found struct `RangeInclusive`
+ found struct `std::ops::RangeInclusive`
= note: constants only support matching by type, if you meant to match against a range of values, consider using a range pattern like `min ..= max` in the match block
error: aborting due to 3 previous errors
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
index 25943d11fc479..fc44c824043ba 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
@@ -5,7 +5,7 @@
fn main() {
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
- //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
index 696214c0a3cdc..973fe7ade602f 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
@@ -1,14 +1,14 @@
-error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
+error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:29
|
LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
+ = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
= note: expected a closure with arguments `(i32,)`
- found a closure with arguments `(& as Iterator>::Item,)`
+ found a closure with arguments `(& as Iterator>::Item,)`
note: required by a bound in `find`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
index 9e44489cbf17e..a96df10db355b 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
@@ -5,7 +5,7 @@
fn main() {
let _ = (-10..=10).find(|x: i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
- //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr
index 1c5a0d65142f8..bb60c33595c25 100644
--- a/tests/ui/never_type/issue-52443.stderr
+++ b/tests/ui/never_type/issue-52443.stderr
@@ -31,7 +31,7 @@ help: give the `break` a value of the expected type
LL | [(); loop { break 42 }];
| ++
-error[E0015]: cannot use `for` loop on `RangeFrom` in constants
+error[E0015]: cannot use `for` loop on `std::ops::RangeFrom` in constants
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
@@ -39,7 +39,7 @@ LL | [(); { for _ in 0usize.. {}; 0}];
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
-error[E0015]: cannot use `for` loop on `RangeFrom` in constants
+error[E0015]: cannot use `for` loop on `std::ops::RangeFrom` in constants
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
diff --git a/tests/ui/range/issue-54505-no-literals.stderr b/tests/ui/range/issue-54505-no-literals.stderr
index 5894bb6ba553f..c6d4384bcd33c 100644
--- a/tests/ui/range/issue-54505-no-literals.stderr
+++ b/tests/ui/range/issue-54505-no-literals.stderr
@@ -47,7 +47,7 @@ LL | take_range(std::ops::RangeFrom { start: 1 });
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
@@ -67,7 +67,7 @@ LL | take_range(::std::ops::RangeFrom { start: 1 });
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
@@ -127,7 +127,7 @@ LL | take_range(std::ops::RangeInclusive::new(0, 1));
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeInclusive<{integer}>`
+ found struct `std::ops::RangeInclusive<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
@@ -147,7 +147,7 @@ LL | take_range(::std::ops::RangeInclusive::new(0, 1));
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeInclusive<{integer}>`
+ found struct `std::ops::RangeInclusive<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
diff --git a/tests/ui/range/issue-54505.stderr b/tests/ui/range/issue-54505.stderr
index 291e097e8659f..8b669b2910f6b 100644
--- a/tests/ui/range/issue-54505.stderr
+++ b/tests/ui/range/issue-54505.stderr
@@ -27,7 +27,7 @@ LL | take_range(1..);
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
note: function defined here
--> $DIR/issue-54505.rs:10:4
|
@@ -72,7 +72,7 @@ LL | take_range(0..=1);
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeInclusive<{integer}>`
+ found struct `std::ops::RangeInclusive<{integer}>`
note: function defined here
--> $DIR/issue-54505.rs:10:4
|
diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr
index f77601bc43cd4..37669dd3f47c7 100644
--- a/tests/ui/range/range-1.stderr
+++ b/tests/ui/range/range-1.stderr
@@ -30,7 +30,7 @@ LL | let range = *arr..;
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[{integer}]`
-note: required by an implicit `Sized` bound in `RangeFrom`
+note: required by an implicit `Sized` bound in `std::ops::RangeFrom`
--> $SRC_DIR/core/src/ops/range.rs:LL:COL
error: aborting due to 3 previous errors
diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
index 8b48ee9f1247b..c0162ec2cab84 100644
--- a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
+++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
@@ -22,7 +22,7 @@ LL | let _: f64 = 1..;
| expected due to this
|
= note: expected type `f64`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
help: remove the unnecessary `.` operator for a floating point literal
|
LL | let _: f64 = 1.;
From f530a29944ff1eba9a146704ba2f13b94331be5d Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Mon, 27 Jan 2025 13:32:10 -0700
Subject: [PATCH 2/2] implement unstable `new_range` feature
for RFC 3550, tracking issue #123741
---
compiler/rustc_ast_lowering/src/expr.rs | 35 +++++++++++---
compiler/rustc_feature/src/unstable.rs | 2 +
compiler/rustc_hir/src/hir.rs | 41 +++++++++++++++-
compiler/rustc_hir/src/lang_items.rs | 5 ++
.../rustc_hir_typeck/src/method/suggest.rs | 4 ++
compiler/rustc_span/src/symbol.rs | 4 ++
library/core/src/range.rs | 3 ++
.../src/language-features/new-range.md | 9 ++++
.../feature-gates/feature-gate-new_range.rs | 10 ++++
.../feature-gate-new_range.stderr | 48 +++++++++++++++++++
...rg-type-mismatch-issue-45727.current.fixed | 2 +-
...-arg-type-mismatch-issue-45727.next.stderr | 8 ++--
.../closure-arg-type-mismatch-issue-45727.rs | 2 +-
tests/ui/new-range/disabled.rs | 27 +++++++++++
tests/ui/new-range/enabled.rs | 24 ++++++++++
15 files changed, 210 insertions(+), 14 deletions(-)
create mode 100644 src/doc/unstable-book/src/language-features/new-range.md
create mode 100644 tests/ui/feature-gates/feature-gate-new_range.rs
create mode 100644 tests/ui/feature-gates/feature-gate-new_range.stderr
create mode 100644 tests/ui/new-range/disabled.rs
create mode 100644 tests/ui/new-range/enabled.rs
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 1267281f73ebe..98d6372ca8965 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -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)
}
@@ -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,
}
}
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 1a216ebf117c6..7a30c8d4737b9 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -568,6 +568,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.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index af2f86b67e007..5483b97a7f4dd 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -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(
@@ -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)
@@ -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,
..
)
),
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 02bc069fc5f27..3edf1370d2b44 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -415,6 +415,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;
}
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index e4a6a0fedc5a7..fb48f5dca8949 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2410,6 +2410,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)
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6f1d3a74a8165..dca96b74174d8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -294,9 +294,12 @@ symbols! {
ProceduralMasqueradeDummyType,
Range,
RangeBounds,
+ RangeCopy,
RangeFrom,
+ RangeFromCopy,
RangeFull,
RangeInclusive,
+ RangeInclusiveCopy,
RangeTo,
RangeToInclusive,
Rc,
@@ -1367,6 +1370,7 @@ symbols! {
new_lower_hex,
new_octal,
new_pointer,
+ new_range,
new_unchecked,
new_upper_exp,
new_upper_hex,
diff --git a/library/core/src/range.rs b/library/core/src/range.rs
index 427526fd14b91..6a62928873fe8 100644
--- a/library/core/src/range.rs
+++ b/library/core/src/range.rs
@@ -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 {
@@ -205,6 +206,7 @@ impl From> for Range {
/// 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 {
@@ -388,6 +390,7 @@ impl From> for RangeInclusive {
/// 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 {
diff --git a/src/doc/unstable-book/src/language-features/new-range.md b/src/doc/unstable-book/src/language-features/new-range.md
new file mode 100644
index 0000000000000..e7464f31e5377
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/new-range.md
@@ -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.
diff --git a/tests/ui/feature-gates/feature-gate-new_range.rs b/tests/ui/feature-gates/feature-gate-new_range.rs
new file mode 100644
index 0000000000000..ecb73546d6a60
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-new_range.rs
@@ -0,0 +1,10 @@
+#![feature(new_range_api)]
+
+fn main() {
+ let a: core::range::RangeFrom = 1..;
+ //~^ mismatched types
+ let b: core::range::Range = 2..3;
+ //~^ mismatched types
+ let c: core::range::RangeInclusive = 4..=5;
+ //~^ mismatched types
+}
diff --git a/tests/ui/feature-gates/feature-gate-new_range.stderr b/tests/ui/feature-gates/feature-gate-new_range.stderr
new file mode 100644
index 0000000000000..c4241390418b6
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-new_range.stderr
@@ -0,0 +1,48 @@
+error[E0308]: mismatched types
+ --> $DIR/feature-gate-new_range.rs:4:41
+ |
+LL | let a: core::range::RangeFrom = 1..;
+ | -------------------------- ^^^ expected `RangeFrom`, found `RangeFrom<{integer}>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `std::range::RangeFrom`
+ found struct `std::ops::RangeFrom<{integer}>`
+help: call `Into::into` on this expression to convert `std::ops::RangeFrom<{integer}>` into `std::range::RangeFrom`
+ |
+LL | let a: core::range::RangeFrom = 1...into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/feature-gate-new_range.rs:6:37
+ |
+LL | let b: core::range::Range = 2..3;
+ | ---------------------- ^^^^ expected `Range`, found `Range<{integer}>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `std::range::Range`
+ found struct `std::ops::Range<{integer}>`
+help: call `Into::into` on this expression to convert `std::ops::Range<{integer}>` into `std::range::Range`
+ |
+LL | let b: core::range::Range = 2..3.into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/feature-gate-new_range.rs:8:46
+ |
+LL | let c: core::range::RangeInclusive = 4..=5;
+ | ------------------------------- ^^^^^ expected `RangeInclusive`, found `RangeInclusive<{integer}>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `std::range::RangeInclusive`
+ found struct `std::ops::RangeInclusive<{integer}>`
+help: call `Into::into` on this expression to convert `std::ops::RangeInclusive<{integer}>` into `std::range::RangeInclusive`
+ |
+LL | let c: core::range::RangeInclusive = 4..=5.into();
+ | +++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
index fc44c824043ba..ba46a447802c8 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
@@ -9,5 +9,5 @@ fn main() {
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
- //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
}
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
index 973fe7ade602f..b716131061993 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
@@ -18,17 +18,17 @@ error[E0271]: expected `RangeInclusive<{integer}>` to be an iterator that yields
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
| ^^^^ expected `&&i32`, found integer
-error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
+error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:29
|
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
+ = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
= note: expected a closure with arguments `(&&&i32,)`
- found a closure with arguments `(& as Iterator>::Item,)`
+ found a closure with arguments `(& as Iterator>::Item,)`
note: required by a bound in `find`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
index a96df10db355b..0fd56707763e9 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
@@ -9,5 +9,5 @@ fn main() {
let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
- //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
}
diff --git a/tests/ui/new-range/disabled.rs b/tests/ui/new-range/disabled.rs
new file mode 100644
index 0000000000000..1a5fe3f974360
--- /dev/null
+++ b/tests/ui/new-range/disabled.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+#![feature(new_range_api)]
+
+fn main() {
+ // Unchanged
+ let a: core::range::RangeFull = ..;
+ let b: core::range::RangeTo = ..2;
+ let c: core::range::RangeToInclusive = ..=3;
+
+ let _: core::ops::RangeFull = a;
+ let _: core::ops::RangeTo = b;
+ let _: core::ops::RangeToInclusive = c;
+
+ // Changed
+ let a: core::range::legacy::RangeFrom = 1..;
+ let b: core::range::legacy::Range = 2..3;
+ let c: core::range::legacy::RangeInclusive = 4..=5;
+
+ let a: core::ops::RangeFrom = a;
+ let b: core::ops::Range = b;
+ let c: core::ops::RangeInclusive = c;
+
+ let _: core::ops::RangeFrom = a.into_iter();
+ let _: core::ops::Range = b.into_iter();
+ let _: core::ops::RangeInclusive = c.into_iter();
+}
diff --git a/tests/ui/new-range/enabled.rs b/tests/ui/new-range/enabled.rs
new file mode 100644
index 0000000000000..a5fb76ad52b72
--- /dev/null
+++ b/tests/ui/new-range/enabled.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+#![feature(new_range_api)]
+#![feature(new_range)]
+
+fn main() {
+ // Unchanged
+ let a: core::range::RangeFull = ..;
+ let b: core::range::RangeTo = ..2;
+ let c: core::range::RangeToInclusive = ..=3;
+
+ let _: core::ops::RangeFull = a;
+ let _: core::ops::RangeTo = b;
+ let _: core::ops::RangeToInclusive = c;
+
+ // Changed
+ let a: core::range::RangeFrom = 1..;
+ let b: core::range::Range = 2..3;
+ let c: core::range::RangeInclusive = 4..=5;
+
+ let _: core::range::IterRangeFrom = a.into_iter();
+ let _: core::range::IterRange = b.into_iter();
+ let _: core::range::IterRangeInclusive = c.into_iter();
+}