@@ -3546,22 +3546,19 @@ impl<'a> Parser<'a> {
35463546 lhs = self . parse_assoc_op_cast ( lhs, lhs_span, ExprKind :: Cast ) ?;
35473547 continue
35483548 } else if op == AssocOp :: Colon {
3549+ let maybe_path = self . could_ascription_be_path ( & lhs. node ) ;
3550+ let next_sp = self . span ;
3551+
35493552 lhs = match self . parse_assoc_op_cast ( lhs, lhs_span, ExprKind :: Type ) {
35503553 Ok ( lhs) => lhs,
35513554 Err ( mut err) => {
3552- err. span_label ( self . span ,
3553- "expecting a type here because of type ascription" ) ;
3554- let cm = self . sess . source_map ( ) ;
3555- let cur_pos = cm. lookup_char_pos ( self . span . lo ( ) ) ;
3556- let op_pos = cm. lookup_char_pos ( cur_op_span. hi ( ) ) ;
3557- if cur_pos. line != op_pos. line {
3558- err. span_suggestion (
3559- cur_op_span,
3560- "try using a semicolon" ,
3561- ";" . to_string ( ) ,
3562- Applicability :: MaybeIncorrect // speculative
3563- ) ;
3564- }
3555+ self . bad_type_ascription (
3556+ & mut err,
3557+ lhs_span,
3558+ cur_op_span,
3559+ next_sp,
3560+ maybe_path,
3561+ ) ;
35653562 return Err ( err) ;
35663563 }
35673564 } ;
@@ -3666,6 +3663,62 @@ impl<'a> Parser<'a> {
36663663 Ok ( lhs)
36673664 }
36683665
3666+ fn could_ascription_be_path ( & self , node : & ast:: ExprKind ) -> bool {
3667+ self . token . is_ident ( ) &&
3668+ if let ast:: ExprKind :: Path ( ..) = node { true } else { false } &&
3669+ !self . token . is_reserved_ident ( ) && // v `foo:bar(baz)`
3670+ self . look_ahead ( 1 , |t| t == & token:: OpenDelim ( token:: Paren ) ) ||
3671+ self . look_ahead ( 1 , |t| t == & token:: Lt ) && // `foo:bar<baz`
3672+ self . look_ahead ( 2 , |t| t. is_ident ( ) ) ||
3673+ self . look_ahead ( 1 , |t| t == & token:: Colon ) && // `foo:bar:baz`
3674+ self . look_ahead ( 2 , |t| t. is_ident ( ) ) ||
3675+ self . look_ahead ( 1 , |t| t == & token:: ModSep ) && // `foo:bar::baz`
3676+ self . look_ahead ( 2 , |t| t. is_ident ( ) )
3677+ }
3678+
3679+ fn bad_type_ascription (
3680+ & self ,
3681+ err : & mut DiagnosticBuilder < ' a > ,
3682+ lhs_span : Span ,
3683+ cur_op_span : Span ,
3684+ next_sp : Span ,
3685+ maybe_path : bool ,
3686+ ) {
3687+ err. span_label ( self . span , "expecting a type here because of type ascription" ) ;
3688+ let cm = self . sess . source_map ( ) ;
3689+ let next_pos = cm. lookup_char_pos ( next_sp. lo ( ) ) ;
3690+ let op_pos = cm. lookup_char_pos ( cur_op_span. hi ( ) ) ;
3691+ if op_pos. line != next_pos. line {
3692+ err. span_suggestion (
3693+ cur_op_span,
3694+ "try using a semicolon" ,
3695+ ";" . to_string ( ) ,
3696+ Applicability :: MaybeIncorrect ,
3697+ ) ;
3698+ } else {
3699+ if maybe_path {
3700+ err. span_suggestion (
3701+ cur_op_span,
3702+ "maybe you meant to write a path separator here" ,
3703+ "::" . to_string ( ) ,
3704+ Applicability :: MaybeIncorrect ,
3705+ ) ;
3706+ } else {
3707+ err. note ( "type ascription is a nightly only feature that lets \
3708+ you annotate expressions with a type: `<expr>: <type>`") ;
3709+ err. span_note (
3710+ lhs_span,
3711+ "this expression is annotated with type ascription..." ,
3712+ ) ;
3713+ err. span_note (
3714+ cur_op_span,
3715+ "...due to this, which is why a type is expected after" ,
3716+ ) ;
3717+ err. help ( "this might be indicative of a syntax error elsewhere" ) ;
3718+ }
3719+ }
3720+ }
3721+
36693722 fn parse_assoc_op_cast ( & mut self , lhs : P < Expr > , lhs_span : Span ,
36703723 expr_kind : fn ( P < Expr > , P < Ty > ) -> ExprKind )
36713724 -> PResult < ' a , P < Expr > > {
0 commit comments