@@ -13,7 +13,7 @@ use rustc_ast::util::parser::ExprPrecedence;
1313use rustc_data_structures:: sync:: { par_for_each_in, Send , Sync } ;
1414use rustc_macros:: HashStable_Generic ;
1515use rustc_span:: def_id:: LocalDefId ;
16- use rustc_span:: source_map:: { SourceMap , Spanned } ;
16+ use rustc_span:: source_map:: Spanned ;
1717use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
1818use rustc_span:: { MultiSpan , Span , DUMMY_SP } ;
1919use rustc_target:: asm:: InlineAsmRegOrRegClass ;
@@ -1495,58 +1495,28 @@ impl Expr<'_> {
14951495
14961496/// Checks if the specified expression is a built-in range literal.
14971497/// (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 {
15231499 match expr. kind {
15241500 // 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+ ) ,
15351512
15361513 // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
15371514 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 , _) ) )
15441516 }
15451517
1546- _ => { }
1518+ _ => false ,
15471519 }
1548-
1549- false
15501520}
15511521
15521522#[ derive( Debug , HashStable_Generic ) ]
0 commit comments