@@ -21,7 +21,8 @@ use tracing::debug;
21
21
use super :: diagnostics:: { ConsumeClosingDelim , dummy_arg} ;
22
22
use super :: ty:: { AllowPlus , RecoverQPath , RecoverReturnSign } ;
23
23
use super :: {
24
- AttrWrapper , FollowedByType , ForceCollect , Parser , PathStyle , Trailing , UsePreAttrPos ,
24
+ AttemptLocalParseRecovery , AttrWrapper , FollowedByType , ForceCollect , Parser , PathStyle ,
25
+ Trailing , UsePreAttrPos ,
25
26
} ;
26
27
use crate :: errors:: { self , MacroExpandsToAdtField } ;
27
28
use crate :: { fluent_generated as fluent, maybe_whole} ;
@@ -74,21 +75,11 @@ impl<'a> Parser<'a> {
74
75
items. push ( item) ;
75
76
}
76
77
78
+ // The last token should be `term`: either EOF or `}`. If it's not that means that we've had an error
79
+ // parsing an item
77
80
if !self . eat ( term) {
78
- let token_str = super :: token_descr ( & self . token ) ;
79
81
if !self . maybe_consume_incorrect_semicolon ( items. last ( ) . map ( |x| & * * x) ) {
80
- let msg = format ! ( "expected item, found {token_str}" ) ;
81
- let mut err = self . dcx ( ) . struct_span_err ( self . token . span , msg) ;
82
- let span = self . token . span ;
83
- if self . is_kw_followed_by_ident ( kw:: Let ) {
84
- err. span_label (
85
- span,
86
- "consider using `const` or `static` instead of `let` for global variables" ,
87
- ) ;
88
- } else {
89
- err. span_label ( span, "expected item" )
90
- . note ( "for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>" ) ;
91
- } ;
82
+ let err = self . fallback_incorrect_item ( ) ;
92
83
return Err ( err) ;
93
84
}
94
85
}
@@ -97,6 +88,64 @@ impl<'a> Parser<'a> {
97
88
let mod_spans = ModSpans { inner_span : lo. to ( self . prev_token . span ) , inject_use_span } ;
98
89
Ok ( ( attrs, items, mod_spans) )
99
90
}
91
+
92
+ /// Tries to parse the item as a statement to provide further diagnostics.
93
+ fn fallback_incorrect_item ( & mut self ) -> rustc_errors:: Diag < ' a > {
94
+ let token_str = super :: token_descr ( & self . token ) ;
95
+ let token_span = self . token . span ;
96
+ let mut err =
97
+ self . dcx ( ) . struct_span_err ( token_span, format ! ( "expected item, found {token_str}" ) ) ;
98
+
99
+ let mut do_default_diag = true ;
100
+
101
+ match self . parse_full_stmt ( AttemptLocalParseRecovery :: No ) {
102
+ Ok ( Some ( stmt) ) => {
103
+ do_default_diag = false ;
104
+ let span = stmt. span ;
105
+ match & stmt. kind {
106
+ StmtKind :: Let ( _) => {
107
+ err. span_label ( span, "unexpected `let` binding outside of a function" )
108
+ . help ( format ! ( "consider using `const` or `static` instead of `let` for global variables, or put it inside of a function: fn foo() {{ {} }}" ,
109
+ pprust:: stmt_to_string( & stmt) ) ) ;
110
+ }
111
+ StmtKind :: Semi ( expr) => {
112
+ err. span_label ( span, "unexpected expression" ) . help ( format ! (
113
+ "consider putting it inside a function: fn foo() {{ {}; }}" ,
114
+ pprust:: expr_to_string( expr)
115
+ ) ) ;
116
+ }
117
+ StmtKind :: Expr ( expr) => {
118
+ err. span_label ( span, "unexpected expression" ) . help ( format ! (
119
+ "consider putting it inside a function: fn foo() {{ {} }}" ,
120
+ pprust:: expr_to_string( expr)
121
+ ) ) ;
122
+ }
123
+ StmtKind :: Empty => {
124
+ unreachable ! (
125
+ "Should have been handled by maybe_consume_incorrect_semicolon"
126
+ ) ;
127
+ }
128
+ StmtKind :: Item ( _) | StmtKind :: MacCall ( _) => {
129
+ unreachable ! ( "These should be valid items!" )
130
+ }
131
+ } ;
132
+ }
133
+ // It's not a statement, we can't do much recovery.
134
+ Ok ( None ) => { }
135
+ Err ( e) => {
136
+ // We don't really care about an error parsing this statement.
137
+ e. cancel ( ) ;
138
+ }
139
+ }
140
+
141
+ if do_default_diag {
142
+ err. span_label ( token_span, "expected item" ) ;
143
+ }
144
+
145
+ err. note ( "for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html>" ) ;
146
+
147
+ err
148
+ }
100
149
}
101
150
102
151
pub ( super ) type ItemInfo = ( Ident , ItemKind ) ;
0 commit comments