@@ -210,30 +210,12 @@ impl<'a> Parser<'a> {
210210 lhs = self . parse_assoc_op_cast ( lhs, lhs_span, ExprKind :: Cast ) ?;
211211 continue ;
212212 } else if op == AssocOp :: Colon {
213- let maybe_path = self . could_ascription_be_path ( & lhs. kind ) ;
214- self . last_type_ascription = Some ( ( self . prev_span , maybe_path) ) ;
215-
216- lhs = self . parse_assoc_op_cast ( lhs, lhs_span, ExprKind :: Type ) ?;
217- self . sess . gated_spans . gate ( sym:: type_ascription, lhs. span ) ;
213+ lhs = self . parse_assoc_op_ascribe ( lhs, lhs_span) ?;
218214 continue ;
219215 } else if op == AssocOp :: DotDot || op == AssocOp :: DotDotEq {
220216 // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to
221217 // generalise it to the Fixity::None code.
222- //
223- // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other
224- // two variants are handled with `parse_prefix_range_expr` call above.
225- let rhs = if self . is_at_start_of_range_notation_rhs ( ) {
226- Some ( self . parse_assoc_expr_with ( prec + 1 , LhsExpr :: NotYetParsed ) ?)
227- } else {
228- None
229- } ;
230- let ( lhs_span, rhs_span) =
231- ( lhs. span , if let Some ( ref x) = rhs { x. span } else { cur_op_span } ) ;
232- let limits =
233- if op == AssocOp :: DotDot { RangeLimits :: HalfOpen } else { RangeLimits :: Closed } ;
234-
235- let r = self . mk_range ( Some ( lhs) , rhs, limits) ?;
236- lhs = self . mk_expr ( lhs_span. to ( rhs_span) , r, AttrVec :: new ( ) ) ;
218+ lhs = self . parse_range_expr ( prec, lhs, op, cur_op_span) ?;
237219 break ;
238220 }
239221
@@ -393,6 +375,27 @@ impl<'a> Parser<'a> {
393375 && !classify:: expr_requires_semi_to_be_stmt ( e)
394376 }
395377
378+ /// Parses `x..y`, `x..=y`, and `x..`/`x..=`.
379+ /// The other two variants are handled in `parse_prefix_range_expr` below.
380+ fn parse_range_expr (
381+ & mut self ,
382+ prec : usize ,
383+ lhs : P < Expr > ,
384+ op : AssocOp ,
385+ cur_op_span : Span ,
386+ ) -> PResult < ' a , P < Expr > > {
387+ let rhs = if self . is_at_start_of_range_notation_rhs ( ) {
388+ Some ( self . parse_assoc_expr_with ( prec + 1 , LhsExpr :: NotYetParsed ) ?)
389+ } else {
390+ None
391+ } ;
392+ let rhs_span = rhs. as_ref ( ) . map_or ( cur_op_span, |x| x. span ) ;
393+ let span = lhs. span . to ( rhs_span) ;
394+ let limits =
395+ if op == AssocOp :: DotDot { RangeLimits :: HalfOpen } else { RangeLimits :: Closed } ;
396+ Ok ( self . mk_expr ( span, self . mk_range ( Some ( lhs) , rhs, limits) ?, AttrVec :: new ( ) ) )
397+ }
398+
396399 fn is_at_start_of_range_notation_rhs ( & self ) -> bool {
397400 if self . token . can_begin_expr ( ) {
398401 // Parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
@@ -615,6 +618,14 @@ impl<'a> Parser<'a> {
615618 }
616619 }
617620
621+ fn parse_assoc_op_ascribe ( & mut self , lhs : P < Expr > , lhs_span : Span ) -> PResult < ' a , P < Expr > > {
622+ let maybe_path = self . could_ascription_be_path ( & lhs. kind ) ;
623+ self . last_type_ascription = Some ( ( self . prev_span , maybe_path) ) ;
624+ let lhs = self . parse_assoc_op_cast ( lhs, lhs_span, ExprKind :: Type ) ?;
625+ self . sess . gated_spans . gate ( sym:: type_ascription, lhs. span ) ;
626+ Ok ( lhs)
627+ }
628+
618629 /// Parse `& mut? <expr>` or `& raw [ const | mut ] <expr>`.
619630 fn parse_borrow_expr ( & mut self , lo : Span ) -> PResult < ' a , ( Span , ExprKind ) > {
620631 self . expect_and ( ) ?;
0 commit comments