@@ -13,7 +13,7 @@ use rustc_ast::util::parser::ExprPrecedence;
13
13
use rustc_data_structures:: sync:: { par_for_each_in, Send , Sync } ;
14
14
use rustc_macros:: HashStable_Generic ;
15
15
use rustc_span:: def_id:: LocalDefId ;
16
- use rustc_span:: source_map:: { SourceMap , Spanned } ;
16
+ use rustc_span:: source_map:: Spanned ;
17
17
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
18
18
use rustc_span:: { MultiSpan , Span , DUMMY_SP } ;
19
19
use rustc_target:: asm:: InlineAsmRegOrRegClass ;
@@ -1495,58 +1495,28 @@ impl Expr<'_> {
1495
1495
1496
1496
/// Checks if the specified expression is a built-in range literal.
1497
1497
/// (See: `LoweringContext::lower_expr()`).
1498
- ///
1499
- /// FIXME(#60607): This function is a hack. If and when we have `QPath::Lang(...)`,
1500
- /// we can use that instead as simpler, more reliable mechanism, as opposed to using `SourceMap`.
1501
- pub fn is_range_literal ( sm : & SourceMap , expr : & Expr < ' _ > ) -> bool {
1502
- // Returns whether the given path represents a (desugared) range,
1503
- // either in std or core, i.e. has either a `::std::ops::Range` or
1504
- // `::core::ops::Range` prefix.
1505
- fn is_range_path ( path : & Path < ' _ > ) -> bool {
1506
- let segs: Vec < _ > = path. segments . iter ( ) . map ( |seg| seg. ident . to_string ( ) ) . collect ( ) ;
1507
- let segs: Vec < _ > = segs. iter ( ) . map ( |seg| & * * seg) . collect ( ) ;
1508
-
1509
- // "{{root}}" is the equivalent of `::` prefix in `Path`.
1510
- if let [ "{{root}}" , std_core, "ops" , range] = segs. as_slice ( ) {
1511
- ( * std_core == "std" || * std_core == "core" ) && range. starts_with ( "Range" )
1512
- } else {
1513
- false
1514
- }
1515
- } ;
1516
-
1517
- // Check whether a span corresponding to a range expression is a
1518
- // range literal, rather than an explicit struct or `new()` call.
1519
- fn is_lit ( sm : & SourceMap , span : & Span ) -> bool {
1520
- sm. span_to_snippet ( * span) . map ( |range_src| range_src. contains ( ".." ) ) . unwrap_or ( false )
1521
- } ;
1522
-
1498
+ pub fn is_range_literal ( expr : & Expr < ' _ > ) -> bool {
1523
1499
match expr. kind {
1524
1500
// All built-in range literals but `..=` and `..` desugar to `Struct`s.
1525
- ExprKind :: Struct ( ref qpath, _, _) => {
1526
- if let QPath :: Resolved ( None , ref path) = * * qpath {
1527
- return is_range_path ( & path) && is_lit ( sm, & expr. span ) ;
1528
- }
1529
- }
1530
-
1531
- // `..` desugars to its struct path.
1532
- ExprKind :: Path ( QPath :: Resolved ( None , ref path) ) => {
1533
- return is_range_path ( & path) && is_lit ( sm, & expr. span ) ;
1534
- }
1501
+ ExprKind :: Struct ( ref qpath, _, _) => matches ! (
1502
+ * * qpath,
1503
+ QPath :: LangItem (
1504
+ LangItem :: Range
1505
+ | LangItem :: RangeTo
1506
+ | LangItem :: RangeFrom
1507
+ | LangItem :: RangeFull
1508
+ | LangItem :: RangeToInclusive ,
1509
+ _,
1510
+ )
1511
+ ) ,
1535
1512
1536
1513
// `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
1537
1514
ExprKind :: Call ( ref func, _) => {
1538
- if let ExprKind :: Path ( QPath :: TypeRelative ( ref ty, ref segment) ) = func. kind {
1539
- if let TyKind :: Path ( QPath :: Resolved ( None , ref path) ) = ty. kind {
1540
- let new_call = segment. ident . name == sym:: new;
1541
- return is_range_path ( & path) && is_lit ( sm, & expr. span ) && new_call;
1542
- }
1543
- }
1515
+ matches ! ( func. kind, ExprKind :: Path ( QPath :: LangItem ( LangItem :: RangeInclusiveNew , _) ) )
1544
1516
}
1545
1517
1546
- _ => { }
1518
+ _ => false ,
1547
1519
}
1548
-
1549
- false
1550
1520
}
1551
1521
1552
1522
#[ derive( Debug , HashStable_Generic ) ]
0 commit comments