@@ -2,6 +2,7 @@ use crate::ast::{
2
2
self , Arg , BinOpKind , BindingMode , BlockCheckMode , Expr , ExprKind , Ident , Item , ItemKind ,
3
3
Mutability , Pat , PatKind , PathSegment , QSelf , Ty , TyKind , VariantData ,
4
4
} ;
5
+ use crate :: feature_gate:: { feature_err, UnstableFeatures } ;
5
6
use crate :: parse:: { SeqSep , PResult , Parser , ParseSess } ;
6
7
use crate :: parse:: parser:: { BlockMode , PathStyle , SemiColonMode , TokenType , TokenExpectType } ;
7
8
use crate :: parse:: token:: { self , TokenKind } ;
@@ -326,8 +327,8 @@ impl<'a> Parser<'a> {
326
327
self . token . is_keyword ( kw:: Return ) ||
327
328
self . token . is_keyword ( kw:: While )
328
329
) ;
329
- let cm = self . sess . source_map ( ) ;
330
- match ( cm . lookup_line ( self . token . span . lo ( ) ) , cm . lookup_line ( sp. lo ( ) ) ) {
330
+ let sm = self . sess . source_map ( ) ;
331
+ match ( sm . lookup_line ( self . token . span . lo ( ) ) , sm . lookup_line ( sp. lo ( ) ) ) {
331
332
( Ok ( ref a) , Ok ( ref b) ) if a. line != b. line && is_semi_suggestable => {
332
333
// The spans are in different lines, expected `;` and found `let` or `return`.
333
334
// High likelihood that it is only a missing `;`.
@@ -365,9 +366,53 @@ impl<'a> Parser<'a> {
365
366
err. span_label ( self . token . span , "unexpected token" ) ;
366
367
}
367
368
}
369
+ self . maybe_annotate_with_ascription ( & mut err, false ) ;
368
370
Err ( err)
369
371
}
370
372
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 sm = self . sess . source_map ( ) ;
380
+ let next_pos = sm. lookup_char_pos ( self . token . span . lo ( ) ) ;
381
+ let op_pos = sm. 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
+
371
416
/// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
372
417
/// passes through any errors encountered. Used for error recovery.
373
418
crate fn eat_to_tokens ( & mut self , kets : & [ & TokenKind ] ) {
@@ -556,7 +601,7 @@ impl<'a> Parser<'a> {
556
601
. collect :: < Vec < _ > > ( ) ;
557
602
558
603
if !discriminant_spans. is_empty ( ) && has_fields {
559
- let mut err = crate :: feature_gate :: feature_err (
604
+ let mut err = feature_err (
560
605
sess,
561
606
sym:: arbitrary_enum_discriminant,
562
607
discriminant_spans. clone ( ) ,
@@ -769,8 +814,8 @@ impl<'a> Parser<'a> {
769
814
return Ok ( recovered) ;
770
815
}
771
816
}
772
- let cm = self . sess . source_map ( ) ;
773
- match ( cm . lookup_line ( prev_sp. lo ( ) ) , cm . lookup_line ( sp. lo ( ) ) ) {
817
+ let sm = self . sess . source_map ( ) ;
818
+ match ( sm . lookup_line ( prev_sp. lo ( ) ) , sm . lookup_line ( sp. lo ( ) ) ) {
774
819
( Ok ( ref a) , Ok ( ref b) ) if a. line == b. line => {
775
820
// When the spans are in the same line, it means that the only content
776
821
// between them is whitespace, point only at the found token.
@@ -887,47 +932,9 @@ impl<'a> Parser<'a> {
887
932
self . look_ahead ( 2 , |t| t. is_ident ( ) ) ||
888
933
self . look_ahead ( 1 , |t| t == & token:: Colon ) && // `foo:bar:baz`
889
934
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>`
931
938
}
932
939
933
940
crate fn recover_seq_parse_error (
0 commit comments