Skip to content

Commit 7e043b6

Browse files
committed
implement unstable new_range feature
for RFC 3550, tracking issue rust-lang#123741
1 parent e3a0a05 commit 7e043b6

File tree

12 files changed

+209
-7
lines changed

12 files changed

+209
-7
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+33-6
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
284284
ExprKind::Index(el, er, brackets_span) => {
285285
hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er), *brackets_span)
286286
}
287+
ExprKind::Range(e1, e2, lims) if self.tcx.features().new_range() => {
288+
self.lower_expr_range::<true>(e.span, e1.as_deref(), e2.as_deref(), *lims)
289+
}
287290
ExprKind::Range(Some(e1), Some(e2), RangeLimits::Closed) => {
288291
self.lower_expr_range_closed(e.span, e1, e2)
289292
}
290293
ExprKind::Range(e1, e2, lims) => {
291-
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
294+
self.lower_expr_range::<false>(e.span, e1.as_deref(), e2.as_deref(), *lims)
292295
}
293296
ExprKind::Underscore => {
294297
let guar = self.dcx().emit_err(UnderscoreExprLhsAssign { span: e.span });
@@ -1497,7 +1500,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
14971500
hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
14981501
}
14991502

1500-
fn lower_expr_range(
1503+
fn lower_expr_range<const NEW_RANGE: bool>(
15011504
&mut self,
15021505
span: Span,
15031506
e1: Option<&Expr>,
@@ -1508,15 +1511,39 @@ impl<'hir> LoweringContext<'_, 'hir> {
15081511

15091512
let lang_item = match (e1, e2, lims) {
15101513
(None, None, HalfOpen) => hir::LangItem::RangeFull,
1511-
(Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
1514+
(Some(..), None, HalfOpen) => {
1515+
if NEW_RANGE {
1516+
hir::LangItem::RangeFromCopy
1517+
} else {
1518+
hir::LangItem::RangeFrom
1519+
}
1520+
}
15121521
(None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
1513-
(Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
1522+
(Some(..), Some(..), HalfOpen) => {
1523+
if NEW_RANGE {
1524+
hir::LangItem::RangeCopy
1525+
} else {
1526+
hir::LangItem::Range
1527+
}
1528+
}
15141529
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
1515-
(Some(..), Some(..), Closed) => unreachable!(),
1530+
(Some(..), Some(..), Closed) => {
1531+
if NEW_RANGE {
1532+
hir::LangItem::RangeInclusiveCopy
1533+
} else {
1534+
unreachable!() // Handled by lower_expr_range_closed
1535+
}
1536+
}
15161537
(start, None, Closed) => {
15171538
self.dcx().emit_err(InclusiveRangeWithNoEnd { span });
15181539
match start {
1519-
Some(..) => hir::LangItem::RangeFrom,
1540+
Some(..) => {
1541+
if NEW_RANGE {
1542+
hir::LangItem::RangeFromCopy
1543+
} else {
1544+
hir::LangItem::RangeFrom
1545+
}
1546+
}
15201547
None => hir::LangItem::RangeFull,
15211548
}
15221549
}

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,8 @@ declare_features! (
568568
(unstable, never_type, "1.13.0", Some(35121)),
569569
/// Allows diverging expressions to fall back to `!` rather than `()`.
570570
(unstable, never_type_fallback, "1.41.0", Some(65992)),
571+
/// Switch `..` syntax to use the new (`Copy + IntoIterator`) range types.
572+
(unstable, new_range, "CURRENT_RUSTC_VERSION", Some(123741)),
571573
/// Allows `#![no_core]`.
572574
(unstable, no_core, "1.3.0", Some(29639)),
573575
/// Allows the use of `no_sanitize` attribute.

compiler/rustc_hir/src/hir.rs

+40-1
Original file line numberDiff line numberDiff line change
@@ -2316,6 +2316,18 @@ impl Expr<'_> {
23162316
[val2],
23172317
StructTailExpr::None,
23182318
),
2319+
)
2320+
| (
2321+
ExprKind::Struct(
2322+
QPath::LangItem(LangItem::RangeFromCopy, _),
2323+
[val1],
2324+
StructTailExpr::None,
2325+
),
2326+
ExprKind::Struct(
2327+
QPath::LangItem(LangItem::RangeFromCopy, _),
2328+
[val2],
2329+
StructTailExpr::None,
2330+
),
23192331
) => val1.expr.equivalent_for_indexing(val2.expr),
23202332
(
23212333
ExprKind::Struct(
@@ -2328,6 +2340,30 @@ impl Expr<'_> {
23282340
[val2, val4],
23292341
StructTailExpr::None,
23302342
),
2343+
)
2344+
| (
2345+
ExprKind::Struct(
2346+
QPath::LangItem(LangItem::RangeCopy, _),
2347+
[val1, val3],
2348+
StructTailExpr::None,
2349+
),
2350+
ExprKind::Struct(
2351+
QPath::LangItem(LangItem::RangeCopy, _),
2352+
[val2, val4],
2353+
StructTailExpr::None,
2354+
),
2355+
)
2356+
| (
2357+
ExprKind::Struct(
2358+
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
2359+
[val1, val3],
2360+
StructTailExpr::None,
2361+
),
2362+
ExprKind::Struct(
2363+
QPath::LangItem(LangItem::RangeInclusiveCopy, _),
2364+
[val2, val4],
2365+
StructTailExpr::None,
2366+
),
23312367
) => {
23322368
val1.expr.equivalent_for_indexing(val2.expr)
23332369
&& val3.expr.equivalent_for_indexing(val4.expr)
@@ -2357,7 +2393,10 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
23572393
| LangItem::RangeTo
23582394
| LangItem::RangeFrom
23592395
| LangItem::RangeFull
2360-
| LangItem::RangeToInclusive,
2396+
| LangItem::RangeToInclusive
2397+
| LangItem::RangeCopy
2398+
| LangItem::RangeFromCopy
2399+
| LangItem::RangeInclusiveCopy,
23612400
..
23622401
)
23632402
),

compiler/rustc_hir/src/lang_items.rs

+5
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,11 @@ language_item_table! {
415415
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
416416
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
417417

418+
// `new_range` types that are `Copy + IntoIterator`
419+
RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
420+
RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None;
421+
RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
422+
418423
String, sym::String, string, Target::Struct, GenericRequirement::None;
419424
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
420425
}

compiler/rustc_hir_typeck/src/method/suggest.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2411,6 +2411,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24112411
let lang_item = match parent_expr.kind {
24122412
ExprKind::Struct(qpath, _, _) => match *qpath {
24132413
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
2414+
QPath::LangItem(LangItem::RangeCopy, ..) => Some(LangItem::RangeCopy),
2415+
QPath::LangItem(LangItem::RangeInclusiveCopy, ..) => {
2416+
Some(LangItem::RangeInclusiveCopy)
2417+
}
24142418
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
24152419
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
24162420
Some(LangItem::RangeToInclusive)

compiler/rustc_span/src/symbol.rs

+4
Original file line numberDiff line numberDiff line change
@@ -294,9 +294,12 @@ symbols! {
294294
ProceduralMasqueradeDummyType,
295295
Range,
296296
RangeBounds,
297+
RangeCopy,
297298
RangeFrom,
299+
RangeFromCopy,
298300
RangeFull,
299301
RangeInclusive,
302+
RangeInclusiveCopy,
300303
RangeTo,
301304
RangeToInclusive,
302305
Rc,
@@ -1367,6 +1370,7 @@ symbols! {
13671370
new_lower_hex,
13681371
new_octal,
13691372
new_pointer,
1373+
new_range,
13701374
new_unchecked,
13711375
new_upper_exp,
13721376
new_upper_hex,

library/core/src/range.rs

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, Rang
4848
/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
4949
/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
5050
/// ```
51+
#[cfg_attr(not(bootstrap), lang = "RangeCopy")]
5152
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
5253
#[unstable(feature = "new_range_api", issue = "125687")]
5354
pub struct Range<Idx> {
@@ -205,6 +206,7 @@ impl<T> From<legacy::Range<T>> for Range<T> {
205206
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
206207
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
207208
/// ```
209+
#[cfg_attr(not(bootstrap), lang = "RangeInclusiveCopy")]
208210
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
209211
#[unstable(feature = "new_range_api", issue = "125687")]
210212
pub struct RangeInclusive<Idx> {
@@ -388,6 +390,7 @@ impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
388390
/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
389391
/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
390392
/// ```
393+
#[cfg_attr(not(bootstrap), lang = "RangeFromCopy")]
391394
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
392395
#[unstable(feature = "new_range_api", issue = "125687")]
393396
pub struct RangeFrom<Idx> {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# `new_range`
2+
3+
The tracking issue for this feature is: [#123741]
4+
5+
[#123741]: https://github.com/rust-lang/rust/issues/123741
6+
7+
---
8+
9+
Switch the syntaxes `a..`, `a..b`, and `a..=b` to resolve the new range types.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(new_range_api)]
2+
3+
fn main() {
4+
let a: core::range::RangeFrom<u8> = 1..;
5+
//~^ mismatched types
6+
let b: core::range::Range<u8> = 2..3;
7+
//~^ mismatched types
8+
let c: core::range::RangeInclusive<u8> = 4..=5;
9+
//~^ mismatched types
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/feature-gate-new_range.rs:4:41
3+
|
4+
LL | let a: core::range::RangeFrom<u8> = 1..;
5+
| -------------------------- ^^^ expected `RangeFrom<u8>`, found `RangeFrom<{integer}>`
6+
| |
7+
| expected due to this
8+
|
9+
= note: expected struct `std::range::RangeFrom<u8>`
10+
found struct `std::ops::RangeFrom<{integer}>`
11+
help: call `Into::into` on this expression to convert `std::ops::RangeFrom<{integer}>` into `std::range::RangeFrom<u8>`
12+
|
13+
LL | let a: core::range::RangeFrom<u8> = 1...into();
14+
| +++++++
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/feature-gate-new_range.rs:6:37
18+
|
19+
LL | let b: core::range::Range<u8> = 2..3;
20+
| ---------------------- ^^^^ expected `Range<u8>`, found `Range<{integer}>`
21+
| |
22+
| expected due to this
23+
|
24+
= note: expected struct `std::range::Range<u8>`
25+
found struct `std::ops::Range<{integer}>`
26+
help: call `Into::into` on this expression to convert `std::ops::Range<{integer}>` into `std::range::Range<u8>`
27+
|
28+
LL | let b: core::range::Range<u8> = 2..3.into();
29+
| +++++++
30+
31+
error[E0308]: mismatched types
32+
--> $DIR/feature-gate-new_range.rs:8:46
33+
|
34+
LL | let c: core::range::RangeInclusive<u8> = 4..=5;
35+
| ------------------------------- ^^^^^ expected `RangeInclusive<u8>`, found `RangeInclusive<{integer}>`
36+
| |
37+
| expected due to this
38+
|
39+
= note: expected struct `std::range::RangeInclusive<u8>`
40+
found struct `std::ops::RangeInclusive<{integer}>`
41+
help: call `Into::into` on this expression to convert `std::ops::RangeInclusive<{integer}>` into `std::range::RangeInclusive<u8>`
42+
|
43+
LL | let c: core::range::RangeInclusive<u8> = 4..=5.into();
44+
| +++++++
45+
46+
error: aborting due to 3 previous errors
47+
48+
For more information about this error, try `rustc --explain E0308`.

tests/ui/new-range/disabled.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ check-pass
2+
3+
#![feature(new_range_api)]
4+
5+
fn main() {
6+
// Unchanged
7+
let a: core::range::RangeFull = ..;
8+
let b: core::range::RangeTo<u8> = ..2;
9+
let c: core::range::RangeToInclusive<u8> = ..=3;
10+
11+
let _: core::ops::RangeFull = a;
12+
let _: core::ops::RangeTo<u8> = b;
13+
let _: core::ops::RangeToInclusive<u8> = c;
14+
15+
// Changed
16+
let a: core::range::legacy::RangeFrom<u8> = 1..;
17+
let b: core::range::legacy::Range<u8> = 2..3;
18+
let c: core::range::legacy::RangeInclusive<u8> = 4..=5;
19+
20+
let a: core::ops::RangeFrom<u8> = a;
21+
let b: core::ops::Range<u8> = b;
22+
let c: core::ops::RangeInclusive<u8> = c;
23+
24+
let _: core::ops::RangeFrom<u8> = a.into_iter();
25+
let _: core::ops::Range<u8> = b.into_iter();
26+
let _: core::ops::RangeInclusive<u8> = c.into_iter();
27+
}

tests/ui/new-range/enabled.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ check-pass
2+
3+
#![feature(new_range_api)]
4+
#![feature(new_range)]
5+
6+
fn main() {
7+
// Unchanged
8+
let a: core::range::RangeFull = ..;
9+
let b: core::range::RangeTo<u8> = ..2;
10+
let c: core::range::RangeToInclusive<u8> = ..=3;
11+
12+
let _: core::ops::RangeFull = a;
13+
let _: core::ops::RangeTo<u8> = b;
14+
let _: core::ops::RangeToInclusive<u8> = c;
15+
16+
// Changed
17+
let a: core::range::RangeFrom<u8> = 1..;
18+
let b: core::range::Range<u8> = 2..3;
19+
let c: core::range::RangeInclusive<u8> = 4..=5;
20+
21+
let _: core::range::IterRangeFrom<u8> = a.into_iter();
22+
let _: core::range::IterRange<u8> = b.into_iter();
23+
let _: core::range::IterRangeInclusive<u8> = c.into_iter();
24+
}

0 commit comments

Comments
 (0)