@@ -3538,22 +3538,19 @@ impl<'a> Parser<'a> {
3538
3538
lhs = self . parse_assoc_op_cast ( lhs, lhs_span, ExprKind :: Cast ) ?;
3539
3539
continue
3540
3540
} else if op == AssocOp :: Colon {
3541
+ let maybe_path = self . could_ascription_be_path ( & lhs. node ) ;
3542
+ let next_sp = self . span ;
3543
+
3541
3544
lhs = match self . parse_assoc_op_cast ( lhs, lhs_span, ExprKind :: Type ) {
3542
3545
Ok ( lhs) => lhs,
3543
3546
Err ( mut err) => {
3544
- err. span_label ( self . span ,
3545
- "expecting a type here because of type ascription" ) ;
3546
- let cm = self . sess . source_map ( ) ;
3547
- let cur_pos = cm. lookup_char_pos ( self . span . lo ( ) ) ;
3548
- let op_pos = cm. lookup_char_pos ( cur_op_span. hi ( ) ) ;
3549
- if cur_pos. line != op_pos. line {
3550
- err. span_suggestion (
3551
- cur_op_span,
3552
- "try using a semicolon" ,
3553
- ";" . to_string ( ) ,
3554
- Applicability :: MaybeIncorrect // speculative
3555
- ) ;
3556
- }
3547
+ self . bad_type_ascription (
3548
+ & mut err,
3549
+ lhs_span,
3550
+ cur_op_span,
3551
+ next_sp,
3552
+ maybe_path,
3553
+ ) ;
3557
3554
return Err ( err) ;
3558
3555
}
3559
3556
} ;
@@ -3658,6 +3655,58 @@ impl<'a> Parser<'a> {
3658
3655
Ok ( lhs)
3659
3656
}
3660
3657
3658
+ fn could_ascription_be_path ( & self , node : & ast:: ExprKind ) -> bool {
3659
+ self . token . is_ident ( ) &&
3660
+ if let ast:: ExprKind :: Path ( ..) = node { true } else { false } &&
3661
+ !self . token . is_reserved_ident ( ) && // v `foo:bar(baz)`
3662
+ self . look_ahead ( 1 , |t| t == & token:: OpenDelim ( token:: Paren ) ) ||
3663
+ self . look_ahead ( 1 , |t| t == & token:: Lt ) && // `foo:bar<baz`
3664
+ self . look_ahead ( 2 , |t| t. is_ident ( ) ) ||
3665
+ self . look_ahead ( 1 , |t| t == & token:: Colon ) && // `foo:bar:baz`
3666
+ self . look_ahead ( 2 , |t| t. is_ident ( ) ) ||
3667
+ self . look_ahead ( 1 , |t| t == & token:: ModSep ) && // `foo:bar::baz`
3668
+ self . look_ahead ( 2 , |t| t. is_ident ( ) )
3669
+ }
3670
+
3671
+ fn bad_type_ascription (
3672
+ & self ,
3673
+ err : & mut DiagnosticBuilder < ' a > ,
3674
+ lhs_span : Span ,
3675
+ cur_op_span : Span ,
3676
+ next_sp : Span ,
3677
+ maybe_path : bool ,
3678
+ ) {
3679
+ err. span_label ( self . span , "expecting a type here because of type ascription" ) ;
3680
+ let cm = self . sess . source_map ( ) ;
3681
+ let next_pos = cm. lookup_char_pos ( next_sp. lo ( ) ) ;
3682
+ let op_pos = cm. lookup_char_pos ( cur_op_span. hi ( ) ) ;
3683
+ if op_pos. line != next_pos. line {
3684
+ err. span_suggestion (
3685
+ cur_op_span,
3686
+ "try using a semicolon" ,
3687
+ ";" . to_string ( ) ,
3688
+ Applicability :: MaybeIncorrect ,
3689
+ ) ;
3690
+ } else {
3691
+ if maybe_path {
3692
+ err. span_suggestion (
3693
+ cur_op_span,
3694
+ "maybe you meant to write a path separator here" ,
3695
+ "::" . to_string ( ) ,
3696
+ Applicability :: MaybeIncorrect ,
3697
+ ) ;
3698
+ } else {
3699
+ err. note ( "type ascription is a nightly-only feature that lets \
3700
+ you annotate an expression with a type: `<expr>: <type>`") ;
3701
+ err. span_note (
3702
+ lhs_span,
3703
+ "this expression expects an ascribed type after the colon" ,
3704
+ ) ;
3705
+ err. help ( "this might be indicative of a syntax error elsewhere" ) ;
3706
+ }
3707
+ }
3708
+ }
3709
+
3661
3710
fn parse_assoc_op_cast ( & mut self , lhs : P < Expr > , lhs_span : Span ,
3662
3711
expr_kind : fn ( P < Expr > , P < Ty > ) -> ExprKind )
3663
3712
-> PResult < ' a , P < Expr > > {
0 commit comments