@@ -2,6 +2,7 @@ use crate::ast::{
22 self , Arg , BinOpKind , BindingMode , BlockCheckMode , Expr , ExprKind , Ident , Item , ItemKind ,
33 Mutability , Pat , PatKind , PathSegment , QSelf , Ty , TyKind , VariantData ,
44} ;
5+ use crate :: feature_gate:: { feature_err, UnstableFeatures } ;
56use crate :: parse:: { SeqSep , PResult , Parser , ParseSess } ;
67use crate :: parse:: parser:: { BlockMode , PathStyle , SemiColonMode , TokenType , TokenExpectType } ;
78use crate :: parse:: token:: { self , TokenKind } ;
@@ -365,9 +366,53 @@ impl<'a> Parser<'a> {
365366 err. span_label ( self . token . span , "unexpected token" ) ;
366367 }
367368 }
369+ self . maybe_annotate_with_ascription ( & mut err, false ) ;
368370 Err ( err)
369371 }
370372
373+ pub fn maybe_annotate_with_ascription (
374+ & self ,
375+ err : & mut DiagnosticBuilder < ' _ > ,
376+ maybe_expected_semicolon : bool ,
377+ ) {
378+ if let Some ( ( sp, likely_path) ) = self . last_type_ascription {
379+ let cm = self . sess . source_map ( ) ;
380+ let next_pos = cm. lookup_char_pos ( self . token . span . lo ( ) ) ;
381+ let op_pos = cm. lookup_char_pos ( sp. hi ( ) ) ;
382+
383+ if likely_path {
384+ err. span_suggestion (
385+ sp,
386+ "maybe write a path separator here" ,
387+ "::" . to_string ( ) ,
388+ match self . sess . unstable_features {
389+ UnstableFeatures :: Disallow => Applicability :: MachineApplicable ,
390+ _ => Applicability :: MaybeIncorrect ,
391+ } ,
392+ ) ;
393+ } else if op_pos. line != next_pos. line && maybe_expected_semicolon {
394+ err. span_suggestion (
395+ sp,
396+ "try using a semicolon" ,
397+ ";" . to_string ( ) ,
398+ Applicability :: MaybeIncorrect ,
399+ ) ;
400+ } else if let UnstableFeatures :: Disallow = self . sess . unstable_features {
401+ err. span_label ( sp, "tried to parse a type due to this" ) ;
402+ } else {
403+ err. span_label ( sp, "tried to parse a type due to this type ascription" ) ;
404+ }
405+ if let UnstableFeatures :: Disallow = self . sess . unstable_features {
406+ // Give extra information about type ascription only if it's a nightly compiler.
407+ } else {
408+ err. note ( "`#![feature(type_ascription)]` lets you annotate an expression with a \
409+ type: `<expr>: <type>`") ;
410+ err. note ( "for more information, see \
411+ https://github.com/rust-lang/rust/issues/23416") ;
412+ }
413+ }
414+ }
415+
371416 /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
372417 /// passes through any errors encountered. Used for error recovery.
373418 crate fn eat_to_tokens ( & mut self , kets : & [ & TokenKind ] ) {
@@ -556,7 +601,7 @@ impl<'a> Parser<'a> {
556601 . collect :: < Vec < _ > > ( ) ;
557602
558603 if !discriminant_spans. is_empty ( ) && has_fields {
559- let mut err = crate :: feature_gate :: feature_err (
604+ let mut err = feature_err (
560605 sess,
561606 sym:: arbitrary_enum_discriminant,
562607 discriminant_spans. clone ( ) ,
@@ -887,47 +932,9 @@ impl<'a> Parser<'a> {
887932 self . look_ahead ( 2 , |t| t. is_ident ( ) ) ||
888933 self . look_ahead ( 1 , |t| t == & token:: Colon ) && // `foo:bar:baz`
889934 self . look_ahead ( 2 , |t| t. is_ident ( ) ) ||
890- self . look_ahead ( 1 , |t| t == & token:: ModSep ) && // `foo:bar::baz`
891- self . look_ahead ( 2 , |t| t. is_ident ( ) )
892- }
893-
894- crate fn bad_type_ascription (
895- & self ,
896- err : & mut DiagnosticBuilder < ' a > ,
897- lhs_span : Span ,
898- cur_op_span : Span ,
899- next_sp : Span ,
900- maybe_path : bool ,
901- ) {
902- err. span_label ( self . token . span , "expecting a type here because of type ascription" ) ;
903- let cm = self . sess . source_map ( ) ;
904- let next_pos = cm. lookup_char_pos ( next_sp. lo ( ) ) ;
905- let op_pos = cm. lookup_char_pos ( cur_op_span. hi ( ) ) ;
906- if op_pos. line != next_pos. line {
907- err. span_suggestion (
908- cur_op_span,
909- "try using a semicolon" ,
910- ";" . to_string ( ) ,
911- Applicability :: MaybeIncorrect ,
912- ) ;
913- } else {
914- if maybe_path {
915- err. span_suggestion (
916- cur_op_span,
917- "maybe you meant to write a path separator here" ,
918- "::" . to_string ( ) ,
919- Applicability :: MaybeIncorrect ,
920- ) ;
921- } else {
922- err. note ( "`#![feature(type_ascription)]` lets you annotate an \
923- expression with a type: `<expr>: <type>`")
924- . span_note (
925- lhs_span,
926- "this expression expects an ascribed type after the colon" ,
927- )
928- . help ( "this might be indicative of a syntax error elsewhere" ) ;
929- }
930- }
935+ self . look_ahead ( 1 , |t| t == & token:: ModSep ) &&
936+ ( self . look_ahead ( 2 , |t| t. is_ident ( ) ) || // `foo:bar::baz`
937+ self . look_ahead ( 2 , |t| t == & token:: Lt ) ) // `foo:bar::<baz>`
931938 }
932939
933940 crate fn recover_seq_parse_error (
0 commit comments