@@ -2890,17 +2890,30 @@ impl<'a> Parser<'a> {
28902890
28912891 match self . parse_path ( PathStyle :: Expr ) {
28922892 Ok ( path) => {
2893+ let ( op_noun, op_verb) = match self . token {
2894+ token:: Lt => ( "comparison" , "comparing" ) ,
2895+ token:: BinOp ( token:: Shl ) => ( "shift" , "shifting" ) ,
2896+ _ => {
2897+ // We can end up here even without `<` being the next token, for
2898+ // example because `parse_ty_no_plus` returns `Err` on keywords,
2899+ // but `parse_path` returns `Ok` on them due to error recovery.
2900+ // Return original error and parser state.
2901+ mem:: replace ( self , parser_snapshot_after_type) ;
2902+ return Err ( type_err) ;
2903+ }
2904+ } ;
2905+
28932906 // Successfully parsed the type path leaving a `<` yet to parse.
28942907 type_err. cancel ( ) ;
28952908
28962909 // Report non-fatal diagnostics, keep `x as usize` as an expression
28972910 // in AST and continue parsing.
28982911 let msg = format ! ( "`<` is interpreted as a start of generic \
2899- arguments for `{}`, not a comparison ", path) ;
2912+ arguments for `{}`, not a {} ", path, op_noun ) ;
29002913 let mut err = self . sess . span_diagnostic . struct_span_err ( self . span , & msg) ;
29012914 err. span_label ( self . look_ahead_span ( 1 ) . to ( parser_snapshot_after_type. span ) ,
29022915 "interpreted as generic arguments" ) ;
2903- err. span_label ( self . span , "not interpreted as comparison" ) ;
2916+ err. span_label ( self . span , format ! ( "not interpreted as {}" , op_noun ) ) ;
29042917
29052918 let expr = mk_expr ( self , P ( Ty {
29062919 span : path. span ,
@@ -2911,7 +2924,7 @@ impl<'a> Parser<'a> {
29112924 let expr_str = self . sess . codemap ( ) . span_to_snippet ( expr. span )
29122925 . unwrap_or ( pprust:: expr_to_string ( & expr) ) ;
29132926 err. span_suggestion ( expr. span ,
2914- "try comparing the casted value" ,
2927+ & format ! ( "try {} the casted value" , op_verb ) ,
29152928 format ! ( "({})" , expr_str) ) ;
29162929 err. emit ( ) ;
29172930
0 commit comments