diff options
-rw-r--r-- | bench_data/glorious_old_parser | 8562 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/tests.rs | 37 | ||||
-rw-r--r-- | crates/syntax/src/tests.rs | 28 | ||||
-rw-r--r-- | crates/test_utils/src/bench_fixture.rs | 9 |
4 files changed, 8628 insertions, 8 deletions
diff --git a/bench_data/glorious_old_parser b/bench_data/glorious_old_parser new file mode 100644 index 000000000..7e900dfeb --- /dev/null +++ b/bench_data/glorious_old_parser | |||
@@ -0,0 +1,8562 @@ | |||
1 | use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy}; | ||
2 | use crate::ast::{GenericBound, TraitBoundModifier}; | ||
3 | use crate::ast::Unsafety; | ||
4 | use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind}; | ||
5 | use crate::ast::Block; | ||
6 | use crate::ast::{BlockCheckMode, CaptureBy, Movability}; | ||
7 | use crate::ast::{Constness, Crate}; | ||
8 | use crate::ast::Defaultness; | ||
9 | use crate::ast::EnumDef; | ||
10 | use crate::ast::{Expr, ExprKind, RangeLimits}; | ||
11 | use crate::ast::{Field, FnDecl, FnHeader}; | ||
12 | use crate::ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; | ||
13 | use crate::ast::{GenericParam, GenericParamKind}; | ||
14 | use crate::ast::GenericArg; | ||
15 | use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind}; | ||
16 | use crate::ast::{Label, Lifetime, Lit, LitKind}; | ||
17 | use crate::ast::Local; | ||
18 | use crate::ast::MacStmtStyle; | ||
19 | use crate::ast::{Mac, Mac_, MacDelimiter}; | ||
20 | use crate::ast::{MutTy, Mutability}; | ||
21 | use crate::ast::{Pat, PatKind, PathSegment}; | ||
22 | use crate::ast::{PolyTraitRef, QSelf}; | ||
23 | use crate::ast::{Stmt, StmtKind}; | ||
24 | use crate::ast::{VariantData, StructField}; | ||
25 | use crate::ast::StrStyle; | ||
26 | use crate::ast::SelfKind; | ||
27 | use crate::ast::{TraitItem, TraitRef, TraitObjectSyntax}; | ||
28 | use crate::ast::{Ty, TyKind, TypeBinding, GenericBounds}; | ||
29 | use crate::ast::{Visibility, VisibilityKind, WhereClause, CrateSugar}; | ||
30 | use crate::ast::{UseTree, UseTreeKind}; | ||
31 | use crate::ast::{BinOpKind, UnOp}; | ||
32 | use crate::ast::{RangeEnd, RangeSyntax}; | ||
33 | use crate::{ast, attr}; | ||
34 | use crate::ext::base::DummyResult; | ||
35 | use crate::source_map::{self, SourceMap, Spanned, respan}; | ||
36 | use crate::parse::{self, SeqSep, classify, token}; | ||
37 | use crate::parse::lexer::{TokenAndSpan, UnmatchedBrace}; | ||
38 | use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; | ||
39 | use crate::parse::token::DelimToken; | ||
40 | use crate::parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership}; | ||
41 | use crate::util::parser::{AssocOp, Fixity}; | ||
42 | use crate::print::pprust; | ||
43 | use crate::ptr::P; | ||
44 | use crate::parse::PResult; | ||
45 | use crate::ThinVec; | ||
46 | use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; | ||
47 | use crate::symbol::{Symbol, keywords}; | ||
48 | |||
49 | use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; | ||
50 | use rustc_target::spec::abi::{self, Abi}; | ||
51 | use syntax_pos::{Span, MultiSpan, BytePos, FileName}; | ||
52 | use log::{debug, trace}; | ||
53 | |||
54 | use std::borrow::Cow; | ||
55 | use std::cmp; | ||
56 | use std::mem; | ||
57 | use std::path::{self, Path, PathBuf}; | ||
58 | use std::slice; | ||
59 | |||
60 | #[derive(Debug)] | ||
61 | /// Whether the type alias or associated type is a concrete type or an existential type | ||
62 | pub enum AliasKind { | ||
63 | /// Just a new name for the same type | ||
64 | Weak(P<Ty>), | ||
65 | /// Only trait impls of the type will be usable, not the actual type itself | ||
66 | Existential(GenericBounds), | ||
67 | } | ||
68 | |||
69 | bitflags::bitflags! { | ||
70 | struct Restrictions: u8 { | ||
71 | const STMT_EXPR = 1 << 0; | ||
72 | const NO_STRUCT_LITERAL = 1 << 1; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | type ItemInfo = (Ident, ItemKind, Option<Vec<Attribute>>); | ||
77 | |||
78 | /// Specifies how to parse a path. | ||
79 | #[derive(Copy, Clone, PartialEq)] | ||
80 | pub enum PathStyle { | ||
81 | /// In some contexts, notably in expressions, paths with generic arguments are ambiguous | ||
82 | /// with something else. For example, in expressions `segment < ....` can be interpreted | ||
83 | /// as a comparison and `segment ( ....` can be interpreted as a function call. | ||
84 | /// In all such contexts the non-path interpretation is preferred by default for practical | ||
85 | /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g. | ||
86 | /// `x<y>` - comparisons, `x::<y>` - unambiguously a path. | ||
87 | Expr, | ||
88 | /// In other contexts, notably in types, no ambiguity exists and paths can be written | ||
89 | /// without the disambiguator, e.g., `x<y>` - unambiguously a path. | ||
90 | /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too. | ||
91 | Type, | ||
92 | /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports, | ||
93 | /// visibilities or attributes. | ||
94 | /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead | ||
95 | /// (paths in "mod" contexts have to be checked later for absence of generic arguments | ||
96 | /// anyway, due to macros), but it is used to avoid weird suggestions about expected | ||
97 | /// tokens when something goes wrong. | ||
98 | Mod, | ||
99 | } | ||
100 | |||
101 | #[derive(Clone, Copy, PartialEq, Debug)] | ||
102 | enum SemiColonMode { | ||
103 | Break, | ||
104 | Ignore, | ||
105 | Comma, | ||
106 | } | ||
107 | |||
108 | #[derive(Clone, Copy, PartialEq, Debug)] | ||
109 | enum BlockMode { | ||
110 | Break, | ||
111 | Ignore, | ||
112 | } | ||
113 | |||
114 | /// Possibly accepts an `token::Interpolated` expression (a pre-parsed expression | ||
115 | /// dropped into the token stream, which happens while parsing the result of | ||
116 | /// macro expansion). Placement of these is not as complex as I feared it would | ||
117 | /// be. The important thing is to make sure that lookahead doesn't balk at | ||
118 | /// `token::Interpolated` tokens. | ||
119 | macro_rules! maybe_whole_expr { | ||
120 | ($p:expr) => { | ||
121 | if let token::Interpolated(nt) = $p.token.clone() { | ||
122 | match *nt { | ||
123 | token::NtExpr(ref e) | token::NtLiteral(ref e) => { | ||
124 | $p.bump(); | ||
125 | return Ok((*e).clone()); | ||
126 | } | ||
127 | token::NtPath(ref path) => { | ||
128 | $p.bump(); | ||
129 | let span = $p.span; | ||
130 | let kind = ExprKind::Path(None, (*path).clone()); | ||
131 | return Ok($p.mk_expr(span, kind, ThinVec::new())); | ||
132 | } | ||
133 | token::NtBlock(ref block) => { | ||
134 | $p.bump(); | ||
135 | let span = $p.span; | ||
136 | let kind = ExprKind::Block((*block).clone(), None); | ||
137 | return Ok($p.mk_expr(span, kind, ThinVec::new())); | ||
138 | } | ||
139 | _ => {}, | ||
140 | }; | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /// As maybe_whole_expr, but for things other than expressions | ||
146 | macro_rules! maybe_whole { | ||
147 | ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { | ||
148 | if let token::Interpolated(nt) = $p.token.clone() { | ||
149 | if let token::$constructor($x) = (*nt).clone() { | ||
150 | $p.bump(); | ||
151 | return Ok($e); | ||
152 | } | ||
153 | } | ||
154 | }; | ||
155 | } | ||
156 | |||
157 | fn maybe_append(mut lhs: Vec<Attribute>, mut rhs: Option<Vec<Attribute>>) -> Vec<Attribute> { | ||
158 | if let Some(ref mut rhs) = rhs { | ||
159 | lhs.append(rhs); | ||
160 | } | ||
161 | lhs | ||
162 | } | ||
163 | |||
164 | #[derive(Debug, Clone, Copy, PartialEq)] | ||
165 | enum PrevTokenKind { | ||
166 | DocComment, | ||
167 | Comma, | ||
168 | Plus, | ||
169 | Interpolated, | ||
170 | Eof, | ||
171 | Ident, | ||
172 | Other, | ||
173 | } | ||
174 | |||
175 | trait RecoverQPath: Sized { | ||
176 | const PATH_STYLE: PathStyle = PathStyle::Expr; | ||
177 | fn to_ty(&self) -> Option<P<Ty>>; | ||
178 | fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self; | ||
179 | fn to_string(&self) -> String; | ||
180 | } | ||
181 | |||
182 | impl RecoverQPath for Ty { | ||
183 | const PATH_STYLE: PathStyle = PathStyle::Type; | ||
184 | fn to_ty(&self) -> Option<P<Ty>> { | ||
185 | Some(P(self.clone())) | ||
186 | } | ||
187 | fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self { | ||
188 | Self { span: path.span, node: TyKind::Path(qself, path), id: self.id } | ||
189 | } | ||
190 | fn to_string(&self) -> String { | ||
191 | pprust::ty_to_string(self) | ||
192 | } | ||
193 | } | ||
194 | |||
195 | impl RecoverQPath for Pat { | ||
196 | fn to_ty(&self) -> Option<P<Ty>> { | ||
197 | self.to_ty() | ||
198 | } | ||
199 | fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self { | ||
200 | Self { span: path.span, node: PatKind::Path(qself, path), id: self.id } | ||
201 | } | ||
202 | fn to_string(&self) -> String { | ||
203 | pprust::pat_to_string(self) | ||
204 | } | ||
205 | } | ||
206 | |||
207 | impl RecoverQPath for Expr { | ||
208 | fn to_ty(&self) -> Option<P<Ty>> { | ||
209 | self.to_ty() | ||
210 | } | ||
211 | fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self { | ||
212 | Self { span: path.span, node: ExprKind::Path(qself, path), | ||
213 | id: self.id, attrs: self.attrs.clone() } | ||
214 | } | ||
215 | fn to_string(&self) -> String { | ||
216 | pprust::expr_to_string(self) | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /* ident is handled by common.rs */ | ||
221 | |||
222 | #[derive(Clone)] | ||
223 | pub struct Parser<'a> { | ||
224 | pub sess: &'a ParseSess, | ||
225 | /// the current token: | ||
226 | pub token: token::Token, | ||
227 | /// the span of the current token: | ||
228 | pub span: Span, | ||
229 | /// the span of the previous token: | ||
230 | meta_var_span: Option<Span>, | ||
231 | pub prev_span: Span, | ||
232 | /// the previous token kind | ||
233 | prev_token_kind: PrevTokenKind, | ||
234 | restrictions: Restrictions, | ||
235 | /// Used to determine the path to externally loaded source files | ||
236 | crate directory: Directory<'a>, | ||
237 | /// Whether to parse sub-modules in other files. | ||
238 | pub recurse_into_file_modules: bool, | ||
239 | /// Name of the root module this parser originated from. If `None`, then the | ||
240 | /// name is not known. This does not change while the parser is descending | ||
241 | /// into modules, and sub-parsers have new values for this name. | ||
242 | pub root_module_name: Option<String>, | ||
243 | crate expected_tokens: Vec<TokenType>, | ||
244 | token_cursor: TokenCursor, | ||
245 | desugar_doc_comments: bool, | ||
246 | /// Whether we should configure out of line modules as we parse. | ||
247 | pub cfg_mods: bool, | ||
248 | /// This field is used to keep track of how many left angle brackets we have seen. This is | ||
249 | /// required in order to detect extra leading left angle brackets (`<` characters) and error | ||
250 | /// appropriately. | ||
251 | /// | ||
252 | /// See the comments in the `parse_path_segment` function for more details. | ||
253 | crate unmatched_angle_bracket_count: u32, | ||
254 | crate max_angle_bracket_count: u32, | ||
255 | /// List of all unclosed delimiters found by the lexer. If an entry is used for error recovery | ||
256 | /// it gets removed from here. Every entry left at the end gets emitted as an independent | ||
257 | /// error. | ||
258 | crate unclosed_delims: Vec<UnmatchedBrace>, | ||
259 | } | ||
260 | |||
261 | |||
262 | #[derive(Clone)] | ||
263 | struct TokenCursor { | ||
264 | frame: TokenCursorFrame, | ||
265 | stack: Vec<TokenCursorFrame>, | ||
266 | } | ||
267 | |||
268 | #[derive(Clone)] | ||
269 | struct TokenCursorFrame { | ||
270 | delim: token::DelimToken, | ||
271 | span: DelimSpan, | ||
272 | open_delim: bool, | ||
273 | tree_cursor: tokenstream::Cursor, | ||
274 | close_delim: bool, | ||
275 | last_token: LastToken, | ||
276 | } | ||
277 | |||
278 | /// This is used in `TokenCursorFrame` above to track tokens that are consumed | ||
279 | /// by the parser, and then that's transitively used to record the tokens that | ||
280 | /// each parse AST item is created with. | ||
281 | /// | ||
282 | /// Right now this has two states, either collecting tokens or not collecting | ||
283 | /// tokens. If we're collecting tokens we just save everything off into a local | ||
284 | /// `Vec`. This should eventually though likely save tokens from the original | ||
285 | /// token stream and just use slicing of token streams to avoid creation of a | ||
286 | /// whole new vector. | ||
287 | /// | ||
288 | /// The second state is where we're passively not recording tokens, but the last | ||
289 | /// token is still tracked for when we want to start recording tokens. This | ||
290 | /// "last token" means that when we start recording tokens we'll want to ensure | ||
291 | /// that this, the first token, is included in the output. | ||
292 | /// | ||
293 | /// You can find some more example usage of this in the `collect_tokens` method | ||
294 | /// on the parser. | ||
295 | #[derive(Clone)] | ||
296 | enum LastToken { | ||
297 | Collecting(Vec<TreeAndJoint>), | ||
298 | Was(Option<TreeAndJoint>), | ||
299 | } | ||
300 | |||
301 | impl TokenCursorFrame { | ||
302 | fn new(sp: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self { | ||
303 | TokenCursorFrame { | ||
304 | delim: delim, | ||
305 | span: sp, | ||
306 | open_delim: delim == token::NoDelim, | ||
307 | tree_cursor: tts.clone().into_trees(), | ||
308 | close_delim: delim == token::NoDelim, | ||
309 | last_token: LastToken::Was(None), | ||
310 | } | ||
311 | } | ||
312 | } | ||
313 | |||
314 | impl TokenCursor { | ||
315 | fn next(&mut self) -> TokenAndSpan { | ||
316 | loop { | ||
317 | let tree = if !self.frame.open_delim { | ||
318 | self.frame.open_delim = true; | ||
319 | TokenTree::open_tt(self.frame.span.open, self.frame.delim) | ||
320 | } else if let Some(tree) = self.frame.tree_cursor.next() { | ||
321 | tree | ||
322 | } else if !self.frame.close_delim { | ||
323 | self.frame.close_delim = true; | ||
324 | TokenTree::close_tt(self.frame.span.close, self.frame.delim) | ||
325 | } else if let Some(frame) = self.stack.pop() { | ||
326 | self.frame = frame; | ||
327 | continue | ||
328 | } else { | ||
329 | return TokenAndSpan { tok: token::Eof, sp: syntax_pos::DUMMY_SP } | ||
330 | }; | ||
331 | |||
332 | match self.frame.last_token { | ||
333 | LastToken::Collecting(ref mut v) => v.push(tree.clone().into()), | ||
334 | LastToken::Was(ref mut t) => *t = Some(tree.clone().into()), | ||
335 | } | ||
336 | |||
337 | match tree { | ||
338 | TokenTree::Token(sp, tok) => return TokenAndSpan { tok: tok, sp: sp }, | ||
339 | TokenTree::Delimited(sp, delim, tts) => { | ||
340 | let frame = TokenCursorFrame::new(sp, delim, &tts); | ||
341 | self.stack.push(mem::replace(&mut self.frame, frame)); | ||
342 | } | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | fn next_desugared(&mut self) -> TokenAndSpan { | ||
348 | let (sp, name) = match self.next() { | ||
349 | TokenAndSpan { sp, tok: token::DocComment(name) } => (sp, name), | ||
350 | tok => return tok, | ||
351 | }; | ||
352 | |||
353 | let stripped = strip_doc_comment_decoration(&name.as_str()); | ||
354 | |||
355 | // Searches for the occurrences of `"#*` and returns the minimum number of `#`s | ||
356 | // required to wrap the text. | ||
357 | let mut num_of_hashes = 0; | ||
358 | let mut count = 0; | ||
359 | for ch in stripped.chars() { | ||
360 | count = match ch { | ||
361 | '"' => 1, | ||
362 | '#' if count > 0 => count + 1, | ||
363 | _ => 0, | ||
364 | }; | ||
365 | num_of_hashes = cmp::max(num_of_hashes, count); | ||
366 | } | ||
367 | |||
368 | let delim_span = DelimSpan::from_single(sp); | ||
369 | let body = TokenTree::Delimited( | ||
370 | delim_span, | ||
371 | token::Bracket, | ||
372 | [TokenTree::Token(sp, token::Ident(ast::Ident::from_str("doc"), false)), | ||
373 | TokenTree::Token(sp, token::Eq), | ||
374 | TokenTree::Token(sp, token::Literal( | ||
375 | token::StrRaw(Symbol::intern(&stripped), num_of_hashes), None)) | ||
376 | ] | ||
377 | .iter().cloned().collect::<TokenStream>().into(), | ||
378 | ); | ||
379 | |||
380 | self.stack.push(mem::replace(&mut self.frame, TokenCursorFrame::new( | ||
381 | delim_span, | ||
382 | token::NoDelim, | ||
383 | &if doc_comment_style(&name.as_str()) == AttrStyle::Inner { | ||
384 | [TokenTree::Token(sp, token::Pound), TokenTree::Token(sp, token::Not), body] | ||
385 | .iter().cloned().collect::<TokenStream>().into() | ||
386 | } else { | ||
387 | [TokenTree::Token(sp, token::Pound), body] | ||
388 | .iter().cloned().collect::<TokenStream>().into() | ||
389 | }, | ||
390 | ))); | ||
391 | |||
392 | self.next() | ||
393 | } | ||
394 | } | ||
395 | |||
396 | #[derive(Clone, PartialEq)] | ||
397 | crate enum TokenType { | ||
398 | Token(token::Token), | ||
399 | Keyword(keywords::Keyword), | ||
400 | Operator, | ||
401 | Lifetime, | ||
402 | Ident, | ||
403 | Path, | ||
404 | Type, | ||
405 | Const, | ||
406 | } | ||
407 | |||
408 | impl TokenType { | ||
409 | fn to_string(&self) -> String { | ||
410 | match *self { | ||
411 | TokenType::Token(ref t) => format!("`{}`", pprust::token_to_string(t)), | ||
412 | TokenType::Keyword(kw) => format!("`{}`", kw.name()), | ||
413 | TokenType::Operator => "an operator".to_string(), | ||
414 | TokenType::Lifetime => "lifetime".to_string(), | ||
415 | TokenType::Ident => "identifier".to_string(), | ||
416 | TokenType::Path => "path".to_string(), | ||
417 | TokenType::Type => "type".to_string(), | ||
418 | TokenType::Const => "const".to_string(), | ||
419 | } | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`, | ||
424 | /// `IDENT<<u8 as Trait>::AssocTy>`. | ||
425 | /// | ||
426 | /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes | ||
427 | /// that `IDENT` is not the ident of a fn trait. | ||
428 | fn can_continue_type_after_non_fn_ident(t: &token::Token) -> bool { | ||
429 | t == &token::ModSep || t == &token::Lt || | ||
430 | t == &token::BinOp(token::Shl) | ||
431 | } | ||
432 | |||
433 | /// Information about the path to a module. | ||
434 | pub struct ModulePath { | ||
435 | name: String, | ||
436 | path_exists: bool, | ||
437 | pub result: Result<ModulePathSuccess, Error>, | ||
438 | } | ||
439 | |||
440 | pub struct ModulePathSuccess { | ||
441 | pub path: PathBuf, | ||
442 | pub directory_ownership: DirectoryOwnership, | ||
443 | warn: bool, | ||
444 | } | ||
445 | |||
446 | pub enum Error { | ||
447 | FileNotFoundForModule { | ||
448 | mod_name: String, | ||
449 | default_path: String, | ||
450 | secondary_path: String, | ||
451 | dir_path: String, | ||
452 | }, | ||
453 | DuplicatePaths { | ||
454 | mod_name: String, | ||
455 | default_path: String, | ||
456 | secondary_path: String, | ||
457 | }, | ||
458 | UselessDocComment, | ||
459 | InclusiveRangeWithNoEnd, | ||
460 | } | ||
461 | |||
462 | impl Error { | ||
463 | fn span_err<S: Into<MultiSpan>>(self, | ||
464 | sp: S, | ||
465 | handler: &errors::Handler) -> DiagnosticBuilder<'_> { | ||
466 | match self { | ||
467 | Error::FileNotFoundForModule { ref mod_name, | ||
468 | ref default_path, | ||
469 | ref secondary_path, | ||
470 | ref dir_path } => { | ||
471 | let mut err = struct_span_err!(handler, sp, E0583, | ||
472 | "file not found for module `{}`", mod_name); | ||
473 | err.help(&format!("name the file either {} or {} inside the directory \"{}\"", | ||
474 | default_path, | ||
475 | secondary_path, | ||
476 | dir_path)); | ||
477 | err | ||
478 | } | ||
479 | Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { | ||
480 | let mut err = struct_span_err!(handler, sp, E0584, | ||
481 | "file for module `{}` found at both {} and {}", | ||
482 | mod_name, | ||
483 | default_path, | ||
484 | secondary_path); | ||
485 | err.help("delete or rename one of them to remove the ambiguity"); | ||
486 | err | ||
487 | } | ||
488 | Error::UselessDocComment => { | ||
489 | let mut err = struct_span_err!(handler, sp, E0585, | ||
490 | "found a documentation comment that doesn't document anything"); | ||
491 | err.help("doc comments must come before what they document, maybe a comment was \ | ||
492 | intended with `//`?"); | ||
493 | err | ||
494 | } | ||
495 | Error::InclusiveRangeWithNoEnd => { | ||
496 | let mut err = struct_span_err!(handler, sp, E0586, | ||
497 | "inclusive range with no end"); | ||
498 | err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)"); | ||
499 | err | ||
500 | } | ||
501 | } | ||
502 | } | ||
503 | } | ||
504 | |||
505 | #[derive(Debug)] | ||
506 | enum LhsExpr { | ||
507 | NotYetParsed, | ||
508 | AttributesParsed(ThinVec<Attribute>), | ||
509 | AlreadyParsed(P<Expr>), | ||
510 | } | ||
511 | |||
512 | impl From<Option<ThinVec<Attribute>>> for LhsExpr { | ||
513 | fn from(o: Option<ThinVec<Attribute>>) -> Self { | ||
514 | if let Some(attrs) = o { | ||
515 | LhsExpr::AttributesParsed(attrs) | ||
516 | } else { | ||
517 | LhsExpr::NotYetParsed | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | |||
522 | impl From<P<Expr>> for LhsExpr { | ||
523 | fn from(expr: P<Expr>) -> Self { | ||
524 | LhsExpr::AlreadyParsed(expr) | ||
525 | } | ||
526 | } | ||
527 | |||
528 | /// Creates a placeholder argument. | ||
529 | fn dummy_arg(span: Span) -> Arg { | ||
530 | let ident = Ident::new(keywords::Invalid.name(), span); | ||
531 | let pat = P(Pat { | ||
532 | id: ast::DUMMY_NODE_ID, | ||
533 | node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), | ||
534 | span, | ||
535 | }); | ||
536 | let ty = Ty { | ||
537 | node: TyKind::Err, | ||
538 | span, | ||
539 | id: ast::DUMMY_NODE_ID | ||
540 | }; | ||
541 | Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } | ||
542 | } | ||
543 | |||
544 | #[derive(Copy, Clone, Debug)] | ||
545 | enum TokenExpectType { | ||
546 | Expect, | ||
547 | NoExpect, | ||
548 | } | ||
549 | |||
550 | impl<'a> Parser<'a> { | ||
551 | pub fn new(sess: &'a ParseSess, | ||
552 | tokens: TokenStream, | ||
553 | directory: Option<Directory<'a>>, | ||
554 | recurse_into_file_modules: bool, | ||
555 | desugar_doc_comments: bool) | ||
556 | -> Self { | ||
557 | let mut parser = Parser { | ||
558 | sess, | ||
559 | token: token::Whitespace, | ||
560 | span: syntax_pos::DUMMY_SP, | ||
561 | prev_span: syntax_pos::DUMMY_SP, | ||
562 | meta_var_span: None, | ||
563 | prev_token_kind: PrevTokenKind::Other, | ||
564 | restrictions: Restrictions::empty(), | ||
565 | recurse_into_file_modules, | ||
566 | directory: Directory { | ||
567 | path: Cow::from(PathBuf::new()), | ||
568 | ownership: DirectoryOwnership::Owned { relative: None } | ||
569 | }, | ||
570 | root_module_name: None, | ||
571 | expected_tokens: Vec::new(), | ||
572 | token_cursor: TokenCursor { | ||
573 | frame: TokenCursorFrame::new( | ||
574 | DelimSpan::dummy(), | ||
575 | token::NoDelim, | ||
576 | &tokens.into(), | ||
577 | ), | ||
578 | stack: Vec::new(), | ||
579 | }, | ||
580 | desugar_doc_comments, | ||
581 | cfg_mods: true, | ||
582 | unmatched_angle_bracket_count: 0, | ||
583 | max_angle_bracket_count: 0, | ||
584 | unclosed_delims: Vec::new(), | ||
585 | }; | ||
586 | |||
587 | let tok = parser.next_tok(); | ||
588 | parser.token = tok.tok; | ||
589 | parser.span = tok.sp; | ||
590 | |||
591 | if let Some(directory) = directory { | ||
592 | parser.directory = directory; | ||
593 | } else if !parser.span.is_dummy() { | ||
594 | if let FileName::Real(mut path) = sess.source_map().span_to_unmapped_path(parser.span) { | ||
595 | path.pop(); | ||
596 | parser.directory.path = Cow::from(path); | ||
597 | } | ||
598 | } | ||
599 | |||
600 | parser.process_potential_macro_variable(); | ||
601 | parser | ||
602 | } | ||
603 | |||
604 | fn next_tok(&mut self) -> TokenAndSpan { | ||
605 | let mut next = if self.desugar_doc_comments { | ||
606 | self.token_cursor.next_desugared() | ||
607 | } else { | ||
608 | self.token_cursor.next() | ||
609 | }; | ||
610 | if next.sp.is_dummy() { | ||
611 | // Tweak the location for better diagnostics, but keep syntactic context intact. | ||
612 | next.sp = self.prev_span.with_ctxt(next.sp.ctxt()); | ||
613 | } | ||
614 | next | ||
615 | } | ||
616 | |||
617 | /// Converts the current token to a string using `self`'s reader. | ||
618 | pub fn this_token_to_string(&self) -> String { | ||
619 | pprust::token_to_string(&self.token) | ||
620 | } | ||
621 | |||
622 | fn token_descr(&self) -> Option<&'static str> { | ||
623 | Some(match &self.token { | ||
624 | t if t.is_special_ident() => "reserved identifier", | ||
625 | t if t.is_used_keyword() => "keyword", | ||
626 | t if t.is_unused_keyword() => "reserved keyword", | ||
627 | token::DocComment(..) => "doc comment", | ||
628 | _ => return None, | ||
629 | }) | ||
630 | } | ||
631 | |||
632 | fn this_token_descr(&self) -> String { | ||
633 | if let Some(prefix) = self.token_descr() { | ||
634 | format!("{} `{}`", prefix, self.this_token_to_string()) | ||
635 | } else { | ||
636 | format!("`{}`", self.this_token_to_string()) | ||
637 | } | ||
638 | } | ||
639 | |||
640 | fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> { | ||
641 | let token_str = pprust::token_to_string(t); | ||
642 | Err(self.span_fatal(self.prev_span, &format!("unexpected token: `{}`", token_str))) | ||
643 | } | ||
644 | |||
645 | crate fn unexpected<T>(&mut self) -> PResult<'a, T> { | ||
646 | match self.expect_one_of(&[], &[]) { | ||
647 | Err(e) => Err(e), | ||
648 | Ok(_) => unreachable!(), | ||
649 | } | ||
650 | } | ||
651 | |||
652 | /// Expects and consumes the token `t`. Signals an error if the next token is not `t`. | ||
653 | pub fn expect(&mut self, t: &token::Token) -> PResult<'a, bool /* recovered */> { | ||
654 | if self.expected_tokens.is_empty() { | ||
655 | if self.token == *t { | ||
656 | self.bump(); | ||
657 | Ok(false) | ||
658 | } else { | ||
659 | let token_str = pprust::token_to_string(t); | ||
660 | let this_token_str = self.this_token_descr(); | ||
661 | let mut err = self.fatal(&format!("expected `{}`, found {}", | ||
662 | token_str, | ||
663 | this_token_str)); | ||
664 | |||
665 | let sp = if self.token == token::Token::Eof { | ||
666 | // EOF, don't want to point at the following char, but rather the last token | ||
667 | self.prev_span | ||
668 | } else { | ||
669 | self.sess.source_map().next_point(self.prev_span) | ||
670 | }; | ||
671 | let label_exp = format!("expected `{}`", token_str); | ||
672 | match self.recover_closing_delimiter(&[t.clone()], err) { | ||
673 | Err(e) => err = e, | ||
674 | Ok(recovered) => { | ||
675 | return Ok(recovered); | ||
676 | } | ||
677 | } | ||
678 | let cm = self.sess.source_map(); | ||
679 | match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) { | ||
680 | (Ok(ref a), Ok(ref b)) if a.line == b.line => { | ||
681 | // When the spans are in the same line, it means that the only content | ||
682 | // between them is whitespace, point only at the found token. | ||
683 | err.span_label(self.span, label_exp); | ||
684 | } | ||
685 | _ => { | ||
686 | err.span_label(sp, label_exp); | ||
687 | err.span_label(self.span, "unexpected token"); | ||
688 | } | ||
689 | } | ||
690 | Err(err) | ||
691 | } | ||
692 | } else { | ||
693 | self.expect_one_of(slice::from_ref(t), &[]) | ||
694 | } | ||
695 | } | ||
696 | |||
697 | fn recover_closing_delimiter( | ||
698 | &mut self, | ||
699 | tokens: &[token::Token], | ||
700 | mut err: DiagnosticBuilder<'a>, | ||
701 | ) -> PResult<'a, bool> { | ||
702 | let mut pos = None; | ||
703 | // we want to use the last closing delim that would apply | ||
704 | for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() { | ||
705 | if tokens.contains(&token::CloseDelim(unmatched.expected_delim)) | ||
706 | && Some(self.span) > unmatched.unclosed_span | ||
707 | { | ||
708 | pos = Some(i); | ||
709 | } | ||
710 | } | ||
711 | match pos { | ||
712 | Some(pos) => { | ||
713 | // Recover and assume that the detected unclosed delimiter was meant for | ||
714 | // this location. Emit the diagnostic and act as if the delimiter was | ||
715 | // present for the parser's sake. | ||
716 | |||
717 | // Don't attempt to recover from this unclosed delimiter more than once. | ||
718 | let unmatched = self.unclosed_delims.remove(pos); | ||
719 | let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim)); | ||
720 | |||
721 | // We want to suggest the inclusion of the closing delimiter where it makes | ||
722 | // the most sense, which is immediately after the last token: | ||
723 | // | ||
724 | // {foo(bar {}} | ||
725 | // - ^ | ||
726 | // | | | ||
727 | // | help: `)` may belong here (FIXME: #58270) | ||
728 | // | | ||
729 | // unclosed delimiter | ||
730 | if let Some(sp) = unmatched.unclosed_span { | ||
731 | err.span_label(sp, "unclosed delimiter"); | ||
732 | } | ||
733 | err.span_suggestion_short( | ||
734 | self.sess.source_map().next_point(self.prev_span), | ||
735 | &format!("{} may belong here", delim.to_string()), | ||
736 | delim.to_string(), | ||
737 | Applicability::MaybeIncorrect, | ||
738 | ); | ||
739 | err.emit(); | ||
740 | self.expected_tokens.clear(); // reduce errors | ||
741 | Ok(true) | ||
742 | } | ||
743 | _ => Err(err), | ||
744 | } | ||
745 | } | ||
746 | |||
747 | /// Expect next token to be edible or inedible token. If edible, | ||
748 | /// then consume it; if inedible, then return without consuming | ||
749 | /// anything. Signal a fatal error if next token is unexpected. | ||
750 | pub fn expect_one_of( | ||
751 | &mut self, | ||
752 | edible: &[token::Token], | ||
753 | inedible: &[token::Token], | ||
754 | ) -> PResult<'a, bool /* recovered */> { | ||
755 | fn tokens_to_string(tokens: &[TokenType]) -> String { | ||
756 | let mut i = tokens.iter(); | ||
757 | // This might be a sign we need a connect method on Iterator. | ||
758 | let b = i.next() | ||
759 | .map_or(String::new(), |t| t.to_string()); | ||
760 | i.enumerate().fold(b, |mut b, (i, a)| { | ||
761 | if tokens.len() > 2 && i == tokens.len() - 2 { | ||
762 | b.push_str(", or "); | ||
763 | } else if tokens.len() == 2 && i == tokens.len() - 2 { | ||
764 | b.push_str(" or "); | ||
765 | } else { | ||
766 | b.push_str(", "); | ||
767 | } | ||
768 | b.push_str(&a.to_string()); | ||
769 | b | ||
770 | }) | ||
771 | } | ||
772 | if edible.contains(&self.token) { | ||
773 | self.bump(); | ||
774 | Ok(false) | ||
775 | } else if inedible.contains(&self.token) { | ||
776 | // leave it in the input | ||
777 | Ok(false) | ||
778 | } else { | ||
779 | let mut expected = edible.iter() | ||
780 | .map(|x| TokenType::Token(x.clone())) | ||
781 | .chain(inedible.iter().map(|x| TokenType::Token(x.clone()))) | ||
782 | .chain(self.expected_tokens.iter().cloned()) | ||
783 | .collect::<Vec<_>>(); | ||
784 | expected.sort_by_cached_key(|x| x.to_string()); | ||
785 | expected.dedup(); | ||
786 | let expect = tokens_to_string(&expected[..]); | ||
787 | let actual = self.this_token_to_string(); | ||
788 | let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { | ||
789 | let short_expect = if expected.len() > 6 { | ||
790 | format!("{} possible tokens", expected.len()) | ||
791 | } else { | ||
792 | expect.clone() | ||
793 | }; | ||
794 | (format!("expected one of {}, found `{}`", expect, actual), | ||
795 | (self.sess.source_map().next_point(self.prev_span), | ||
796 | format!("expected one of {} here", short_expect))) | ||
797 | } else if expected.is_empty() { | ||
798 | (format!("unexpected token: `{}`", actual), | ||
799 | (self.prev_span, "unexpected token after this".to_string())) | ||
800 | } else { | ||
801 | (format!("expected {}, found `{}`", expect, actual), | ||
802 | (self.sess.source_map().next_point(self.prev_span), | ||
803 | format!("expected {} here", expect))) | ||
804 | }; | ||
805 | let mut err = self.fatal(&msg_exp); | ||
806 | if self.token.is_ident_named("and") { | ||
807 | err.span_suggestion_short( | ||
808 | self.span, | ||
809 | "use `&&` instead of `and` for the boolean operator", | ||
810 | "&&".to_string(), | ||
811 | Applicability::MaybeIncorrect, | ||
812 | ); | ||
813 | } | ||
814 | if self.token.is_ident_named("or") { | ||
815 | err.span_suggestion_short( | ||
816 | self.span, | ||
817 | "use `||` instead of `or` for the boolean operator", | ||
818 | "||".to_string(), | ||
819 | Applicability::MaybeIncorrect, | ||
820 | ); | ||
821 | } | ||
822 | let sp = if self.token == token::Token::Eof { | ||
823 | // This is EOF, don't want to point at the following char, but rather the last token | ||
824 | self.prev_span | ||
825 | } else { | ||
826 | label_sp | ||
827 | }; | ||
828 | match self.recover_closing_delimiter(&expected.iter().filter_map(|tt| match tt { | ||
829 | TokenType::Token(t) => Some(t.clone()), | ||
830 | _ => None, | ||
831 | }).collect::<Vec<_>>(), err) { | ||
832 | Err(e) => err = e, | ||
833 | Ok(recovered) => { | ||
834 | return Ok(recovered); | ||
835 | } | ||
836 | } | ||
837 | |||
838 | let cm = self.sess.source_map(); | ||
839 | match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) { | ||
840 | (Ok(ref a), Ok(ref b)) if a.line == b.line => { | ||
841 | // When the spans are in the same line, it means that the only content between | ||
842 | // them is whitespace, point at the found token in that case: | ||
843 | // | ||
844 | // X | () => { syntax error }; | ||
845 | // | ^^^^^ expected one of 8 possible tokens here | ||
846 | // | ||
847 | // instead of having: | ||
848 | // | ||
849 | // X | () => { syntax error }; | ||
850 | // | -^^^^^ unexpected token | ||
851 | // | | | ||
852 | // | expected one of 8 possible tokens here | ||
853 | err.span_label(self.span, label_exp); | ||
854 | } | ||
855 | _ if self.prev_span == syntax_pos::DUMMY_SP => { | ||
856 | // Account for macro context where the previous span might not be | ||
857 | // available to avoid incorrect output (#54841). | ||
858 | err.span_label(self.span, "unexpected token"); | ||
859 | } | ||
860 | _ => { | ||
861 | err.span_label(sp, label_exp); | ||
862 | err.span_label(self.span, "unexpected token"); | ||
863 | } | ||
864 | } | ||
865 | Err(err) | ||
866 | } | ||
867 | } | ||
868 | |||
869 | /// Returns the span of expr, if it was not interpolated or the span of the interpolated token. | ||
870 | fn interpolated_or_expr_span(&self, | ||
871 | expr: PResult<'a, P<Expr>>) | ||
872 | -> PResult<'a, (Span, P<Expr>)> { | ||
873 | expr.map(|e| { | ||
874 | if self.prev_token_kind == PrevTokenKind::Interpolated { | ||
875 | (self.prev_span, e) | ||
876 | } else { | ||
877 | (e.span, e) | ||
878 | } | ||
879 | }) | ||
880 | } | ||
881 | |||
882 | fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { | ||
883 | let mut err = self.struct_span_err(self.span, | ||
884 | &format!("expected identifier, found {}", | ||
885 | self.this_token_descr())); | ||
886 | if let token::Ident(ident, false) = &self.token { | ||
887 | if ident.is_reserved() && !ident.is_path_segment_keyword() && | ||
888 | ident.name != keywords::Underscore.name() | ||
889 | { | ||
890 | err.span_suggestion( | ||
891 | self.span, | ||
892 | "you can escape reserved keywords to use them as identifiers", | ||
893 | format!("r#{}", ident), | ||
894 | Applicability::MaybeIncorrect, | ||
895 | ); | ||
896 | } | ||
897 | } | ||
898 | if let Some(token_descr) = self.token_descr() { | ||
899 | err.span_label(self.span, format!("expected identifier, found {}", token_descr)); | ||
900 | } else { | ||
901 | err.span_label(self.span, "expected identifier"); | ||
902 | if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) { | ||
903 | err.span_suggestion( | ||
904 | self.span, | ||
905 | "remove this comma", | ||
906 | String::new(), | ||
907 | Applicability::MachineApplicable, | ||
908 | ); | ||
909 | } | ||
910 | } | ||
911 | err | ||
912 | } | ||
913 | |||
914 | pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { | ||
915 | self.parse_ident_common(true) | ||
916 | } | ||
917 | |||
918 | fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { | ||
919 | match self.token { | ||
920 | token::Ident(ident, _) => { | ||
921 | if self.token.is_reserved_ident() { | ||
922 | let mut err = self.expected_ident_found(); | ||
923 | if recover { | ||
924 | err.emit(); | ||
925 | } else { | ||
926 | return Err(err); | ||
927 | } | ||
928 | } | ||
929 | let span = self.span; | ||
930 | self.bump(); | ||
931 | Ok(Ident::new(ident.name, span)) | ||
932 | } | ||
933 | _ => { | ||
934 | Err(if self.prev_token_kind == PrevTokenKind::DocComment { | ||
935 | self.span_fatal_err(self.prev_span, Error::UselessDocComment) | ||
936 | } else { | ||
937 | self.expected_ident_found() | ||
938 | }) | ||
939 | } | ||
940 | } | ||
941 | } | ||
942 | |||
943 | /// Checks if the next token is `tok`, and returns `true` if so. | ||
944 | /// | ||
945 | /// This method will automatically add `tok` to `expected_tokens` if `tok` is not | ||
946 | /// encountered. | ||
947 | crate fn check(&mut self, tok: &token::Token) -> bool { | ||
948 | let is_present = self.token == *tok; | ||
949 | if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); } | ||
950 | is_present | ||
951 | } | ||
952 | |||
953 | /// Consumes a token 'tok' if it exists. Returns whether the given token was present. | ||
954 | pub fn eat(&mut self, tok: &token::Token) -> bool { | ||
955 | let is_present = self.check(tok); | ||
956 | if is_present { self.bump() } | ||
957 | is_present | ||
958 | } | ||
959 | |||
960 | fn check_keyword(&mut self, kw: keywords::Keyword) -> bool { | ||
961 | self.expected_tokens.push(TokenType::Keyword(kw)); | ||
962 | self.token.is_keyword(kw) | ||
963 | } | ||
964 | |||
965 | /// If the next token is the given keyword, eats it and returns | ||
966 | /// `true`. Otherwise, returns `false`. | ||
967 | pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool { | ||
968 | if self.check_keyword(kw) { | ||
969 | self.bump(); | ||
970 | true | ||
971 | } else { | ||
972 | false | ||
973 | } | ||
974 | } | ||
975 | |||
976 | fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> bool { | ||
977 | if self.token.is_keyword(kw) { | ||
978 | self.bump(); | ||
979 | true | ||
980 | } else { | ||
981 | false | ||
982 | } | ||
983 | } | ||
984 | |||
985 | /// If the given word is not a keyword, signals an error. | ||
986 | /// If the next token is not the given word, signals an error. | ||
987 | /// Otherwise, eats it. | ||
988 | fn expect_keyword(&mut self, kw: keywords::Keyword) -> PResult<'a, ()> { | ||
989 | if !self.eat_keyword(kw) { | ||
990 | self.unexpected() | ||
991 | } else { | ||
992 | Ok(()) | ||
993 | } | ||
994 | } | ||
995 | |||
996 | fn check_ident(&mut self) -> bool { | ||
997 | if self.token.is_ident() { | ||
998 | true | ||
999 | } else { | ||
1000 | self.expected_tokens.push(TokenType::Ident); | ||
1001 | false | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | fn check_path(&mut self) -> bool { | ||
1006 | if self.token.is_path_start() { | ||
1007 | true | ||
1008 | } else { | ||
1009 | self.expected_tokens.push(TokenType::Path); | ||
1010 | false | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | fn check_type(&mut self) -> bool { | ||
1015 | if self.token.can_begin_type() { | ||
1016 | true | ||
1017 | } else { | ||
1018 | self.expected_tokens.push(TokenType::Type); | ||
1019 | false | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | fn check_const_arg(&mut self) -> bool { | ||
1024 | if self.token.can_begin_const_arg() { | ||
1025 | true | ||
1026 | } else { | ||
1027 | self.expected_tokens.push(TokenType::Const); | ||
1028 | false | ||
1029 | } | ||
1030 | } | ||
1031 | |||
1032 | /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=` | ||
1033 | /// and continues. If a `+` is not seen, returns `false`. | ||
1034 | /// | ||
1035 | /// This is used when token-splitting `+=` into `+`. | ||
1036 | /// See issue #47856 for an example of when this may occur. | ||
1037 | fn eat_plus(&mut self) -> bool { | ||
1038 | self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus))); | ||
1039 | match self.token { | ||
1040 | token::BinOp(token::Plus) => { | ||
1041 | self.bump(); | ||
1042 | true | ||
1043 | } | ||
1044 | token::BinOpEq(token::Plus) => { | ||
1045 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1046 | self.bump_with(token::Eq, span); | ||
1047 | true | ||
1048 | } | ||
1049 | _ => false, | ||
1050 | } | ||
1051 | } | ||
1052 | |||
1053 | |||
1054 | /// Checks to see if the next token is either `+` or `+=`. | ||
1055 | /// Otherwise returns `false`. | ||
1056 | fn check_plus(&mut self) -> bool { | ||
1057 | if self.token.is_like_plus() { | ||
1058 | true | ||
1059 | } | ||
1060 | else { | ||
1061 | self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus))); | ||
1062 | false | ||
1063 | } | ||
1064 | } | ||
1065 | |||
1066 | /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single | ||
1067 | /// `&` and continues. If an `&` is not seen, signals an error. | ||
1068 | fn expect_and(&mut self) -> PResult<'a, ()> { | ||
1069 | self.expected_tokens.push(TokenType::Token(token::BinOp(token::And))); | ||
1070 | match self.token { | ||
1071 | token::BinOp(token::And) => { | ||
1072 | self.bump(); | ||
1073 | Ok(()) | ||
1074 | } | ||
1075 | token::AndAnd => { | ||
1076 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1077 | Ok(self.bump_with(token::BinOp(token::And), span)) | ||
1078 | } | ||
1079 | _ => self.unexpected() | ||
1080 | } | ||
1081 | } | ||
1082 | |||
1083 | /// Expects and consumes an `|`. If `||` is seen, replaces it with a single | ||
1084 | /// `|` and continues. If an `|` is not seen, signals an error. | ||
1085 | fn expect_or(&mut self) -> PResult<'a, ()> { | ||
1086 | self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or))); | ||
1087 | match self.token { | ||
1088 | token::BinOp(token::Or) => { | ||
1089 | self.bump(); | ||
1090 | Ok(()) | ||
1091 | } | ||
1092 | token::OrOr => { | ||
1093 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1094 | Ok(self.bump_with(token::BinOp(token::Or), span)) | ||
1095 | } | ||
1096 | _ => self.unexpected() | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) { | ||
1101 | match suffix { | ||
1102 | None => {/* everything ok */} | ||
1103 | Some(suf) => { | ||
1104 | let text = suf.as_str(); | ||
1105 | if text.is_empty() { | ||
1106 | self.span_bug(sp, "found empty literal suffix in Some") | ||
1107 | } | ||
1108 | let msg = format!("{} with a suffix is invalid", kind); | ||
1109 | self.struct_span_err(sp, &msg) | ||
1110 | .span_label(sp, msg) | ||
1111 | .emit(); | ||
1112 | } | ||
1113 | } | ||
1114 | } | ||
1115 | |||
1116 | /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single | ||
1117 | /// `<` and continue. If `<-` is seen, replaces it with a single `<` | ||
1118 | /// and continue. If a `<` is not seen, returns false. | ||
1119 | /// | ||
1120 | /// This is meant to be used when parsing generics on a path to get the | ||
1121 | /// starting token. | ||
1122 | fn eat_lt(&mut self) -> bool { | ||
1123 | self.expected_tokens.push(TokenType::Token(token::Lt)); | ||
1124 | let ate = match self.token { | ||
1125 | token::Lt => { | ||
1126 | self.bump(); | ||
1127 | true | ||
1128 | } | ||
1129 | token::BinOp(token::Shl) => { | ||
1130 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1131 | self.bump_with(token::Lt, span); | ||
1132 | true | ||
1133 | } | ||
1134 | token::LArrow => { | ||
1135 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1136 | self.bump_with(token::BinOp(token::Minus), span); | ||
1137 | true | ||
1138 | } | ||
1139 | _ => false, | ||
1140 | }; | ||
1141 | |||
1142 | if ate { | ||
1143 | // See doc comment for `unmatched_angle_bracket_count`. | ||
1144 | self.unmatched_angle_bracket_count += 1; | ||
1145 | self.max_angle_bracket_count += 1; | ||
1146 | debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count); | ||
1147 | } | ||
1148 | |||
1149 | ate | ||
1150 | } | ||
1151 | |||
1152 | fn expect_lt(&mut self) -> PResult<'a, ()> { | ||
1153 | if !self.eat_lt() { | ||
1154 | self.unexpected() | ||
1155 | } else { | ||
1156 | Ok(()) | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | /// Expects and consumes a single `>` token. if a `>>` is seen, replaces it | ||
1161 | /// with a single `>` and continues. If a `>` is not seen, signals an error. | ||
1162 | fn expect_gt(&mut self) -> PResult<'a, ()> { | ||
1163 | self.expected_tokens.push(TokenType::Token(token::Gt)); | ||
1164 | let ate = match self.token { | ||
1165 | token::Gt => { | ||
1166 | self.bump(); | ||
1167 | Some(()) | ||
1168 | } | ||
1169 | token::BinOp(token::Shr) => { | ||
1170 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1171 | Some(self.bump_with(token::Gt, span)) | ||
1172 | } | ||
1173 | token::BinOpEq(token::Shr) => { | ||
1174 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1175 | Some(self.bump_with(token::Ge, span)) | ||
1176 | } | ||
1177 | token::Ge => { | ||
1178 | let span = self.span.with_lo(self.span.lo() + BytePos(1)); | ||
1179 | Some(self.bump_with(token::Eq, span)) | ||
1180 | } | ||
1181 | _ => None, | ||
1182 | }; | ||
1183 | |||
1184 | match ate { | ||
1185 | Some(_) => { | ||
1186 | // See doc comment for `unmatched_angle_bracket_count`. | ||
1187 | if self.unmatched_angle_bracket_count > 0 { | ||
1188 | self.unmatched_angle_bracket_count -= 1; | ||
1189 | debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count); | ||
1190 | } | ||
1191 | |||
1192 | Ok(()) | ||
1193 | }, | ||
1194 | None => self.unexpected(), | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | /// Eats and discards tokens until one of `kets` is encountered. Respects token trees, | ||
1199 | /// passes through any errors encountered. Used for error recovery. | ||
1200 | fn eat_to_tokens(&mut self, kets: &[&token::Token]) { | ||
1201 | let handler = self.diagnostic(); | ||
1202 | |||
1203 | if let Err(ref mut err) = self.parse_seq_to_before_tokens(kets, | ||
1204 | SeqSep::none(), | ||
1205 | TokenExpectType::Expect, | ||
1206 | |p| Ok(p.parse_token_tree())) { | ||
1207 | handler.cancel(err); | ||
1208 | } | ||
1209 | } | ||
1210 | |||
1211 | /// Parses a sequence, including the closing delimiter. The function | ||
1212 | /// `f` must consume tokens until reaching the next separator or | ||
1213 | /// closing bracket. | ||
1214 | pub fn parse_seq_to_end<T, F>(&mut self, | ||
1215 | ket: &token::Token, | ||
1216 | sep: SeqSep, | ||
1217 | f: F) | ||
1218 | -> PResult<'a, Vec<T>> where | ||
1219 | F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | ||
1220 | { | ||
1221 | let (val, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; | ||
1222 | if !recovered { | ||
1223 | self.bump(); | ||
1224 | } | ||
1225 | Ok(val) | ||
1226 | } | ||
1227 | |||
1228 | /// Parses a sequence, not including the closing delimiter. The function | ||
1229 | /// `f` must consume tokens until reaching the next separator or | ||
1230 | /// closing bracket. | ||
1231 | pub fn parse_seq_to_before_end<T, F>( | ||
1232 | &mut self, | ||
1233 | ket: &token::Token, | ||
1234 | sep: SeqSep, | ||
1235 | f: F, | ||
1236 | ) -> PResult<'a, (Vec<T>, bool)> | ||
1237 | where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> | ||
1238 | { | ||
1239 | self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f) | ||
1240 | } | ||
1241 | |||
1242 | fn parse_seq_to_before_tokens<T, F>( | ||
1243 | &mut self, | ||
1244 | kets: &[&token::Token], | ||
1245 | sep: SeqSep, | ||
1246 | expect: TokenExpectType, | ||
1247 | mut f: F, | ||
1248 | ) -> PResult<'a, (Vec<T>, bool /* recovered */)> | ||
1249 | where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> | ||
1250 | { | ||
1251 | let mut first = true; | ||
1252 | let mut recovered = false; | ||
1253 | let mut v = vec![]; | ||
1254 | while !kets.iter().any(|k| { | ||
1255 | match expect { | ||
1256 | TokenExpectType::Expect => self.check(k), | ||
1257 | TokenExpectType::NoExpect => self.token == **k, | ||
1258 | } | ||
1259 | }) { | ||
1260 | match self.token { | ||
1261 | token::CloseDelim(..) | token::Eof => break, | ||
1262 | _ => {} | ||
1263 | }; | ||
1264 | if let Some(ref t) = sep.sep { | ||
1265 | if first { | ||
1266 | first = false; | ||
1267 | } else { | ||
1268 | match self.expect(t) { | ||
1269 | Ok(false) => {} | ||
1270 | Ok(true) => { | ||
1271 | recovered = true; | ||
1272 | break; | ||
1273 | } | ||
1274 | Err(mut e) => { | ||
1275 | // Attempt to keep parsing if it was a similar separator | ||
1276 | if let Some(ref tokens) = t.similar_tokens() { | ||
1277 | if tokens.contains(&self.token) { | ||
1278 | self.bump(); | ||
1279 | } | ||
1280 | } | ||
1281 | e.emit(); | ||
1282 | // Attempt to keep parsing if it was an omitted separator | ||
1283 | match f(self) { | ||
1284 | Ok(t) => { | ||
1285 | v.push(t); | ||
1286 | continue; | ||
1287 | }, | ||
1288 | Err(mut e) => { | ||
1289 | e.cancel(); | ||
1290 | break; | ||
1291 | } | ||
1292 | } | ||
1293 | } | ||
1294 | } | ||
1295 | } | ||
1296 | } | ||
1297 | if sep.trailing_sep_allowed && kets.iter().any(|k| { | ||
1298 | match expect { | ||
1299 | TokenExpectType::Expect => self.check(k), | ||
1300 | TokenExpectType::NoExpect => self.token == **k, | ||
1301 | } | ||
1302 | }) { | ||
1303 | break; | ||
1304 | } | ||
1305 | |||
1306 | let t = f(self)?; | ||
1307 | v.push(t); | ||
1308 | } | ||
1309 | |||
1310 | Ok((v, recovered)) | ||
1311 | } | ||
1312 | |||
1313 | /// Parses a sequence, including the closing delimiter. The function | ||
1314 | /// `f` must consume tokens until reaching the next separator or | ||
1315 | /// closing bracket. | ||
1316 | fn parse_unspanned_seq<T, F>( | ||
1317 | &mut self, | ||
1318 | bra: &token::Token, | ||
1319 | ket: &token::Token, | ||
1320 | sep: SeqSep, | ||
1321 | f: F, | ||
1322 | ) -> PResult<'a, Vec<T>> where | ||
1323 | F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, | ||
1324 | { | ||
1325 | self.expect(bra)?; | ||
1326 | let (result, recovered) = self.parse_seq_to_before_end(ket, sep, f)?; | ||
1327 | if !recovered { | ||
1328 | self.eat(ket); | ||
1329 | } | ||
1330 | Ok(result) | ||
1331 | } | ||
1332 | |||
1333 | /// Advance the parser by one token | ||
1334 | pub fn bump(&mut self) { | ||
1335 | if self.prev_token_kind == PrevTokenKind::Eof { | ||
1336 | // Bumping after EOF is a bad sign, usually an infinite loop. | ||
1337 | self.bug("attempted to bump the parser past EOF (may be stuck in a loop)"); | ||
1338 | } | ||
1339 | |||
1340 | self.prev_span = self.meta_var_span.take().unwrap_or(self.span); | ||
1341 | |||
1342 | // Record last token kind for possible error recovery. | ||
1343 | self.prev_token_kind = match self.token { | ||
1344 | token::DocComment(..) => PrevTokenKind::DocComment, | ||
1345 | token::Comma => PrevTokenKind::Comma, | ||
1346 | token::BinOp(token::Plus) => PrevTokenKind::Plus, | ||
1347 | token::Interpolated(..) => PrevTokenKind::Interpolated, | ||
1348 | token::Eof => PrevTokenKind::Eof, | ||
1349 | token::Ident(..) => PrevTokenKind::Ident, | ||
1350 | _ => PrevTokenKind::Other, | ||
1351 | }; | ||
1352 | |||
1353 | let next = self.next_tok(); | ||
1354 | self.span = next.sp; | ||
1355 | self.token = next.tok; | ||
1356 | self.expected_tokens.clear(); | ||
1357 | // check after each token | ||
1358 | self.process_potential_macro_variable(); | ||
1359 | } | ||
1360 | |||
1361 | /// Advance the parser using provided token as a next one. Use this when | ||
1362 | /// consuming a part of a token. For example a single `<` from `<<`. | ||
1363 | fn bump_with(&mut self, next: token::Token, span: Span) { | ||
1364 | self.prev_span = self.span.with_hi(span.lo()); | ||
1365 | // It would be incorrect to record the kind of the current token, but | ||
1366 | // fortunately for tokens currently using `bump_with`, the | ||
1367 | // prev_token_kind will be of no use anyway. | ||
1368 | self.prev_token_kind = PrevTokenKind::Other; | ||
1369 | self.span = span; | ||
1370 | self.token = next; | ||
1371 | self.expected_tokens.clear(); | ||
1372 | } | ||
1373 | |||
1374 | pub fn look_ahead<R, F>(&self, dist: usize, f: F) -> R where | ||
1375 | F: FnOnce(&token::Token) -> R, | ||
1376 | { | ||
1377 | if dist == 0 { | ||
1378 | return f(&self.token) | ||
1379 | } | ||
1380 | |||
1381 | f(&match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { | ||
1382 | Some(tree) => match tree { | ||
1383 | TokenTree::Token(_, tok) => tok, | ||
1384 | TokenTree::Delimited(_, delim, _) => token::OpenDelim(delim), | ||
1385 | }, | ||
1386 | None => token::CloseDelim(self.token_cursor.frame.delim), | ||
1387 | }) | ||
1388 | } | ||
1389 | |||
1390 | fn look_ahead_span(&self, dist: usize) -> Span { | ||
1391 | if dist == 0 { | ||
1392 | return self.span | ||
1393 | } | ||
1394 | |||
1395 | match self.token_cursor.frame.tree_cursor.look_ahead(dist - 1) { | ||
1396 | Some(TokenTree::Token(span, _)) => span, | ||
1397 | Some(TokenTree::Delimited(span, ..)) => span.entire(), | ||
1398 | None => self.look_ahead_span(dist - 1), | ||
1399 | } | ||
1400 | } | ||
1401 | pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { | ||
1402 | self.sess.span_diagnostic.struct_span_fatal(self.span, m) | ||
1403 | } | ||
1404 | pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { | ||
1405 | self.sess.span_diagnostic.struct_span_fatal(sp, m) | ||
1406 | } | ||
1407 | fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> { | ||
1408 | err.span_err(sp, self.diagnostic()) | ||
1409 | } | ||
1410 | fn bug(&self, m: &str) -> ! { | ||
1411 | self.sess.span_diagnostic.span_bug(self.span, m) | ||
1412 | } | ||
1413 | fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) { | ||
1414 | self.sess.span_diagnostic.span_err(sp, m) | ||
1415 | } | ||
1416 | fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { | ||
1417 | self.sess.span_diagnostic.struct_span_err(sp, m) | ||
1418 | } | ||
1419 | crate fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! { | ||
1420 | self.sess.span_diagnostic.span_bug(sp, m) | ||
1421 | } | ||
1422 | |||
1423 | fn cancel(&self, err: &mut DiagnosticBuilder<'_>) { | ||
1424 | self.sess.span_diagnostic.cancel(err) | ||
1425 | } | ||
1426 | |||
1427 | crate fn diagnostic(&self) -> &'a errors::Handler { | ||
1428 | &self.sess.span_diagnostic | ||
1429 | } | ||
1430 | |||
1431 | /// Is the current token one of the keywords that signals a bare function type? | ||
1432 | fn token_is_bare_fn_keyword(&mut self) -> bool { | ||
1433 | self.check_keyword(keywords::Fn) || | ||
1434 | self.check_keyword(keywords::Unsafe) || | ||
1435 | self.check_keyword(keywords::Extern) | ||
1436 | } | ||
1437 | |||
1438 | /// Parses a `TyKind::BareFn` type. | ||
1439 | fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> { | ||
1440 | /* | ||
1441 | |||
1442 | [unsafe] [extern "ABI"] fn (S) -> T | ||
1443 | ^~~~^ ^~~~^ ^~^ ^ | ||
1444 | | | | | | ||
1445 | | | | Return type | ||
1446 | | | Argument types | ||
1447 | | | | ||
1448 | | ABI | ||
1449 | Function Style | ||
1450 | */ | ||
1451 | |||
1452 | let unsafety = self.parse_unsafety(); | ||
1453 | let abi = if self.eat_keyword(keywords::Extern) { | ||
1454 | self.parse_opt_abi()?.unwrap_or(Abi::C) | ||
1455 | } else { | ||
1456 | Abi::Rust | ||
1457 | }; | ||
1458 | |||
1459 | self.expect_keyword(keywords::Fn)?; | ||
1460 | let (inputs, variadic) = self.parse_fn_args(false, true)?; | ||
1461 | let ret_ty = self.parse_ret_ty(false)?; | ||
1462 | let decl = P(FnDecl { | ||
1463 | inputs, | ||
1464 | output: ret_ty, | ||
1465 | variadic, | ||
1466 | }); | ||
1467 | Ok(TyKind::BareFn(P(BareFnTy { | ||
1468 | abi, | ||
1469 | unsafety, | ||
1470 | generic_params, | ||
1471 | decl, | ||
1472 | }))) | ||
1473 | } | ||
1474 | |||
1475 | /// Parses asyncness: `async` or nothing. | ||
1476 | fn parse_asyncness(&mut self) -> IsAsync { | ||
1477 | if self.eat_keyword(keywords::Async) { | ||
1478 | IsAsync::Async { | ||
1479 | closure_id: ast::DUMMY_NODE_ID, | ||
1480 | return_impl_trait_id: ast::DUMMY_NODE_ID, | ||
1481 | } | ||
1482 | } else { | ||
1483 | IsAsync::NotAsync | ||
1484 | } | ||
1485 | } | ||
1486 | |||
1487 | /// Parses unsafety: `unsafe` or nothing. | ||
1488 | fn parse_unsafety(&mut self) -> Unsafety { | ||
1489 | if self.eat_keyword(keywords::Unsafe) { | ||
1490 | Unsafety::Unsafe | ||
1491 | } else { | ||
1492 | Unsafety::Normal | ||
1493 | } | ||
1494 | } | ||
1495 | |||
1496 | /// Parses the items in a trait declaration. | ||
1497 | pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { | ||
1498 | maybe_whole!(self, NtTraitItem, |x| x); | ||
1499 | let attrs = self.parse_outer_attributes()?; | ||
1500 | let (mut item, tokens) = self.collect_tokens(|this| { | ||
1501 | this.parse_trait_item_(at_end, attrs) | ||
1502 | })?; | ||
1503 | // See `parse_item` for why this clause is here. | ||
1504 | if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { | ||
1505 | item.tokens = Some(tokens); | ||
1506 | } | ||
1507 | Ok(item) | ||
1508 | } | ||
1509 | |||
1510 | fn parse_trait_item_(&mut self, | ||
1511 | at_end: &mut bool, | ||
1512 | mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> { | ||
1513 | let lo = self.span; | ||
1514 | |||
1515 | let (name, node, generics) = if self.eat_keyword(keywords::Type) { | ||
1516 | self.parse_trait_item_assoc_ty()? | ||
1517 | } else if self.is_const_item() { | ||
1518 | self.expect_keyword(keywords::Const)?; | ||
1519 | let ident = self.parse_ident()?; | ||
1520 | self.expect(&token::Colon)?; | ||
1521 | let ty = self.parse_ty()?; | ||
1522 | let default = if self.eat(&token::Eq) { | ||
1523 | let expr = self.parse_expr()?; | ||
1524 | self.expect(&token::Semi)?; | ||
1525 | Some(expr) | ||
1526 | } else { | ||
1527 | self.expect(&token::Semi)?; | ||
1528 | None | ||
1529 | }; | ||
1530 | (ident, TraitItemKind::Const(ty, default), ast::Generics::default()) | ||
1531 | } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { | ||
1532 | // trait item macro. | ||
1533 | (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) | ||
1534 | } else { | ||
1535 | let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; | ||
1536 | |||
1537 | let ident = self.parse_ident()?; | ||
1538 | let mut generics = self.parse_generics()?; | ||
1539 | |||
1540 | let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| { | ||
1541 | // This is somewhat dubious; We don't want to allow | ||
1542 | // argument names to be left off if there is a | ||
1543 | // definition... | ||
1544 | |||
1545 | // We don't allow argument names to be left off in edition 2018. | ||
1546 | p.parse_arg_general(p.span.rust_2018(), true) | ||
1547 | })?; | ||
1548 | generics.where_clause = self.parse_where_clause()?; | ||
1549 | |||
1550 | let sig = ast::MethodSig { | ||
1551 | header: FnHeader { | ||
1552 | unsafety, | ||
1553 | constness, | ||
1554 | abi, | ||
1555 | asyncness, | ||
1556 | }, | ||
1557 | decl: d, | ||
1558 | }; | ||
1559 | |||
1560 | let body = match self.token { | ||
1561 | token::Semi => { | ||
1562 | self.bump(); | ||
1563 | *at_end = true; | ||
1564 | debug!("parse_trait_methods(): parsing required method"); | ||
1565 | None | ||
1566 | } | ||
1567 | token::OpenDelim(token::Brace) => { | ||
1568 | debug!("parse_trait_methods(): parsing provided method"); | ||
1569 | *at_end = true; | ||
1570 | let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; | ||
1571 | attrs.extend(inner_attrs.iter().cloned()); | ||
1572 | Some(body) | ||
1573 | } | ||
1574 | token::Interpolated(ref nt) => { | ||
1575 | match **nt { | ||
1576 | token::NtBlock(..) => { | ||
1577 | *at_end = true; | ||
1578 | let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; | ||
1579 | attrs.extend(inner_attrs.iter().cloned()); | ||
1580 | Some(body) | ||
1581 | } | ||
1582 | _ => { | ||
1583 | let token_str = self.this_token_descr(); | ||
1584 | let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", | ||
1585 | token_str)); | ||
1586 | err.span_label(self.span, "expected `;` or `{`"); | ||
1587 | return Err(err); | ||
1588 | } | ||
1589 | } | ||
1590 | } | ||
1591 | _ => { | ||
1592 | let token_str = self.this_token_descr(); | ||
1593 | let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", | ||
1594 | token_str)); | ||
1595 | err.span_label(self.span, "expected `;` or `{`"); | ||
1596 | return Err(err); | ||
1597 | } | ||
1598 | }; | ||
1599 | (ident, ast::TraitItemKind::Method(sig, body), generics) | ||
1600 | }; | ||
1601 | |||
1602 | Ok(TraitItem { | ||
1603 | id: ast::DUMMY_NODE_ID, | ||
1604 | ident: name, | ||
1605 | attrs, | ||
1606 | generics, | ||
1607 | node, | ||
1608 | span: lo.to(self.prev_span), | ||
1609 | tokens: None, | ||
1610 | }) | ||
1611 | } | ||
1612 | |||
1613 | /// Parses an optional return type `[ -> TY ]` in a function declaration. | ||
1614 | fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> { | ||
1615 | if self.eat(&token::RArrow) { | ||
1616 | Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?)) | ||
1617 | } else { | ||
1618 | Ok(FunctionRetTy::Default(self.span.shrink_to_lo())) | ||
1619 | } | ||
1620 | } | ||
1621 | |||
1622 | /// Parses a type. | ||
1623 | pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> { | ||
1624 | self.parse_ty_common(true, true) | ||
1625 | } | ||
1626 | |||
1627 | /// Parses a type in restricted contexts where `+` is not permitted. | ||
1628 | /// | ||
1629 | /// Example 1: `&'a TYPE` | ||
1630 | /// `+` is prohibited to maintain operator priority (P(+) < P(&)). | ||
1631 | /// Example 2: `value1 as TYPE + value2` | ||
1632 | /// `+` is prohibited to avoid interactions with expression grammar. | ||
1633 | fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> { | ||
1634 | self.parse_ty_common(false, true) | ||
1635 | } | ||
1636 | |||
1637 | fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool) | ||
1638 | -> PResult<'a, P<Ty>> { | ||
1639 | maybe_whole!(self, NtTy, |x| x); | ||
1640 | |||
1641 | let lo = self.span; | ||
1642 | let mut impl_dyn_multi = false; | ||
1643 | let node = if self.eat(&token::OpenDelim(token::Paren)) { | ||
1644 | // `(TYPE)` is a parenthesized type. | ||
1645 | // `(TYPE,)` is a tuple with a single field of type TYPE. | ||
1646 | let mut ts = vec![]; | ||
1647 | let mut last_comma = false; | ||
1648 | while self.token != token::CloseDelim(token::Paren) { | ||
1649 | ts.push(self.parse_ty()?); | ||
1650 | if self.eat(&token::Comma) { | ||
1651 | last_comma = true; | ||
1652 | } else { | ||
1653 | last_comma = false; | ||
1654 | break; | ||
1655 | } | ||
1656 | } | ||
1657 | let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus; | ||
1658 | self.expect(&token::CloseDelim(token::Paren))?; | ||
1659 | |||
1660 | if ts.len() == 1 && !last_comma { | ||
1661 | let ty = ts.into_iter().nth(0).unwrap().into_inner(); | ||
1662 | let maybe_bounds = allow_plus && self.token.is_like_plus(); | ||
1663 | match ty.node { | ||
1664 | // `(TY_BOUND_NOPAREN) + BOUND + ...`. | ||
1665 | TyKind::Path(None, ref path) if maybe_bounds => { | ||
1666 | self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)? | ||
1667 | } | ||
1668 | TyKind::TraitObject(ref bounds, TraitObjectSyntax::None) | ||
1669 | if maybe_bounds && bounds.len() == 1 && !trailing_plus => { | ||
1670 | let path = match bounds[0] { | ||
1671 | GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(), | ||
1672 | GenericBound::Outlives(..) => self.bug("unexpected lifetime bound"), | ||
1673 | }; | ||
1674 | self.parse_remaining_bounds(Vec::new(), path, lo, true)? | ||
1675 | } | ||
1676 | // `(TYPE)` | ||
1677 | _ => TyKind::Paren(P(ty)) | ||
1678 | } | ||
1679 | } else { | ||
1680 | TyKind::Tup(ts) | ||
1681 | } | ||
1682 | } else if self.eat(&token::Not) { | ||
1683 | // Never type `!` | ||
1684 | TyKind::Never | ||
1685 | } else if self.eat(&token::BinOp(token::Star)) { | ||
1686 | // Raw pointer | ||
1687 | TyKind::Ptr(self.parse_ptr()?) | ||
1688 | } else if self.eat(&token::OpenDelim(token::Bracket)) { | ||
1689 | // Array or slice | ||
1690 | let t = self.parse_ty()?; | ||
1691 | // Parse optional `; EXPR` in `[TYPE; EXPR]` | ||
1692 | let t = match self.maybe_parse_fixed_length_of_vec()? { | ||
1693 | None => TyKind::Slice(t), | ||
1694 | Some(length) => TyKind::Array(t, AnonConst { | ||
1695 | id: ast::DUMMY_NODE_ID, | ||
1696 | value: length, | ||
1697 | }), | ||
1698 | }; | ||
1699 | self.expect(&token::CloseDelim(token::Bracket))?; | ||
1700 | t | ||
1701 | } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) { | ||
1702 | // Reference | ||
1703 | self.expect_and()?; | ||
1704 | self.parse_borrowed_pointee()? | ||
1705 | } else if self.eat_keyword_noexpect(keywords::Typeof) { | ||
1706 | // `typeof(EXPR)` | ||
1707 | // In order to not be ambiguous, the type must be surrounded by parens. | ||
1708 | self.expect(&token::OpenDelim(token::Paren))?; | ||
1709 | let e = AnonConst { | ||
1710 | id: ast::DUMMY_NODE_ID, | ||
1711 | value: self.parse_expr()?, | ||
1712 | }; | ||
1713 | self.expect(&token::CloseDelim(token::Paren))?; | ||
1714 | TyKind::Typeof(e) | ||
1715 | } else if self.eat_keyword(keywords::Underscore) { | ||
1716 | // A type to be inferred `_` | ||
1717 | TyKind::Infer | ||
1718 | } else if self.token_is_bare_fn_keyword() { | ||
1719 | // Function pointer type | ||
1720 | self.parse_ty_bare_fn(Vec::new())? | ||
1721 | } else if self.check_keyword(keywords::For) { | ||
1722 | // Function pointer type or bound list (trait object type) starting with a poly-trait. | ||
1723 | // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` | ||
1724 | // `for<'lt> Trait1<'lt> + Trait2 + 'a` | ||
1725 | let lo = self.span; | ||
1726 | let lifetime_defs = self.parse_late_bound_lifetime_defs()?; | ||
1727 | if self.token_is_bare_fn_keyword() { | ||
1728 | self.parse_ty_bare_fn(lifetime_defs)? | ||
1729 | } else { | ||
1730 | let path = self.parse_path(PathStyle::Type)?; | ||
1731 | let parse_plus = allow_plus && self.check_plus(); | ||
1732 | self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? | ||
1733 | } | ||
1734 | } else if self.eat_keyword(keywords::Impl) { | ||
1735 | // Always parse bounds greedily for better error recovery. | ||
1736 | let bounds = self.parse_generic_bounds(None)?; | ||
1737 | impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; | ||
1738 | TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) | ||
1739 | } else if self.check_keyword(keywords::Dyn) && | ||
1740 | (self.span.rust_2018() || | ||
1741 | self.look_ahead(1, |t| t.can_begin_bound() && | ||
1742 | !can_continue_type_after_non_fn_ident(t))) { | ||
1743 | self.bump(); // `dyn` | ||
1744 | // Always parse bounds greedily for better error recovery. | ||
1745 | let bounds = self.parse_generic_bounds(None)?; | ||
1746 | impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; | ||
1747 | TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) | ||
1748 | } else if self.check(&token::Question) || | ||
1749 | self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) { | ||
1750 | // Bound list (trait object type) | ||
1751 | TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus, None)?, | ||
1752 | TraitObjectSyntax::None) | ||
1753 | } else if self.eat_lt() { | ||
1754 | // Qualified path | ||
1755 | let (qself, path) = self.parse_qpath(PathStyle::Type)?; | ||
1756 | TyKind::Path(Some(qself), path) | ||
1757 | } else if self.token.is_path_start() { | ||
1758 | // Simple path | ||
1759 | let path = self.parse_path(PathStyle::Type)?; | ||
1760 | if self.eat(&token::Not) { | ||
1761 | // Macro invocation in type position | ||
1762 | let (delim, tts) = self.expect_delimited_token_tree()?; | ||
1763 | let node = Mac_ { path, tts, delim }; | ||
1764 | TyKind::Mac(respan(lo.to(self.prev_span), node)) | ||
1765 | } else { | ||
1766 | // Just a type path or bound list (trait object type) starting with a trait. | ||
1767 | // `Type` | ||
1768 | // `Trait1 + Trait2 + 'a` | ||
1769 | if allow_plus && self.check_plus() { | ||
1770 | self.parse_remaining_bounds(Vec::new(), path, lo, true)? | ||
1771 | } else { | ||
1772 | TyKind::Path(None, path) | ||
1773 | } | ||
1774 | } | ||
1775 | } else { | ||
1776 | let msg = format!("expected type, found {}", self.this_token_descr()); | ||
1777 | return Err(self.fatal(&msg)); | ||
1778 | }; | ||
1779 | |||
1780 | let span = lo.to(self.prev_span); | ||
1781 | let ty = Ty { node, span, id: ast::DUMMY_NODE_ID }; | ||
1782 | |||
1783 | // Try to recover from use of `+` with incorrect priority. | ||
1784 | self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty); | ||
1785 | self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?; | ||
1786 | let ty = self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)?; | ||
1787 | |||
1788 | Ok(P(ty)) | ||
1789 | } | ||
1790 | |||
1791 | fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path, | ||
1792 | lo: Span, parse_plus: bool) -> PResult<'a, TyKind> { | ||
1793 | let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); | ||
1794 | let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; | ||
1795 | if parse_plus { | ||
1796 | self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded | ||
1797 | bounds.append(&mut self.parse_generic_bounds(None)?); | ||
1798 | } | ||
1799 | Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) | ||
1800 | } | ||
1801 | |||
1802 | fn maybe_report_ambiguous_plus(&mut self, allow_plus: bool, impl_dyn_multi: bool, ty: &Ty) { | ||
1803 | if !allow_plus && impl_dyn_multi { | ||
1804 | let sum_with_parens = format!("({})", pprust::ty_to_string(&ty)); | ||
1805 | self.struct_span_err(ty.span, "ambiguous `+` in a type") | ||
1806 | .span_suggestion( | ||
1807 | ty.span, | ||
1808 | "use parentheses to disambiguate", | ||
1809 | sum_with_parens, | ||
1810 | Applicability::MachineApplicable | ||
1811 | ).emit(); | ||
1812 | } | ||
1813 | } | ||
1814 | |||
1815 | fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> { | ||
1816 | // Do not add `+` to expected tokens. | ||
1817 | if !allow_plus || !self.token.is_like_plus() { | ||
1818 | return Ok(()) | ||
1819 | } | ||
1820 | |||
1821 | self.bump(); // `+` | ||
1822 | let bounds = self.parse_generic_bounds(None)?; | ||
1823 | let sum_span = ty.span.to(self.prev_span); | ||
1824 | |||
1825 | let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178, | ||
1826 | "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(ty)); | ||
1827 | |||
1828 | match ty.node { | ||
1829 | TyKind::Rptr(ref lifetime, ref mut_ty) => { | ||
1830 | let sum_with_parens = pprust::to_string(|s| { | ||
1831 | use crate::print::pprust::PrintState; | ||
1832 | |||
1833 | s.s.word("&")?; | ||
1834 | s.print_opt_lifetime(lifetime)?; | ||
1835 | s.print_mutability(mut_ty.mutbl)?; | ||
1836 | s.popen()?; | ||
1837 | s.print_type(&mut_ty.ty)?; | ||
1838 | s.print_type_bounds(" +", &bounds)?; | ||
1839 | s.pclose() | ||
1840 | }); | ||
1841 | err.span_suggestion( | ||
1842 | sum_span, | ||
1843 | "try adding parentheses", | ||
1844 | sum_with_parens, | ||
1845 | Applicability::MachineApplicable | ||
1846 | ); | ||
1847 | } | ||
1848 | TyKind::Ptr(..) | TyKind::BareFn(..) => { | ||
1849 | err.span_label(sum_span, "perhaps you forgot parentheses?"); | ||
1850 | } | ||
1851 | _ => { | ||
1852 | err.span_label(sum_span, "expected a path"); | ||
1853 | }, | ||
1854 | } | ||
1855 | err.emit(); | ||
1856 | Ok(()) | ||
1857 | } | ||
1858 | |||
1859 | // Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`. | ||
1860 | fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T, allow_recovery: bool) | ||
1861 | -> PResult<'a, T> { | ||
1862 | // Do not add `::` to expected tokens. | ||
1863 | if !allow_recovery || self.token != token::ModSep { | ||
1864 | return Ok(base); | ||
1865 | } | ||
1866 | let ty = match base.to_ty() { | ||
1867 | Some(ty) => ty, | ||
1868 | None => return Ok(base), | ||
1869 | }; | ||
1870 | |||
1871 | self.bump(); // `::` | ||
1872 | let mut segments = Vec::new(); | ||
1873 | self.parse_path_segments(&mut segments, T::PATH_STYLE, true)?; | ||
1874 | |||
1875 | let span = ty.span.to(self.prev_span); | ||
1876 | let path_span = span.to(span); // use an empty path since `position` == 0 | ||
1877 | let recovered = base.to_recovered( | ||
1878 | Some(QSelf { ty, path_span, position: 0 }), | ||
1879 | ast::Path { segments, span }, | ||
1880 | ); | ||
1881 | |||
1882 | self.diagnostic() | ||
1883 | .struct_span_err(span, "missing angle brackets in associated item path") | ||
1884 | .span_suggestion( // this is a best-effort recovery | ||
1885 | span, "try", recovered.to_string(), Applicability::MaybeIncorrect | ||
1886 | ).emit(); | ||
1887 | |||
1888 | Ok(recovered) | ||
1889 | } | ||
1890 | |||
1891 | fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> { | ||
1892 | let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None }; | ||
1893 | let mutbl = self.parse_mutability(); | ||
1894 | let ty = self.parse_ty_no_plus()?; | ||
1895 | return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty: ty, mutbl: mutbl })); | ||
1896 | } | ||
1897 | |||
1898 | fn parse_ptr(&mut self) -> PResult<'a, MutTy> { | ||
1899 | let mutbl = if self.eat_keyword(keywords::Mut) { | ||
1900 | Mutability::Mutable | ||
1901 | } else if self.eat_keyword(keywords::Const) { | ||
1902 | Mutability::Immutable | ||
1903 | } else { | ||
1904 | let span = self.prev_span; | ||
1905 | let msg = "expected mut or const in raw pointer type"; | ||
1906 | self.struct_span_err(span, msg) | ||
1907 | .span_label(span, msg) | ||
1908 | .help("use `*mut T` or `*const T` as appropriate") | ||
1909 | .emit(); | ||
1910 | Mutability::Immutable | ||
1911 | }; | ||
1912 | let t = self.parse_ty_no_plus()?; | ||
1913 | Ok(MutTy { ty: t, mutbl: mutbl }) | ||
1914 | } | ||
1915 | |||
1916 | fn is_named_argument(&mut self) -> bool { | ||
1917 | let offset = match self.token { | ||
1918 | token::Interpolated(ref nt) => match **nt { | ||
1919 | token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), | ||
1920 | _ => 0, | ||
1921 | } | ||
1922 | token::BinOp(token::And) | token::AndAnd => 1, | ||
1923 | _ if self.token.is_keyword(keywords::Mut) => 1, | ||
1924 | _ => 0, | ||
1925 | }; | ||
1926 | |||
1927 | self.look_ahead(offset, |t| t.is_ident()) && | ||
1928 | self.look_ahead(offset + 1, |t| t == &token::Colon) | ||
1929 | } | ||
1930 | |||
1931 | /// Skips unexpected attributes and doc comments in this position and emits an appropriate | ||
1932 | /// error. | ||
1933 | fn eat_incorrect_doc_comment(&mut self, applied_to: &str) { | ||
1934 | if let token::DocComment(_) = self.token { | ||
1935 | let mut err = self.diagnostic().struct_span_err( | ||
1936 | self.span, | ||
1937 | &format!("documentation comments cannot be applied to {}", applied_to), | ||
1938 | ); | ||
1939 | err.span_label(self.span, "doc comments are not allowed here"); | ||
1940 | err.emit(); | ||
1941 | self.bump(); | ||
1942 | } else if self.token == token::Pound && self.look_ahead(1, |t| { | ||
1943 | *t == token::OpenDelim(token::Bracket) | ||
1944 | }) { | ||
1945 | let lo = self.span; | ||
1946 | // Skip every token until next possible arg. | ||
1947 | while self.token != token::CloseDelim(token::Bracket) { | ||
1948 | self.bump(); | ||
1949 | } | ||
1950 | let sp = lo.to(self.span); | ||
1951 | self.bump(); | ||
1952 | let mut err = self.diagnostic().struct_span_err( | ||
1953 | sp, | ||
1954 | &format!("attributes cannot be applied to {}", applied_to), | ||
1955 | ); | ||
1956 | err.span_label(sp, "attributes are not allowed here"); | ||
1957 | err.emit(); | ||
1958 | } | ||
1959 | } | ||
1960 | |||
1961 | /// This version of parse arg doesn't necessarily require identifier names. | ||
1962 | fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool) -> PResult<'a, Arg> { | ||
1963 | maybe_whole!(self, NtArg, |x| x); | ||
1964 | |||
1965 | if let Ok(Some(_)) = self.parse_self_arg() { | ||
1966 | let mut err = self.struct_span_err(self.prev_span, | ||
1967 | "unexpected `self` argument in function"); | ||
1968 | err.span_label(self.prev_span, | ||
1969 | "`self` is only valid as the first argument of an associated function"); | ||
1970 | return Err(err); | ||
1971 | } | ||
1972 | |||
1973 | let (pat, ty) = if require_name || self.is_named_argument() { | ||
1974 | debug!("parse_arg_general parse_pat (require_name:{})", | ||
1975 | require_name); | ||
1976 | self.eat_incorrect_doc_comment("method arguments"); | ||
1977 | let pat = self.parse_pat(Some("argument name"))?; | ||
1978 | |||
1979 | if let Err(mut err) = self.expect(&token::Colon) { | ||
1980 | // If we find a pattern followed by an identifier, it could be an (incorrect) | ||
1981 | // C-style parameter declaration. | ||
1982 | if self.check_ident() && self.look_ahead(1, |t| { | ||
1983 | *t == token::Comma || *t == token::CloseDelim(token::Paren) | ||
1984 | }) { | ||
1985 | let ident = self.parse_ident().unwrap(); | ||
1986 | let span = pat.span.with_hi(ident.span.hi()); | ||
1987 | |||
1988 | err.span_suggestion( | ||
1989 | span, | ||
1990 | "declare the type after the parameter binding", | ||
1991 | String::from("<identifier>: <type>"), | ||
1992 | Applicability::HasPlaceholders, | ||
1993 | ); | ||
1994 | } else if require_name && is_trait_item { | ||
1995 | if let PatKind::Ident(_, ident, _) = pat.node { | ||
1996 | err.span_suggestion( | ||
1997 | pat.span, | ||
1998 | "explicitly ignore parameter", | ||
1999 | format!("_: {}", ident), | ||
2000 | Applicability::MachineApplicable, | ||
2001 | ); | ||
2002 | } | ||
2003 | |||
2004 | err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)"); | ||
2005 | } | ||
2006 | |||
2007 | return Err(err); | ||
2008 | } | ||
2009 | |||
2010 | self.eat_incorrect_doc_comment("a method argument's type"); | ||
2011 | (pat, self.parse_ty()?) | ||
2012 | } else { | ||
2013 | debug!("parse_arg_general ident_to_pat"); | ||
2014 | let parser_snapshot_before_ty = self.clone(); | ||
2015 | self.eat_incorrect_doc_comment("a method argument's type"); | ||
2016 | let mut ty = self.parse_ty(); | ||
2017 | if ty.is_ok() && self.token != token::Comma && | ||
2018 | self.token != token::CloseDelim(token::Paren) { | ||
2019 | // This wasn't actually a type, but a pattern looking like a type, | ||
2020 | // so we are going to rollback and re-parse for recovery. | ||
2021 | ty = self.unexpected(); | ||
2022 | } | ||
2023 | match ty { | ||
2024 | Ok(ty) => { | ||
2025 | let ident = Ident::new(keywords::Invalid.name(), self.prev_span); | ||
2026 | let pat = P(Pat { | ||
2027 | id: ast::DUMMY_NODE_ID, | ||
2028 | node: PatKind::Ident( | ||
2029 | BindingMode::ByValue(Mutability::Immutable), ident, None), | ||
2030 | span: ty.span, | ||
2031 | }); | ||
2032 | (pat, ty) | ||
2033 | } | ||
2034 | Err(mut err) => { | ||
2035 | // Recover from attempting to parse the argument as a type without pattern. | ||
2036 | err.cancel(); | ||
2037 | mem::replace(self, parser_snapshot_before_ty); | ||
2038 | let pat = self.parse_pat(Some("argument name"))?; | ||
2039 | self.expect(&token::Colon)?; | ||
2040 | let ty = self.parse_ty()?; | ||
2041 | |||
2042 | let mut err = self.diagnostic().struct_span_err_with_code( | ||
2043 | pat.span, | ||
2044 | "patterns aren't allowed in methods without bodies", | ||
2045 | DiagnosticId::Error("E0642".into()), | ||
2046 | ); | ||
2047 | err.span_suggestion_short( | ||
2048 | pat.span, | ||
2049 | "give this argument a name or use an underscore to ignore it", | ||
2050 | "_".to_owned(), | ||
2051 | Applicability::MachineApplicable, | ||
2052 | ); | ||
2053 | err.emit(); | ||
2054 | |||
2055 | // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. | ||
2056 | let pat = P(Pat { | ||
2057 | node: PatKind::Wild, | ||
2058 | span: pat.span, | ||
2059 | id: ast::DUMMY_NODE_ID | ||
2060 | }); | ||
2061 | (pat, ty) | ||
2062 | } | ||
2063 | } | ||
2064 | }; | ||
2065 | |||
2066 | Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID }) | ||
2067 | } | ||
2068 | |||
2069 | /// Parses a single function argument. | ||
2070 | crate fn parse_arg(&mut self) -> PResult<'a, Arg> { | ||
2071 | self.parse_arg_general(true, false) | ||
2072 | } | ||
2073 | |||
2074 | /// Parses an argument in a lambda header (e.g., `|arg, arg|`). | ||
2075 | fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { | ||
2076 | let pat = self.parse_pat(Some("argument name"))?; | ||
2077 | let t = if self.eat(&token::Colon) { | ||
2078 | self.parse_ty()? | ||
2079 | } else { | ||
2080 | P(Ty { | ||
2081 | id: ast::DUMMY_NODE_ID, | ||
2082 | node: TyKind::Infer, | ||
2083 | span: self.prev_span, | ||
2084 | }) | ||
2085 | }; | ||
2086 | Ok(Arg { | ||
2087 | ty: t, | ||
2088 | pat, | ||
2089 | id: ast::DUMMY_NODE_ID | ||
2090 | }) | ||
2091 | } | ||
2092 | |||
2093 | fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> { | ||
2094 | if self.eat(&token::Semi) { | ||
2095 | Ok(Some(self.parse_expr()?)) | ||
2096 | } else { | ||
2097 | Ok(None) | ||
2098 | } | ||
2099 | } | ||
2100 | |||
2101 | /// Matches `token_lit = LIT_INTEGER | ...`. | ||
2102 | fn parse_lit_token(&mut self) -> PResult<'a, LitKind> { | ||
2103 | let out = match self.token { | ||
2104 | token::Interpolated(ref nt) => match **nt { | ||
2105 | token::NtExpr(ref v) | token::NtLiteral(ref v) => match v.node { | ||
2106 | ExprKind::Lit(ref lit) => { lit.node.clone() } | ||
2107 | _ => { return self.unexpected_last(&self.token); } | ||
2108 | }, | ||
2109 | _ => { return self.unexpected_last(&self.token); } | ||
2110 | }, | ||
2111 | token::Literal(lit, suf) => { | ||
2112 | let diag = Some((self.span, &self.sess.span_diagnostic)); | ||
2113 | let (suffix_illegal, result) = parse::lit_token(lit, suf, diag); | ||
2114 | |||
2115 | if suffix_illegal { | ||
2116 | let sp = self.span; | ||
2117 | self.expect_no_suffix(sp, lit.literal_name(), suf) | ||
2118 | } | ||
2119 | |||
2120 | result.unwrap() | ||
2121 | } | ||
2122 | token::Dot if self.look_ahead(1, |t| match t { | ||
2123 | token::Literal(parse::token::Lit::Integer(_) , _) => true, | ||
2124 | _ => false, | ||
2125 | }) => { // recover from `let x = .4;` | ||
2126 | let lo = self.span; | ||
2127 | self.bump(); | ||
2128 | if let token::Literal( | ||
2129 | parse::token::Lit::Integer(val), | ||
2130 | suffix, | ||
2131 | ) = self.token { | ||
2132 | let suffix = suffix.and_then(|s| { | ||
2133 | let s = s.as_str().get(); | ||
2134 | if ["f32", "f64"].contains(&s) { | ||
2135 | Some(s) | ||
2136 | } else { | ||
2137 | None | ||
2138 | } | ||
2139 | }).unwrap_or(""); | ||
2140 | self.bump(); | ||
2141 | let sp = lo.to(self.prev_span); | ||
2142 | let mut err = self.diagnostic() | ||
2143 | .struct_span_err(sp, "float literals must have an integer part"); | ||
2144 | err.span_suggestion( | ||
2145 | sp, | ||
2146 | "must have an integer part", | ||
2147 | format!("0.{}{}", val, suffix), | ||
2148 | Applicability::MachineApplicable, | ||
2149 | ); | ||
2150 | err.emit(); | ||
2151 | return Ok(match suffix { | ||
2152 | "f32" => ast::LitKind::Float(val, ast::FloatTy::F32), | ||
2153 | "f64" => ast::LitKind::Float(val, ast::FloatTy::F64), | ||
2154 | _ => ast::LitKind::FloatUnsuffixed(val), | ||
2155 | }); | ||
2156 | } else { | ||
2157 | unreachable!(); | ||
2158 | }; | ||
2159 | } | ||
2160 | _ => { return self.unexpected_last(&self.token); } | ||
2161 | }; | ||
2162 | |||
2163 | self.bump(); | ||
2164 | Ok(out) | ||
2165 | } | ||
2166 | |||
2167 | /// Matches `lit = true | false | token_lit`. | ||
2168 | crate fn parse_lit(&mut self) -> PResult<'a, Lit> { | ||
2169 | let lo = self.span; | ||
2170 | let lit = if self.eat_keyword(keywords::True) { | ||
2171 | LitKind::Bool(true) | ||
2172 | } else if self.eat_keyword(keywords::False) { | ||
2173 | LitKind::Bool(false) | ||
2174 | } else { | ||
2175 | let lit = self.parse_lit_token()?; | ||
2176 | lit | ||
2177 | }; | ||
2178 | Ok(source_map::Spanned { node: lit, span: lo.to(self.prev_span) }) | ||
2179 | } | ||
2180 | |||
2181 | /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). | ||
2182 | crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> { | ||
2183 | maybe_whole_expr!(self); | ||
2184 | |||
2185 | let minus_lo = self.span; | ||
2186 | let minus_present = self.eat(&token::BinOp(token::Minus)); | ||
2187 | let lo = self.span; | ||
2188 | let literal = self.parse_lit()?; | ||
2189 | let hi = self.prev_span; | ||
2190 | let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new()); | ||
2191 | |||
2192 | if minus_present { | ||
2193 | let minus_hi = self.prev_span; | ||
2194 | let unary = self.mk_unary(UnOp::Neg, expr); | ||
2195 | Ok(self.mk_expr(minus_lo.to(minus_hi), unary, ThinVec::new())) | ||
2196 | } else { | ||
2197 | Ok(expr) | ||
2198 | } | ||
2199 | } | ||
2200 | |||
2201 | fn parse_path_segment_ident(&mut self) -> PResult<'a, ast::Ident> { | ||
2202 | match self.token { | ||
2203 | token::Ident(ident, _) if self.token.is_path_segment_keyword() => { | ||
2204 | let span = self.span; | ||
2205 | self.bump(); | ||
2206 | Ok(Ident::new(ident.name, span)) | ||
2207 | } | ||
2208 | _ => self.parse_ident(), | ||
2209 | } | ||
2210 | } | ||
2211 | |||
2212 | fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { | ||
2213 | match self.token { | ||
2214 | token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { | ||
2215 | let span = self.span; | ||
2216 | self.bump(); | ||
2217 | Ok(Ident::new(ident.name, span)) | ||
2218 | } | ||
2219 | _ => self.parse_ident(), | ||
2220 | } | ||
2221 | } | ||
2222 | |||
2223 | /// Parses a qualified path. | ||
2224 | /// Assumes that the leading `<` has been parsed already. | ||
2225 | /// | ||
2226 | /// `qualified_path = <type [as trait_ref]>::path` | ||
2227 | /// | ||
2228 | /// # Examples | ||
2229 | /// `<T>::default` | ||
2230 | /// `<T as U>::a` | ||
2231 | /// `<T as U>::F::a<S>` (without disambiguator) | ||
2232 | /// `<T as U>::F::a::<S>` (with disambiguator) | ||
2233 | fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, ast::Path)> { | ||
2234 | let lo = self.prev_span; | ||
2235 | let ty = self.parse_ty()?; | ||
2236 | |||
2237 | // `path` will contain the prefix of the path up to the `>`, | ||
2238 | // if any (e.g., `U` in the `<T as U>::*` examples | ||
2239 | // above). `path_span` has the span of that path, or an empty | ||
2240 | // span in the case of something like `<T>::Bar`. | ||
2241 | let (mut path, path_span); | ||
2242 | if self.eat_keyword(keywords::As) { | ||
2243 | let path_lo = self.span; | ||
2244 | path = self.parse_path(PathStyle::Type)?; | ||
2245 | path_span = path_lo.to(self.prev_span); | ||
2246 | } else { | ||
2247 | path = ast::Path { segments: Vec::new(), span: syntax_pos::DUMMY_SP }; | ||
2248 | path_span = self.span.to(self.span); | ||
2249 | } | ||
2250 | |||
2251 | // See doc comment for `unmatched_angle_bracket_count`. | ||
2252 | self.expect(&token::Gt)?; | ||
2253 | if self.unmatched_angle_bracket_count > 0 { | ||
2254 | self.unmatched_angle_bracket_count -= 1; | ||
2255 | debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count); | ||
2256 | } | ||
2257 | |||
2258 | self.expect(&token::ModSep)?; | ||
2259 | |||
2260 | let qself = QSelf { ty, path_span, position: path.segments.len() }; | ||
2261 | self.parse_path_segments(&mut path.segments, style, true)?; | ||
2262 | |||
2263 | Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) })) | ||
2264 | } | ||
2265 | |||
2266 | /// Parses simple paths. | ||
2267 | /// | ||
2268 | /// `path = [::] segment+` | ||
2269 | /// `segment = ident | ident[::]<args> | ident[::](args) [-> type]` | ||
2270 | /// | ||
2271 | /// # Examples | ||
2272 | /// `a::b::C<D>` (without disambiguator) | ||
2273 | /// `a::b::C::<D>` (with disambiguator) | ||
2274 | /// `Fn(Args)` (without disambiguator) | ||
2275 | /// `Fn::(Args)` (with disambiguator) | ||
2276 | pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { | ||
2277 | self.parse_path_common(style, true) | ||
2278 | } | ||
2279 | |||
2280 | crate fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool) | ||
2281 | -> PResult<'a, ast::Path> { | ||
2282 | maybe_whole!(self, NtPath, |path| { | ||
2283 | if style == PathStyle::Mod && | ||
2284 | path.segments.iter().any(|segment| segment.args.is_some()) { | ||
2285 | self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); | ||
2286 | } | ||
2287 | path | ||
2288 | }); | ||
2289 | |||
2290 | let lo = self.meta_var_span.unwrap_or(self.span); | ||
2291 | let mut segments = Vec::new(); | ||
2292 | let mod_sep_ctxt = self.span.ctxt(); | ||
2293 | if self.eat(&token::ModSep) { | ||
2294 | segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); | ||
2295 | } | ||
2296 | self.parse_path_segments(&mut segments, style, enable_warning)?; | ||
2297 | |||
2298 | Ok(ast::Path { segments, span: lo.to(self.prev_span) }) | ||
2299 | } | ||
2300 | |||
2301 | /// Like `parse_path`, but also supports parsing `Word` meta items into paths for | ||
2302 | /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]` | ||
2303 | /// attributes. | ||
2304 | pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { | ||
2305 | let meta_ident = match self.token { | ||
2306 | token::Interpolated(ref nt) => match **nt { | ||
2307 | token::NtMeta(ref meta) => match meta.node { | ||
2308 | ast::MetaItemKind::Word => Some(meta.ident.clone()), | ||
2309 | _ => None, | ||
2310 | }, | ||
2311 | _ => None, | ||
2312 | }, | ||
2313 | _ => None, | ||
2314 | }; | ||
2315 | if let Some(path) = meta_ident { | ||
2316 | self.bump(); | ||
2317 | return Ok(path); | ||
2318 | } | ||
2319 | self.parse_path(style) | ||
2320 | } | ||
2321 | |||
2322 | fn parse_path_segments(&mut self, | ||
2323 | segments: &mut Vec<PathSegment>, | ||
2324 | style: PathStyle, | ||
2325 | enable_warning: bool) | ||
2326 | -> PResult<'a, ()> { | ||
2327 | loop { | ||
2328 | let segment = self.parse_path_segment(style, enable_warning)?; | ||
2329 | if style == PathStyle::Expr { | ||
2330 | // In order to check for trailing angle brackets, we must have finished | ||
2331 | // recursing (`parse_path_segment` can indirectly call this function), | ||
2332 | // that is, the next token must be the highlighted part of the below example: | ||
2333 | // | ||
2334 | // `Foo::<Bar as Baz<T>>::Qux` | ||
2335 | // ^ here | ||
2336 | // | ||
2337 | // As opposed to the below highlight (if we had only finished the first | ||
2338 | // recursion): | ||
2339 | // | ||
2340 | // `Foo::<Bar as Baz<T>>::Qux` | ||
2341 | // ^ here | ||
2342 | // | ||
2343 | // `PathStyle::Expr` is only provided at the root invocation and never in | ||
2344 | // `parse_path_segment` to recurse and therefore can be checked to maintain | ||
2345 | // this invariant. | ||
2346 | self.check_trailing_angle_brackets(&segment, token::ModSep); | ||
2347 | } | ||
2348 | segments.push(segment); | ||
2349 | |||
2350 | if self.is_import_coupler() || !self.eat(&token::ModSep) { | ||
2351 | return Ok(()); | ||
2352 | } | ||
2353 | } | ||
2354 | } | ||
2355 | |||
2356 | fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool) | ||
2357 | -> PResult<'a, PathSegment> { | ||
2358 | let ident = self.parse_path_segment_ident()?; | ||
2359 | |||
2360 | let is_args_start = |token: &token::Token| match *token { | ||
2361 | token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true, | ||
2362 | _ => false, | ||
2363 | }; | ||
2364 | let check_args_start = |this: &mut Self| { | ||
2365 | this.expected_tokens.extend_from_slice( | ||
2366 | &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))] | ||
2367 | ); | ||
2368 | is_args_start(&this.token) | ||
2369 | }; | ||
2370 | |||
2371 | Ok(if style == PathStyle::Type && check_args_start(self) || | ||
2372 | style != PathStyle::Mod && self.check(&token::ModSep) | ||
2373 | && self.look_ahead(1, |t| is_args_start(t)) { | ||
2374 | // Generic arguments are found - `<`, `(`, `::<` or `::(`. | ||
2375 | if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning { | ||
2376 | self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator") | ||
2377 | .span_label(self.prev_span, "try removing `::`").emit(); | ||
2378 | } | ||
2379 | let lo = self.span; | ||
2380 | |||
2381 | // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If | ||
2382 | // it isn't, then we reset the unmatched angle bracket count as we're about to start | ||
2383 | // parsing a new path. | ||
2384 | if style == PathStyle::Expr { | ||
2385 | self.unmatched_angle_bracket_count = 0; | ||
2386 | self.max_angle_bracket_count = 0; | ||
2387 | } | ||
2388 | |||
2389 | let args = if self.eat_lt() { | ||
2390 | // `<'a, T, A = U>` | ||
2391 | let (args, bindings) = | ||
2392 | self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?; | ||
2393 | self.expect_gt()?; | ||
2394 | let span = lo.to(self.prev_span); | ||
2395 | AngleBracketedArgs { args, bindings, span }.into() | ||
2396 | } else { | ||
2397 | // `(T, U) -> R` | ||
2398 | self.bump(); // `(` | ||
2399 | let (inputs, recovered) = self.parse_seq_to_before_tokens( | ||
2400 | &[&token::CloseDelim(token::Paren)], | ||
2401 | SeqSep::trailing_allowed(token::Comma), | ||
2402 | TokenExpectType::Expect, | ||
2403 | |p| p.parse_ty())?; | ||
2404 | if !recovered { | ||
2405 | self.bump(); // `)` | ||
2406 | } | ||
2407 | let span = lo.to(self.prev_span); | ||
2408 | let output = if self.eat(&token::RArrow) { | ||
2409 | Some(self.parse_ty_common(false, false)?) | ||
2410 | } else { | ||
2411 | None | ||
2412 | }; | ||
2413 | ParenthesizedArgs { inputs, output, span }.into() | ||
2414 | }; | ||
2415 | |||
2416 | PathSegment { ident, args, id: ast::DUMMY_NODE_ID } | ||
2417 | } else { | ||
2418 | // Generic arguments are not found. | ||
2419 | PathSegment::from_ident(ident) | ||
2420 | }) | ||
2421 | } | ||
2422 | |||
2423 | crate fn check_lifetime(&mut self) -> bool { | ||
2424 | self.expected_tokens.push(TokenType::Lifetime); | ||
2425 | self.token.is_lifetime() | ||
2426 | } | ||
2427 | |||
2428 | /// Parses a single lifetime `'a` or panics. | ||
2429 | crate fn expect_lifetime(&mut self) -> Lifetime { | ||
2430 | if let Some(ident) = self.token.lifetime() { | ||
2431 | let span = self.span; | ||
2432 | self.bump(); | ||
2433 | Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID } | ||
2434 | } else { | ||
2435 | self.span_bug(self.span, "not a lifetime") | ||
2436 | } | ||
2437 | } | ||
2438 | |||
2439 | fn eat_label(&mut self) -> Option<Label> { | ||
2440 | if let Some(ident) = self.token.lifetime() { | ||
2441 | let span = self.span; | ||
2442 | self.bump(); | ||
2443 | Some(Label { ident: Ident::new(ident.name, span) }) | ||
2444 | } else { | ||
2445 | None | ||
2446 | } | ||
2447 | } | ||
2448 | |||
2449 | /// Parses mutability (`mut` or nothing). | ||
2450 | fn parse_mutability(&mut self) -> Mutability { | ||
2451 | if self.eat_keyword(keywords::Mut) { | ||
2452 | Mutability::Mutable | ||
2453 | } else { | ||
2454 | Mutability::Immutable | ||
2455 | } | ||
2456 | } | ||
2457 | |||
2458 | fn parse_field_name(&mut self) -> PResult<'a, Ident> { | ||
2459 | if let token::Literal(token::Integer(name), None) = self.token { | ||
2460 | self.bump(); | ||
2461 | Ok(Ident::new(name, self.prev_span)) | ||
2462 | } else { | ||
2463 | self.parse_ident_common(false) | ||
2464 | } | ||
2465 | } | ||
2466 | |||
2467 | /// Parse ident (COLON expr)? | ||
2468 | fn parse_field(&mut self) -> PResult<'a, Field> { | ||
2469 | let attrs = self.parse_outer_attributes()?; | ||
2470 | let lo = self.span; | ||
2471 | |||
2472 | // Check if a colon exists one ahead. This means we're parsing a fieldname. | ||
2473 | let (fieldname, expr, is_shorthand) = if self.look_ahead(1, |t| { | ||
2474 | t == &token::Colon || t == &token::Eq | ||
2475 | }) { | ||
2476 | let fieldname = self.parse_field_name()?; | ||
2477 | |||
2478 | // Check for an equals token. This means the source incorrectly attempts to | ||
2479 | // initialize a field with an eq rather than a colon. | ||
2480 | if self.token == token::Eq { | ||
2481 | self.diagnostic() | ||
2482 | .struct_span_err(self.span, "expected `:`, found `=`") | ||
2483 | .span_suggestion( | ||
2484 | fieldname.span.shrink_to_hi().to(self.span), | ||
2485 | "replace equals symbol with a colon", | ||
2486 | ":".to_string(), | ||
2487 | Applicability::MachineApplicable, | ||
2488 | ) | ||
2489 | .emit(); | ||
2490 | } | ||
2491 | self.bump(); // `:` | ||
2492 | (fieldname, self.parse_expr()?, false) | ||
2493 | } else { | ||
2494 | let fieldname = self.parse_ident_common(false)?; | ||
2495 | |||
2496 | // Mimic `x: x` for the `x` field shorthand. | ||
2497 | let path = ast::Path::from_ident(fieldname); | ||
2498 | let expr = self.mk_expr(fieldname.span, ExprKind::Path(None, path), ThinVec::new()); | ||
2499 | (fieldname, expr, true) | ||
2500 | }; | ||
2501 | Ok(ast::Field { | ||
2502 | ident: fieldname, | ||
2503 | span: lo.to(expr.span), | ||
2504 | expr, | ||
2505 | is_shorthand, | ||
2506 | attrs: attrs.into(), | ||
2507 | }) | ||
2508 | } | ||
2509 | |||
2510 | fn mk_expr(&mut self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> { | ||
2511 | P(Expr { node, span, attrs, id: ast::DUMMY_NODE_ID }) | ||
2512 | } | ||
2513 | |||
2514 | fn mk_unary(&mut self, unop: ast::UnOp, expr: P<Expr>) -> ast::ExprKind { | ||
2515 | ExprKind::Unary(unop, expr) | ||
2516 | } | ||
2517 | |||
2518 | fn mk_binary(&mut self, binop: ast::BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind { | ||
2519 | ExprKind::Binary(binop, lhs, rhs) | ||
2520 | } | ||
2521 | |||
2522 | fn mk_call(&mut self, f: P<Expr>, args: Vec<P<Expr>>) -> ast::ExprKind { | ||
2523 | ExprKind::Call(f, args) | ||
2524 | } | ||
2525 | |||
2526 | fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind { | ||
2527 | ExprKind::Index(expr, idx) | ||
2528 | } | ||
2529 | |||
2530 | fn mk_range(&mut self, | ||
2531 | start: Option<P<Expr>>, | ||
2532 | end: Option<P<Expr>>, | ||
2533 | limits: RangeLimits) | ||
2534 | -> PResult<'a, ast::ExprKind> { | ||
2535 | if end.is_none() && limits == RangeLimits::Closed { | ||
2536 | Err(self.span_fatal_err(self.span, Error::InclusiveRangeWithNoEnd)) | ||
2537 | } else { | ||
2538 | Ok(ExprKind::Range(start, end, limits)) | ||
2539 | } | ||
2540 | } | ||
2541 | |||
2542 | fn mk_assign_op(&mut self, binop: ast::BinOp, | ||
2543 | lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind { | ||
2544 | ExprKind::AssignOp(binop, lhs, rhs) | ||
2545 | } | ||
2546 | |||
2547 | pub fn mk_mac_expr(&mut self, span: Span, m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> { | ||
2548 | P(Expr { | ||
2549 | id: ast::DUMMY_NODE_ID, | ||
2550 | node: ExprKind::Mac(source_map::Spanned {node: m, span: span}), | ||
2551 | span, | ||
2552 | attrs, | ||
2553 | }) | ||
2554 | } | ||
2555 | |||
2556 | fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> { | ||
2557 | let delim = match self.token { | ||
2558 | token::OpenDelim(delim) => delim, | ||
2559 | _ => { | ||
2560 | let msg = "expected open delimiter"; | ||
2561 | let mut err = self.fatal(msg); | ||
2562 | err.span_label(self.span, msg); | ||
2563 | return Err(err) | ||
2564 | } | ||
2565 | }; | ||
2566 | let tts = match self.parse_token_tree() { | ||
2567 | TokenTree::Delimited(_, _, tts) => tts, | ||
2568 | _ => unreachable!(), | ||
2569 | }; | ||
2570 | let delim = match delim { | ||
2571 | token::Paren => MacDelimiter::Parenthesis, | ||
2572 | token::Bracket => MacDelimiter::Bracket, | ||
2573 | token::Brace => MacDelimiter::Brace, | ||
2574 | token::NoDelim => self.bug("unexpected no delimiter"), | ||
2575 | }; | ||
2576 | Ok((delim, tts.into())) | ||
2577 | } | ||
2578 | |||
2579 | /// At the bottom (top?) of the precedence hierarchy, | ||
2580 | /// Parses things like parenthesized exprs, macros, `return`, etc. | ||
2581 | /// | ||
2582 | /// N.B., this does not parse outer attributes, and is private because it only works | ||
2583 | /// correctly if called from `parse_dot_or_call_expr()`. | ||
2584 | fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> { | ||
2585 | maybe_whole_expr!(self); | ||
2586 | |||
2587 | // Outer attributes are already parsed and will be | ||
2588 | // added to the return value after the fact. | ||
2589 | // | ||
2590 | // Therefore, prevent sub-parser from parsing | ||
2591 | // attributes by giving them a empty "already parsed" list. | ||
2592 | let mut attrs = ThinVec::new(); | ||
2593 | |||
2594 | let lo = self.span; | ||
2595 | let mut hi = self.span; | ||
2596 | |||
2597 | let ex: ExprKind; | ||
2598 | |||
2599 | // Note: when adding new syntax here, don't forget to adjust Token::can_begin_expr(). | ||
2600 | match self.token { | ||
2601 | token::OpenDelim(token::Paren) => { | ||
2602 | self.bump(); | ||
2603 | |||
2604 | attrs.extend(self.parse_inner_attributes()?); | ||
2605 | |||
2606 | // (e) is parenthesized e | ||
2607 | // (e,) is a tuple with only one field, e | ||
2608 | let mut es = vec![]; | ||
2609 | let mut trailing_comma = false; | ||
2610 | let mut recovered = false; | ||
2611 | while self.token != token::CloseDelim(token::Paren) { | ||
2612 | es.push(self.parse_expr()?); | ||
2613 | recovered = self.expect_one_of( | ||
2614 | &[], | ||
2615 | &[token::Comma, token::CloseDelim(token::Paren)], | ||
2616 | )?; | ||
2617 | if self.eat(&token::Comma) { | ||
2618 | trailing_comma = true; | ||
2619 | } else { | ||
2620 | trailing_comma = false; | ||
2621 | break; | ||
2622 | } | ||
2623 | } | ||
2624 | if !recovered { | ||
2625 | self.bump(); | ||
2626 | } | ||
2627 | |||
2628 | hi = self.prev_span; | ||
2629 | ex = if es.len() == 1 && !trailing_comma { | ||
2630 | ExprKind::Paren(es.into_iter().nth(0).unwrap()) | ||
2631 | } else { | ||
2632 | ExprKind::Tup(es) | ||
2633 | }; | ||
2634 | } | ||
2635 | token::OpenDelim(token::Brace) => { | ||
2636 | return self.parse_block_expr(None, lo, BlockCheckMode::Default, attrs); | ||
2637 | } | ||
2638 | token::BinOp(token::Or) | token::OrOr => { | ||
2639 | return self.parse_lambda_expr(attrs); | ||
2640 | } | ||
2641 | token::OpenDelim(token::Bracket) => { | ||
2642 | self.bump(); | ||
2643 | |||
2644 | attrs.extend(self.parse_inner_attributes()?); | ||
2645 | |||
2646 | if self.eat(&token::CloseDelim(token::Bracket)) { | ||
2647 | // Empty vector. | ||
2648 | ex = ExprKind::Array(Vec::new()); | ||
2649 | } else { | ||
2650 | // Nonempty vector. | ||
2651 | let first_expr = self.parse_expr()?; | ||
2652 | if self.eat(&token::Semi) { | ||
2653 | // Repeating array syntax: [ 0; 512 ] | ||
2654 | let count = AnonConst { | ||
2655 | id: ast::DUMMY_NODE_ID, | ||
2656 | value: self.parse_expr()?, | ||
2657 | }; | ||
2658 | self.expect(&token::CloseDelim(token::Bracket))?; | ||
2659 | ex = ExprKind::Repeat(first_expr, count); | ||
2660 | } else if self.eat(&token::Comma) { | ||
2661 | // Vector with two or more elements. | ||
2662 | let remaining_exprs = self.parse_seq_to_end( | ||
2663 | &token::CloseDelim(token::Bracket), | ||
2664 | SeqSep::trailing_allowed(token::Comma), | ||
2665 | |p| Ok(p.parse_expr()?) | ||
2666 | )?; | ||
2667 | let mut exprs = vec![first_expr]; | ||
2668 | exprs.extend(remaining_exprs); | ||
2669 | ex = ExprKind::Array(exprs); | ||
2670 | } else { | ||
2671 | // Vector with one element. | ||
2672 | self.expect(&token::CloseDelim(token::Bracket))?; | ||
2673 | ex = ExprKind::Array(vec![first_expr]); | ||
2674 | } | ||
2675 | } | ||
2676 | hi = self.prev_span; | ||
2677 | } | ||
2678 | _ => { | ||
2679 | if self.eat_lt() { | ||
2680 | let (qself, path) = self.parse_qpath(PathStyle::Expr)?; | ||
2681 | hi = path.span; | ||
2682 | return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); | ||
2683 | } | ||
2684 | if self.span.rust_2018() && self.check_keyword(keywords::Async) | ||
2685 | { | ||
2686 | if self.is_async_block() { // check for `async {` and `async move {` | ||
2687 | return self.parse_async_block(attrs); | ||
2688 | } else { | ||
2689 | return self.parse_lambda_expr(attrs); | ||
2690 | } | ||
2691 | } | ||
2692 | if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) { | ||
2693 | return self.parse_lambda_expr(attrs); | ||
2694 | } | ||
2695 | if self.eat_keyword(keywords::If) { | ||
2696 | return self.parse_if_expr(attrs); | ||
2697 | } | ||
2698 | if self.eat_keyword(keywords::For) { | ||
2699 | let lo = self.prev_span; | ||
2700 | return self.parse_for_expr(None, lo, attrs); | ||
2701 | } | ||
2702 | if self.eat_keyword(keywords::While) { | ||
2703 | let lo = self.prev_span; | ||
2704 | return self.parse_while_expr(None, lo, attrs); | ||
2705 | } | ||
2706 | if let Some(label) = self.eat_label() { | ||
2707 | let lo = label.ident.span; | ||
2708 | self.expect(&token::Colon)?; | ||
2709 | if self.eat_keyword(keywords::While) { | ||
2710 | return self.parse_while_expr(Some(label), lo, attrs) | ||
2711 | } | ||
2712 | if self.eat_keyword(keywords::For) { | ||
2713 | return self.parse_for_expr(Some(label), lo, attrs) | ||
2714 | } | ||
2715 | if self.eat_keyword(keywords::Loop) { | ||
2716 | return self.parse_loop_expr(Some(label), lo, attrs) | ||
2717 | } | ||
2718 | if self.token == token::OpenDelim(token::Brace) { | ||
2719 | return self.parse_block_expr(Some(label), | ||
2720 | lo, | ||
2721 | BlockCheckMode::Default, | ||
2722 | attrs); | ||
2723 | } | ||
2724 | let msg = "expected `while`, `for`, `loop` or `{` after a label"; | ||
2725 | let mut err = self.fatal(msg); | ||
2726 | err.span_label(self.span, msg); | ||
2727 | return Err(err); | ||
2728 | } | ||
2729 | if self.eat_keyword(keywords::Loop) { | ||
2730 | let lo = self.prev_span; | ||
2731 | return self.parse_loop_expr(None, lo, attrs); | ||
2732 | } | ||
2733 | if self.eat_keyword(keywords::Continue) { | ||
2734 | let label = self.eat_label(); | ||
2735 | let ex = ExprKind::Continue(label); | ||
2736 | let hi = self.prev_span; | ||
2737 | return Ok(self.mk_expr(lo.to(hi), ex, attrs)); | ||
2738 | } | ||
2739 | if self.eat_keyword(keywords::Match) { | ||
2740 | let match_sp = self.prev_span; | ||
2741 | return self.parse_match_expr(attrs).map_err(|mut err| { | ||
2742 | err.span_label(match_sp, "while parsing this match expression"); | ||
2743 | err | ||
2744 | }); | ||
2745 | } | ||
2746 | if self.eat_keyword(keywords::Unsafe) { | ||
2747 | return self.parse_block_expr( | ||
2748 | None, | ||
2749 | lo, | ||
2750 | BlockCheckMode::Unsafe(ast::UserProvided), | ||
2751 | attrs); | ||
2752 | } | ||
2753 | if self.is_do_catch_block() { | ||
2754 | let mut db = self.fatal("found removed `do catch` syntax"); | ||
2755 | db.help("Following RFC #2388, the new non-placeholder syntax is `try`"); | ||
2756 | return Err(db); | ||
2757 | } | ||
2758 | if self.is_try_block() { | ||
2759 | let lo = self.span; | ||
2760 | assert!(self.eat_keyword(keywords::Try)); | ||
2761 | return self.parse_try_block(lo, attrs); | ||
2762 | } | ||
2763 | if self.eat_keyword(keywords::Return) { | ||
2764 | if self.token.can_begin_expr() { | ||
2765 | let e = self.parse_expr()?; | ||
2766 | hi = e.span; | ||
2767 | ex = ExprKind::Ret(Some(e)); | ||
2768 | } else { | ||
2769 | ex = ExprKind::Ret(None); | ||
2770 | } | ||
2771 | } else if self.eat_keyword(keywords::Break) { | ||
2772 | let label = self.eat_label(); | ||
2773 | let e = if self.token.can_begin_expr() | ||
2774 | && !(self.token == token::OpenDelim(token::Brace) | ||
2775 | && self.restrictions.contains( | ||
2776 | Restrictions::NO_STRUCT_LITERAL)) { | ||
2777 | Some(self.parse_expr()?) | ||
2778 | } else { | ||
2779 | None | ||
2780 | }; | ||
2781 | ex = ExprKind::Break(label, e); | ||
2782 | hi = self.prev_span; | ||
2783 | } else if self.eat_keyword(keywords::Yield) { | ||
2784 | if self.token.can_begin_expr() { | ||
2785 | let e = self.parse_expr()?; | ||
2786 | hi = e.span; | ||
2787 | ex = ExprKind::Yield(Some(e)); | ||
2788 | } else { | ||
2789 | ex = ExprKind::Yield(None); | ||
2790 | } | ||
2791 | } else if self.token.is_keyword(keywords::Let) { | ||
2792 | // Catch this syntax error here, instead of in `parse_ident`, so | ||
2793 | // that we can explicitly mention that let is not to be used as an expression | ||
2794 | let mut db = self.fatal("expected expression, found statement (`let`)"); | ||
2795 | db.span_label(self.span, "expected expression"); | ||
2796 | db.note("variable declaration using `let` is a statement"); | ||
2797 | return Err(db); | ||
2798 | } else if self.token.is_path_start() { | ||
2799 | let pth = self.parse_path(PathStyle::Expr)?; | ||
2800 | |||
2801 | // `!`, as an operator, is prefix, so we know this isn't that | ||
2802 | if self.eat(&token::Not) { | ||
2803 | // MACRO INVOCATION expression | ||
2804 | let (delim, tts) = self.expect_delimited_token_tree()?; | ||
2805 | let hi = self.prev_span; | ||
2806 | let node = Mac_ { path: pth, tts, delim }; | ||
2807 | return Ok(self.mk_mac_expr(lo.to(hi), node, attrs)) | ||
2808 | } | ||
2809 | if self.check(&token::OpenDelim(token::Brace)) { | ||
2810 | // This is a struct literal, unless we're prohibited | ||
2811 | // from parsing struct literals here. | ||
2812 | let prohibited = self.restrictions.contains( | ||
2813 | Restrictions::NO_STRUCT_LITERAL | ||
2814 | ); | ||
2815 | if !prohibited { | ||
2816 | return self.parse_struct_expr(lo, pth, attrs); | ||
2817 | } | ||
2818 | } | ||
2819 | |||
2820 | hi = pth.span; | ||
2821 | ex = ExprKind::Path(None, pth); | ||
2822 | } else { | ||
2823 | if !self.unclosed_delims.is_empty() && self.check(&token::Semi) { | ||
2824 | // Don't complain about bare semicolons after unclosed braces | ||
2825 | // recovery in order to keep the error count down. Fixing the | ||
2826 | // delimiters will possibly also fix the bare semicolon found in | ||
2827 | // expression context. For example, silence the following error: | ||
2828 | // ``` | ||
2829 | // error: expected expression, found `;` | ||
2830 | // --> file.rs:2:13 | ||
2831 | // | | ||
2832 | // 2 | foo(bar(; | ||
2833 | // | ^ expected expression | ||
2834 | // ``` | ||
2835 | self.bump(); | ||
2836 | return Ok(self.mk_expr(self.span, ExprKind::Err, ThinVec::new())); | ||
2837 | } | ||
2838 | match self.parse_literal_maybe_minus() { | ||
2839 | Ok(expr) => { | ||
2840 | hi = expr.span; | ||
2841 | ex = expr.node.clone(); | ||
2842 | } | ||
2843 | Err(mut err) => { | ||
2844 | self.cancel(&mut err); | ||
2845 | let msg = format!("expected expression, found {}", | ||
2846 | self.this_token_descr()); | ||
2847 | let mut err = self.fatal(&msg); | ||
2848 | err.span_label(self.span, "expected expression"); | ||
2849 | return Err(err); | ||
2850 | } | ||
2851 | } | ||
2852 | } | ||
2853 | } | ||
2854 | } | ||
2855 | |||
2856 | let expr = Expr { node: ex, span: lo.to(hi), id: ast::DUMMY_NODE_ID, attrs }; | ||
2857 | let expr = self.maybe_recover_from_bad_qpath(expr, true)?; | ||
2858 | |||
2859 | return Ok(P(expr)); | ||
2860 | } | ||
2861 | |||
2862 | fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Attribute>) | ||
2863 | -> PResult<'a, P<Expr>> { | ||
2864 | let struct_sp = lo.to(self.prev_span); | ||
2865 | self.bump(); | ||
2866 | let mut fields = Vec::new(); | ||
2867 | let mut base = None; | ||
2868 | |||
2869 | attrs.extend(self.parse_inner_attributes()?); | ||
2870 | |||
2871 | while self.token != token::CloseDelim(token::Brace) { | ||
2872 | if self.eat(&token::DotDot) { | ||
2873 | let exp_span = self.prev_span; | ||
2874 | match self.parse_expr() { | ||
2875 | Ok(e) => { | ||
2876 | base = Some(e); | ||
2877 | } | ||
2878 | Err(mut e) => { | ||
2879 | e.emit(); | ||
2880 | self.recover_stmt(); | ||
2881 | } | ||
2882 | } | ||
2883 | if self.token == token::Comma { | ||
2884 | let mut err = self.sess.span_diagnostic.mut_span_err( | ||
2885 | exp_span.to(self.prev_span), | ||
2886 | "cannot use a comma after the base struct", | ||
2887 | ); | ||
2888 | err.span_suggestion_short( | ||
2889 | self.span, | ||
2890 | "remove this comma", | ||
2891 | String::new(), | ||
2892 | Applicability::MachineApplicable | ||
2893 | ); | ||
2894 | err.note("the base struct must always be the last field"); | ||
2895 | err.emit(); | ||
2896 | self.recover_stmt(); | ||
2897 | } | ||
2898 | break; | ||
2899 | } | ||
2900 | |||
2901 | let mut recovery_field = None; | ||
2902 | if let token::Ident(ident, _) = self.token { | ||
2903 | if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) { | ||
2904 | // Use in case of error after field-looking code: `S { foo: () with a }` | ||
2905 | let mut ident = ident.clone(); | ||
2906 | ident.span = self.span; | ||
2907 | recovery_field = Some(ast::Field { | ||
2908 | ident, | ||
2909 | span: self.span, | ||
2910 | expr: self.mk_expr(self.span, ExprKind::Err, ThinVec::new()), | ||
2911 | is_shorthand: false, | ||
2912 | attrs: ThinVec::new(), | ||
2913 | }); | ||
2914 | } | ||
2915 | } | ||
2916 | let mut parsed_field = None; | ||
2917 | match self.parse_field() { | ||
2918 | Ok(f) => parsed_field = Some(f), | ||
2919 | Err(mut e) => { | ||
2920 | e.span_label(struct_sp, "while parsing this struct"); | ||
2921 | e.emit(); | ||
2922 | |||
2923 | // If the next token is a comma, then try to parse | ||
2924 | // what comes next as additional fields, rather than | ||
2925 | // bailing out until next `}`. | ||
2926 | if self.token != token::Comma { | ||
2927 | self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore); | ||
2928 | if self.token != token::Comma { | ||
2929 | break; | ||
2930 | } | ||
2931 | } | ||
2932 | } | ||
2933 | } | ||
2934 | |||
2935 | match self.expect_one_of(&[token::Comma], | ||
2936 | &[token::CloseDelim(token::Brace)]) { | ||
2937 | Ok(_) => if let Some(f) = parsed_field.or(recovery_field) { | ||
2938 | // only include the field if there's no parse error for the field name | ||
2939 | fields.push(f); | ||
2940 | } | ||
2941 | Err(mut e) => { | ||
2942 | if let Some(f) = recovery_field { | ||
2943 | fields.push(f); | ||
2944 | } | ||
2945 | e.span_label(struct_sp, "while parsing this struct"); | ||
2946 | e.emit(); | ||
2947 | self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore); | ||
2948 | self.eat(&token::Comma); | ||
2949 | } | ||
2950 | } | ||
2951 | } | ||
2952 | |||
2953 | let span = lo.to(self.span); | ||
2954 | self.expect(&token::CloseDelim(token::Brace))?; | ||
2955 | return Ok(self.mk_expr(span, ExprKind::Struct(pth, fields, base), attrs)); | ||
2956 | } | ||
2957 | |||
2958 | fn parse_or_use_outer_attributes(&mut self, | ||
2959 | already_parsed_attrs: Option<ThinVec<Attribute>>) | ||
2960 | -> PResult<'a, ThinVec<Attribute>> { | ||
2961 | if let Some(attrs) = already_parsed_attrs { | ||
2962 | Ok(attrs) | ||
2963 | } else { | ||
2964 | self.parse_outer_attributes().map(|a| a.into()) | ||
2965 | } | ||
2966 | } | ||
2967 | |||
2968 | /// Parses a block or unsafe block. | ||
2969 | fn parse_block_expr(&mut self, opt_label: Option<Label>, | ||
2970 | lo: Span, blk_mode: BlockCheckMode, | ||
2971 | outer_attrs: ThinVec<Attribute>) | ||
2972 | -> PResult<'a, P<Expr>> { | ||
2973 | self.expect(&token::OpenDelim(token::Brace))?; | ||
2974 | |||
2975 | let mut attrs = outer_attrs; | ||
2976 | attrs.extend(self.parse_inner_attributes()?); | ||
2977 | |||
2978 | let blk = self.parse_block_tail(lo, blk_mode)?; | ||
2979 | return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, opt_label), attrs)); | ||
2980 | } | ||
2981 | |||
2982 | /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. | ||
2983 | fn parse_dot_or_call_expr(&mut self, | ||
2984 | already_parsed_attrs: Option<ThinVec<Attribute>>) | ||
2985 | -> PResult<'a, P<Expr>> { | ||
2986 | let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; | ||
2987 | |||
2988 | let b = self.parse_bottom_expr(); | ||
2989 | let (span, b) = self.interpolated_or_expr_span(b)?; | ||
2990 | self.parse_dot_or_call_expr_with(b, span, attrs) | ||
2991 | } | ||
2992 | |||
2993 | fn parse_dot_or_call_expr_with(&mut self, | ||
2994 | e0: P<Expr>, | ||
2995 | lo: Span, | ||
2996 | mut attrs: ThinVec<Attribute>) | ||
2997 | -> PResult<'a, P<Expr>> { | ||
2998 | // Stitch the list of outer attributes onto the return value. | ||
2999 | // A little bit ugly, but the best way given the current code | ||
3000 | // structure | ||
3001 | self.parse_dot_or_call_expr_with_(e0, lo) | ||
3002 | .map(|expr| | ||
3003 | expr.map(|mut expr| { | ||
3004 | attrs.extend::<Vec<_>>(expr.attrs.into()); | ||
3005 | expr.attrs = attrs; | ||
3006 | match expr.node { | ||
3007 | ExprKind::If(..) | ExprKind::IfLet(..) => { | ||
3008 | if !expr.attrs.is_empty() { | ||
3009 | // Just point to the first attribute in there... | ||
3010 | let span = expr.attrs[0].span; | ||
3011 | |||
3012 | self.span_err(span, | ||
3013 | "attributes are not yet allowed on `if` \ | ||
3014 | expressions"); | ||
3015 | } | ||
3016 | } | ||
3017 | _ => {} | ||
3018 | } | ||
3019 | expr | ||
3020 | }) | ||
3021 | ) | ||
3022 | } | ||
3023 | |||
3024 | // Assuming we have just parsed `.`, continue parsing into an expression. | ||
3025 | fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { | ||
3026 | let segment = self.parse_path_segment(PathStyle::Expr, true)?; | ||
3027 | self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren)); | ||
3028 | |||
3029 | Ok(match self.token { | ||
3030 | token::OpenDelim(token::Paren) => { | ||
3031 | // Method call `expr.f()` | ||
3032 | let mut args = self.parse_unspanned_seq( | ||
3033 | &token::OpenDelim(token::Paren), | ||
3034 | &token::CloseDelim(token::Paren), | ||
3035 | SeqSep::trailing_allowed(token::Comma), | ||
3036 | |p| Ok(p.parse_expr()?) | ||
3037 | )?; | ||
3038 | args.insert(0, self_arg); | ||
3039 | |||
3040 | let span = lo.to(self.prev_span); | ||
3041 | self.mk_expr(span, ExprKind::MethodCall(segment, args), ThinVec::new()) | ||
3042 | } | ||
3043 | _ => { | ||
3044 | // Field access `expr.f` | ||
3045 | if let Some(args) = segment.args { | ||
3046 | self.span_err(args.span(), | ||
3047 | "field expressions may not have generic arguments"); | ||
3048 | } | ||
3049 | |||
3050 | let span = lo.to(self.prev_span); | ||
3051 | self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), ThinVec::new()) | ||
3052 | } | ||
3053 | }) | ||
3054 | } | ||
3055 | |||
3056 | /// This function checks if there are trailing angle brackets and produces | ||
3057 | /// a diagnostic to suggest removing them. | ||
3058 | /// | ||
3059 | /// ```ignore (diagnostic) | ||
3060 | /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>(); | ||
3061 | /// ^^ help: remove extra angle brackets | ||
3062 | /// ``` | ||
3063 | fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: token::Token) { | ||
3064 | // This function is intended to be invoked after parsing a path segment where there are two | ||
3065 | // cases: | ||
3066 | // | ||
3067 | // 1. A specific token is expected after the path segment. | ||
3068 | // eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call), | ||
3069 | // `Foo::`, or `Foo::<Bar>::` (mod sep - continued path). | ||
3070 | // 2. No specific token is expected after the path segment. | ||
3071 | // eg. `x.foo` (field access) | ||
3072 | // | ||
3073 | // This function is called after parsing `.foo` and before parsing the token `end` (if | ||
3074 | // present). This includes any angle bracket arguments, such as `.foo::<u32>` or | ||
3075 | // `Foo::<Bar>`. | ||
3076 | |||
3077 | // We only care about trailing angle brackets if we previously parsed angle bracket | ||
3078 | // arguments. This helps stop us incorrectly suggesting that extra angle brackets be | ||
3079 | // removed in this case: | ||
3080 | // | ||
3081 | // `x.foo >> (3)` (where `x.foo` is a `u32` for example) | ||
3082 | // | ||
3083 | // This case is particularly tricky as we won't notice it just looking at the tokens - | ||
3084 | // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will | ||
3085 | // have already been parsed): | ||
3086 | // | ||
3087 | // `x.foo::<u32>>>(3)` | ||
3088 | let parsed_angle_bracket_args = segment.args | ||
3089 | .as_ref() | ||
3090 | .map(|args| args.is_angle_bracketed()) | ||
3091 | .unwrap_or(false); | ||
3092 | |||
3093 | debug!( | ||
3094 | "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}", | ||
3095 | parsed_angle_bracket_args, | ||
3096 | ); | ||
3097 | if !parsed_angle_bracket_args { | ||
3098 | return; | ||
3099 | } | ||
3100 | |||
3101 | // Keep the span at the start so we can highlight the sequence of `>` characters to be | ||
3102 | // removed. | ||
3103 | let lo = self.span; | ||
3104 | |||
3105 | // We need to look-ahead to see if we have `>` characters without moving the cursor forward | ||
3106 | // (since we might have the field access case and the characters we're eating are | ||
3107 | // actual operators and not trailing characters - ie `x.foo >> 3`). | ||
3108 | let mut position = 0; | ||
3109 | |||
3110 | // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how | ||
3111 | // many of each (so we can correctly pluralize our error messages) and continue to | ||
3112 | // advance. | ||
3113 | let mut number_of_shr = 0; | ||
3114 | let mut number_of_gt = 0; | ||
3115 | while self.look_ahead(position, |t| { | ||
3116 | trace!("check_trailing_angle_brackets: t={:?}", t); | ||
3117 | if *t == token::BinOp(token::BinOpToken::Shr) { | ||
3118 | number_of_shr += 1; | ||
3119 | true | ||
3120 | } else if *t == token::Gt { | ||
3121 | number_of_gt += 1; | ||
3122 | true | ||
3123 | } else { | ||
3124 | false | ||
3125 | } | ||
3126 | }) { | ||
3127 | position += 1; | ||
3128 | } | ||
3129 | |||
3130 | // If we didn't find any trailing `>` characters, then we have nothing to error about. | ||
3131 | debug!( | ||
3132 | "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}", | ||
3133 | number_of_gt, number_of_shr, | ||
3134 | ); | ||
3135 | if number_of_gt < 1 && number_of_shr < 1 { | ||
3136 | return; | ||
3137 | } | ||
3138 | |||
3139 | // Finally, double check that we have our end token as otherwise this is the | ||
3140 | // second case. | ||
3141 | if self.look_ahead(position, |t| { | ||
3142 | trace!("check_trailing_angle_brackets: t={:?}", t); | ||
3143 | *t == end | ||
3144 | }) { | ||
3145 | // Eat from where we started until the end token so that parsing can continue | ||
3146 | // as if we didn't have those extra angle brackets. | ||
3147 | self.eat_to_tokens(&[&end]); | ||
3148 | let span = lo.until(self.span); | ||
3149 | |||
3150 | let plural = number_of_gt > 1 || number_of_shr >= 1; | ||
3151 | self.diagnostic() | ||
3152 | .struct_span_err( | ||
3153 | span, | ||
3154 | &format!("unmatched angle bracket{}", if plural { "s" } else { "" }), | ||
3155 | ) | ||
3156 | .span_suggestion( | ||
3157 | span, | ||
3158 | &format!("remove extra angle bracket{}", if plural { "s" } else { "" }), | ||
3159 | String::new(), | ||
3160 | Applicability::MachineApplicable, | ||
3161 | ) | ||
3162 | .emit(); | ||
3163 | } | ||
3164 | } | ||
3165 | |||
3166 | fn parse_dot_or_call_expr_with_(&mut self, e0: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { | ||
3167 | let mut e = e0; | ||
3168 | let mut hi; | ||
3169 | loop { | ||
3170 | // expr? | ||
3171 | while self.eat(&token::Question) { | ||
3172 | let hi = self.prev_span; | ||
3173 | e = self.mk_expr(lo.to(hi), ExprKind::Try(e), ThinVec::new()); | ||
3174 | } | ||
3175 | |||
3176 | // expr.f | ||
3177 | if self.eat(&token::Dot) { | ||
3178 | match self.token { | ||
3179 | token::Ident(..) => { | ||
3180 | e = self.parse_dot_suffix(e, lo)?; | ||
3181 | } | ||
3182 | token::Literal(token::Integer(name), _) => { | ||
3183 | let span = self.span; | ||
3184 | self.bump(); | ||
3185 | let field = ExprKind::Field(e, Ident::new(name, span)); | ||
3186 | e = self.mk_expr(lo.to(span), field, ThinVec::new()); | ||
3187 | } | ||
3188 | token::Literal(token::Float(n), _suf) => { | ||
3189 | self.bump(); | ||
3190 | let fstr = n.as_str(); | ||
3191 | let mut err = self.diagnostic() | ||
3192 | .struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n)); | ||
3193 | err.span_label(self.prev_span, "unexpected token"); | ||
3194 | if fstr.chars().all(|x| "0123456789.".contains(x)) { | ||
3195 | let float = match fstr.parse::<f64>().ok() { | ||
3196 | Some(f) => f, | ||
3197 | None => continue, | ||
3198 | }; | ||
3199 | let sugg = pprust::to_string(|s| { | ||
3200 | use crate::print::pprust::PrintState; | ||
3201 | s.popen()?; | ||
3202 | s.print_expr(&e)?; | ||
3203 | s.s.word( ".")?; | ||
3204 | s.print_usize(float.trunc() as usize)?; | ||
3205 | s.pclose()?; | ||
3206 | s.s.word(".")?; | ||
3207 | s.s.word(fstr.splitn(2, ".").last().unwrap().to_string()) | ||
3208 | }); | ||
3209 | err.span_suggestion( | ||
3210 | lo.to(self.prev_span), | ||
3211 | "try parenthesizing the first index", | ||
3212 | sugg, | ||
3213 | Applicability::MachineApplicable | ||
3214 | ); | ||
3215 | } | ||
3216 | return Err(err); | ||
3217 | |||
3218 | } | ||
3219 | _ => { | ||
3220 | // FIXME Could factor this out into non_fatal_unexpected or something. | ||
3221 | let actual = self.this_token_to_string(); | ||
3222 | self.span_err(self.span, &format!("unexpected token: `{}`", actual)); | ||
3223 | } | ||
3224 | } | ||
3225 | continue; | ||
3226 | } | ||
3227 | if self.expr_is_complete(&e) { break; } | ||
3228 | match self.token { | ||
3229 | // expr(...) | ||
3230 | token::OpenDelim(token::Paren) => { | ||
3231 | let es = self.parse_unspanned_seq( | ||
3232 | &token::OpenDelim(token::Paren), | ||
3233 | &token::CloseDelim(token::Paren), | ||
3234 | SeqSep::trailing_allowed(token::Comma), | ||
3235 | |p| Ok(p.parse_expr()?) | ||
3236 | )?; | ||
3237 | hi = self.prev_span; | ||
3238 | |||
3239 | let nd = self.mk_call(e, es); | ||
3240 | e = self.mk_expr(lo.to(hi), nd, ThinVec::new()); | ||
3241 | } | ||
3242 | |||
3243 | // expr[...] | ||
3244 | // Could be either an index expression or a slicing expression. | ||
3245 | token::OpenDelim(token::Bracket) => { | ||
3246 | self.bump(); | ||
3247 | let ix = self.parse_expr()?; | ||
3248 | hi = self.span; | ||
3249 | self.expect(&token::CloseDelim(token::Bracket))?; | ||
3250 | let index = self.mk_index(e, ix); | ||
3251 | e = self.mk_expr(lo.to(hi), index, ThinVec::new()) | ||
3252 | } | ||
3253 | _ => return Ok(e) | ||
3254 | } | ||
3255 | } | ||
3256 | return Ok(e); | ||
3257 | } | ||
3258 | |||
3259 | crate fn process_potential_macro_variable(&mut self) { | ||
3260 | let (token, span) = match self.token { | ||
3261 | token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() && | ||
3262 | self.look_ahead(1, |t| t.is_ident()) => { | ||
3263 | self.bump(); | ||
3264 | let name = match self.token { | ||
3265 | token::Ident(ident, _) => ident, | ||
3266 | _ => unreachable!() | ||
3267 | }; | ||
3268 | let mut err = self.fatal(&format!("unknown macro variable `{}`", name)); | ||
3269 | err.span_label(self.span, "unknown macro variable"); | ||
3270 | err.emit(); | ||
3271 | self.bump(); | ||
3272 | return | ||
3273 | } | ||
3274 | token::Interpolated(ref nt) => { | ||
3275 | self.meta_var_span = Some(self.span); | ||
3276 | // Interpolated identifier and lifetime tokens are replaced with usual identifier | ||
3277 | // and lifetime tokens, so the former are never encountered during normal parsing. | ||
3278 | match **nt { | ||
3279 | token::NtIdent(ident, is_raw) => (token::Ident(ident, is_raw), ident.span), | ||
3280 | token::NtLifetime(ident) => (token::Lifetime(ident), ident.span), | ||
3281 | _ => return, | ||
3282 | } | ||
3283 | } | ||
3284 | _ => return, | ||
3285 | }; | ||
3286 | self.token = token; | ||
3287 | self.span = span; | ||
3288 | } | ||
3289 | |||
3290 | /// Parses a single token tree from the input. | ||
3291 | crate fn parse_token_tree(&mut self) -> TokenTree { | ||
3292 | match self.token { | ||
3293 | token::OpenDelim(..) => { | ||
3294 | let frame = mem::replace(&mut self.token_cursor.frame, | ||
3295 | self.token_cursor.stack.pop().unwrap()); | ||
3296 | self.span = frame.span.entire(); | ||
3297 | self.bump(); | ||
3298 | TokenTree::Delimited( | ||
3299 | frame.span, | ||
3300 | frame.delim, | ||
3301 | frame.tree_cursor.stream.into(), | ||
3302 | ) | ||
3303 | }, | ||
3304 | token::CloseDelim(_) | token::Eof => unreachable!(), | ||
3305 | _ => { | ||
3306 | let (token, span) = (mem::replace(&mut self.token, token::Whitespace), self.span); | ||
3307 | self.bump(); | ||
3308 | TokenTree::Token(span, token) | ||
3309 | } | ||
3310 | } | ||
3311 | } | ||
3312 | |||
3313 | // parse a stream of tokens into a list of TokenTree's, | ||
3314 | // up to EOF. | ||
3315 | pub fn parse_all_token_trees(&mut self) -> PResult<'a, Vec<TokenTree>> { | ||
3316 | let mut tts = Vec::new(); | ||
3317 | while self.token != token::Eof { | ||
3318 | tts.push(self.parse_token_tree()); | ||
3319 | } | ||
3320 | Ok(tts) | ||
3321 | } | ||
3322 | |||
3323 | pub fn parse_tokens(&mut self) -> TokenStream { | ||
3324 | let mut result = Vec::new(); | ||
3325 | loop { | ||
3326 | match self.token { | ||
3327 | token::Eof | token::CloseDelim(..) => break, | ||
3328 | _ => result.push(self.parse_token_tree().into()), | ||
3329 | } | ||
3330 | } | ||
3331 | TokenStream::new(result) | ||
3332 | } | ||
3333 | |||
3334 | /// Parse a prefix-unary-operator expr | ||
3335 | fn parse_prefix_expr(&mut self, | ||
3336 | already_parsed_attrs: Option<ThinVec<Attribute>>) | ||
3337 | -> PResult<'a, P<Expr>> { | ||
3338 | let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; | ||
3339 | let lo = self.span; | ||
3340 | // Note: when adding new unary operators, don't forget to adjust Token::can_begin_expr() | ||
3341 | let (hi, ex) = match self.token { | ||
3342 | token::Not => { | ||
3343 | self.bump(); | ||
3344 | let e = self.parse_prefix_expr(None); | ||
3345 | let (span, e) = self.interpolated_or_expr_span(e)?; | ||
3346 | (lo.to(span), self.mk_unary(UnOp::Not, e)) | ||
3347 | } | ||
3348 | // Suggest `!` for bitwise negation when encountering a `~` | ||
3349 | token::Tilde => { | ||
3350 | self.bump(); | ||
3351 | let e = self.parse_prefix_expr(None); | ||
3352 | let (span, e) = self.interpolated_or_expr_span(e)?; | ||
3353 | let span_of_tilde = lo; | ||
3354 | let mut err = self.diagnostic() | ||
3355 | .struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator"); | ||
3356 | err.span_suggestion_short( | ||
3357 | span_of_tilde, | ||
3358 | "use `!` to perform bitwise negation", | ||
3359 | "!".to_owned(), | ||
3360 | Applicability::MachineApplicable | ||
3361 | ); | ||
3362 | err.emit(); | ||
3363 | (lo.to(span), self.mk_unary(UnOp::Not, e)) | ||
3364 | } | ||
3365 | token::BinOp(token::Minus) => { | ||
3366 | self.bump(); | ||
3367 | let e = self.parse_prefix_expr(None); | ||
3368 | let (span, e) = self.interpolated_or_expr_span(e)?; | ||
3369 | (lo.to(span), self.mk_unary(UnOp::Neg, e)) | ||
3370 | } | ||
3371 | token::BinOp(token::Star) => { | ||
3372 | self.bump(); | ||
3373 | let e = self.parse_prefix_expr(None); | ||
3374 | let (span, e) = self.interpolated_or_expr_span(e)?; | ||
3375 | (lo.to(span), self.mk_unary(UnOp::Deref, e)) | ||
3376 | } | ||
3377 | token::BinOp(token::And) | token::AndAnd => { | ||
3378 | self.expect_and()?; | ||
3379 | let m = self.parse_mutability(); | ||
3380 | let e = self.parse_prefix_expr(None); | ||
3381 | let (span, e) = self.interpolated_or_expr_span(e)?; | ||
3382 | (lo.to(span), ExprKind::AddrOf(m, e)) | ||
3383 | } | ||
3384 | token::Ident(..) if self.token.is_keyword(keywords::In) => { | ||
3385 | self.bump(); | ||
3386 | let place = self.parse_expr_res( | ||
3387 | Restrictions::NO_STRUCT_LITERAL, | ||
3388 | None, | ||
3389 | )?; | ||
3390 | let blk = self.parse_block()?; | ||
3391 | let span = blk.span; | ||
3392 | let blk_expr = self.mk_expr(span, ExprKind::Block(blk, None), ThinVec::new()); | ||
3393 | (lo.to(span), ExprKind::ObsoleteInPlace(place, blk_expr)) | ||
3394 | } | ||
3395 | token::Ident(..) if self.token.is_keyword(keywords::Box) => { | ||
3396 | self.bump(); | ||
3397 | let e = self.parse_prefix_expr(None); | ||
3398 | let (span, e) = self.interpolated_or_expr_span(e)?; | ||
3399 | (lo.to(span), ExprKind::Box(e)) | ||
3400 | } | ||
3401 | token::Ident(..) if self.token.is_ident_named("not") => { | ||
3402 | // `not` is just an ordinary identifier in Rust-the-language, | ||
3403 | // but as `rustc`-the-compiler, we can issue clever diagnostics | ||
3404 | // for confused users who really want to say `!` | ||
3405 | let token_cannot_continue_expr = |t: &token::Token| match *t { | ||
3406 | // These tokens can start an expression after `!`, but | ||
3407 | // can't continue an expression after an ident | ||
3408 | token::Ident(ident, is_raw) => token::ident_can_begin_expr(ident, is_raw), | ||
3409 | token::Literal(..) | token::Pound => true, | ||
3410 | token::Interpolated(ref nt) => match **nt { | ||
3411 | token::NtIdent(..) | token::NtExpr(..) | | ||
3412 | token::NtBlock(..) | token::NtPath(..) => true, | ||
3413 | _ => false, | ||
3414 | }, | ||
3415 | _ => false | ||
3416 | }; | ||
3417 | let cannot_continue_expr = self.look_ahead(1, token_cannot_continue_expr); | ||
3418 | if cannot_continue_expr { | ||
3419 | self.bump(); | ||
3420 | // Emit the error ... | ||
3421 | let mut err = self.diagnostic() | ||
3422 | .struct_span_err(self.span, | ||
3423 | &format!("unexpected {} after identifier", | ||
3424 | self.this_token_descr())); | ||
3425 | // span the `not` plus trailing whitespace to avoid | ||
3426 | // trailing whitespace after the `!` in our suggestion | ||
3427 | let to_replace = self.sess.source_map() | ||
3428 | .span_until_non_whitespace(lo.to(self.span)); | ||
3429 | err.span_suggestion_short( | ||
3430 | to_replace, | ||
3431 | "use `!` to perform logical negation", | ||
3432 | "!".to_owned(), | ||
3433 | Applicability::MachineApplicable | ||
3434 | ); | ||
3435 | err.emit(); | ||
3436 | // —and recover! (just as if we were in the block | ||
3437 | // for the `token::Not` arm) | ||
3438 | let e = self.parse_prefix_expr(None); | ||
3439 | let (span, e) = self.interpolated_or_expr_span(e)?; | ||
3440 | (lo.to(span), self.mk_unary(UnOp::Not, e)) | ||
3441 | } else { | ||
3442 | return self.parse_dot_or_call_expr(Some(attrs)); | ||
3443 | } | ||
3444 | } | ||
3445 | _ => { return self.parse_dot_or_call_expr(Some(attrs)); } | ||
3446 | }; | ||
3447 | return Ok(self.mk_expr(lo.to(hi), ex, attrs)); | ||
3448 | } | ||
3449 | |||
3450 | /// Parses an associative expression. | ||
3451 | /// | ||
3452 | /// This parses an expression accounting for associativity and precedence of the operators in | ||
3453 | /// the expression. | ||
3454 | #[inline] | ||
3455 | fn parse_assoc_expr(&mut self, | ||
3456 | already_parsed_attrs: Option<ThinVec<Attribute>>) | ||
3457 | -> PResult<'a, P<Expr>> { | ||
3458 | self.parse_assoc_expr_with(0, already_parsed_attrs.into()) | ||
3459 | } | ||
3460 | |||
3461 | /// Parses an associative expression with operators of at least `min_prec` precedence. | ||
3462 | fn parse_assoc_expr_with(&mut self, | ||
3463 | min_prec: usize, | ||
3464 | lhs: LhsExpr) | ||
3465 | -> PResult<'a, P<Expr>> { | ||
3466 | let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs { | ||
3467 | expr | ||
3468 | } else { | ||
3469 | let attrs = match lhs { | ||
3470 | LhsExpr::AttributesParsed(attrs) => Some(attrs), | ||
3471 | _ => None, | ||
3472 | }; | ||
3473 | if [token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token) { | ||
3474 | return self.parse_prefix_range_expr(attrs); | ||
3475 | } else { | ||
3476 | self.parse_prefix_expr(attrs)? | ||
3477 | } | ||
3478 | }; | ||
3479 | |||
3480 | if self.expr_is_complete(&lhs) { | ||
3481 | // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 | ||
3482 | return Ok(lhs); | ||
3483 | } | ||
3484 | self.expected_tokens.push(TokenType::Operator); | ||
3485 | while let Some(op) = AssocOp::from_token(&self.token) { | ||
3486 | |||
3487 | // Adjust the span for interpolated LHS to point to the `$lhs` token and not to what | ||
3488 | // it refers to. Interpolated identifiers are unwrapped early and never show up here | ||
3489 | // as `PrevTokenKind::Interpolated` so if LHS is a single identifier we always process | ||
3490 | // it as "interpolated", it doesn't change the answer for non-interpolated idents. | ||
3491 | let lhs_span = match (self.prev_token_kind, &lhs.node) { | ||
3492 | (PrevTokenKind::Interpolated, _) => self.prev_span, | ||
3493 | (PrevTokenKind::Ident, &ExprKind::Path(None, ref path)) | ||
3494 | if path.segments.len() == 1 => self.prev_span, | ||
3495 | _ => lhs.span, | ||
3496 | }; | ||
3497 | |||
3498 | let cur_op_span = self.span; | ||
3499 | let restrictions = if op.is_assign_like() { | ||
3500 | self.restrictions & Restrictions::NO_STRUCT_LITERAL | ||
3501 | } else { | ||
3502 | self.restrictions | ||
3503 | }; | ||
3504 | if op.precedence() < min_prec { | ||
3505 | break; | ||
3506 | } | ||
3507 | // Check for deprecated `...` syntax | ||
3508 | if self.token == token::DotDotDot && op == AssocOp::DotDotEq { | ||
3509 | self.err_dotdotdot_syntax(self.span); | ||
3510 | } | ||
3511 | |||
3512 | self.bump(); | ||
3513 | if op.is_comparison() { | ||
3514 | self.check_no_chained_comparison(&lhs, &op); | ||
3515 | } | ||
3516 | // Special cases: | ||
3517 | if op == AssocOp::As { | ||
3518 | lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Cast)?; | ||
3519 | continue | ||
3520 | } else if op == AssocOp::Colon { | ||
3521 | lhs = match self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type) { | ||
3522 | Ok(lhs) => lhs, | ||
3523 | Err(mut err) => { | ||
3524 | err.span_label(self.span, | ||
3525 | "expecting a type here because of type ascription"); | ||
3526 | let cm = self.sess.source_map(); | ||
3527 | let cur_pos = cm.lookup_char_pos(self.span.lo()); | ||
3528 | let op_pos = cm.lookup_char_pos(cur_op_span.hi()); | ||
3529 | if cur_pos.line != op_pos.line { | ||
3530 | err.span_suggestion( | ||
3531 | cur_op_span, | ||
3532 | "try using a semicolon", | ||
3533 | ";".to_string(), | ||
3534 | Applicability::MaybeIncorrect // speculative | ||
3535 | ); | ||
3536 | } | ||
3537 | return Err(err); | ||
3538 | } | ||
3539 | }; | ||
3540 | continue | ||
3541 | } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { | ||
3542 | // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to | ||
3543 | // generalise it to the Fixity::None code. | ||
3544 | // | ||
3545 | // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other | ||
3546 | // two variants are handled with `parse_prefix_range_expr` call above. | ||
3547 | let rhs = if self.is_at_start_of_range_notation_rhs() { | ||
3548 | Some(self.parse_assoc_expr_with(op.precedence() + 1, | ||
3549 | LhsExpr::NotYetParsed)?) | ||
3550 | } else { | ||
3551 | None | ||
3552 | }; | ||
3553 | let (lhs_span, rhs_span) = (lhs.span, if let Some(ref x) = rhs { | ||
3554 | x.span | ||
3555 | } else { | ||
3556 | cur_op_span | ||
3557 | }); | ||
3558 | let limits = if op == AssocOp::DotDot { | ||
3559 | RangeLimits::HalfOpen | ||
3560 | } else { | ||
3561 | RangeLimits::Closed | ||
3562 | }; | ||
3563 | |||
3564 | let r = self.mk_range(Some(lhs), rhs, limits)?; | ||
3565 | lhs = self.mk_expr(lhs_span.to(rhs_span), r, ThinVec::new()); | ||
3566 | break | ||
3567 | } | ||
3568 | |||
3569 | let rhs = match op.fixity() { | ||
3570 | Fixity::Right => self.with_res( | ||
3571 | restrictions - Restrictions::STMT_EXPR, | ||
3572 | |this| { | ||
3573 | this.parse_assoc_expr_with(op.precedence(), | ||
3574 | LhsExpr::NotYetParsed) | ||
3575 | }), | ||
3576 | Fixity::Left => self.with_res( | ||
3577 | restrictions - Restrictions::STMT_EXPR, | ||
3578 | |this| { | ||
3579 | this.parse_assoc_expr_with(op.precedence() + 1, | ||
3580 | LhsExpr::NotYetParsed) | ||
3581 | }), | ||
3582 | // We currently have no non-associative operators that are not handled above by | ||
3583 | // the special cases. The code is here only for future convenience. | ||
3584 | Fixity::None => self.with_res( | ||
3585 | restrictions - Restrictions::STMT_EXPR, | ||
3586 | |this| { | ||
3587 | this.parse_assoc_expr_with(op.precedence() + 1, | ||
3588 | LhsExpr::NotYetParsed) | ||
3589 | }), | ||
3590 | }?; | ||
3591 | |||
3592 | // Make sure that the span of the parent node is larger than the span of lhs and rhs, | ||
3593 | // including the attributes. | ||
3594 | let lhs_span = lhs | ||
3595 | .attrs | ||
3596 | .iter() | ||
3597 | .filter(|a| a.style == AttrStyle::Outer) | ||
3598 | .next() | ||
3599 | .map_or(lhs_span, |a| a.span); | ||
3600 | let span = lhs_span.to(rhs.span); | ||
3601 | lhs = match op { | ||
3602 | AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide | | ||
3603 | AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor | | ||
3604 | AssocOp::BitAnd | AssocOp::BitOr | AssocOp::ShiftLeft | AssocOp::ShiftRight | | ||
3605 | AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual | | ||
3606 | AssocOp::Greater | AssocOp::GreaterEqual => { | ||
3607 | let ast_op = op.to_ast_binop().unwrap(); | ||
3608 | let binary = self.mk_binary(source_map::respan(cur_op_span, ast_op), lhs, rhs); | ||
3609 | self.mk_expr(span, binary, ThinVec::new()) | ||
3610 | } | ||
3611 | AssocOp::Assign => | ||
3612 | self.mk_expr(span, ExprKind::Assign(lhs, rhs), ThinVec::new()), | ||
3613 | AssocOp::ObsoleteInPlace => | ||
3614 | self.mk_expr(span, ExprKind::ObsoleteInPlace(lhs, rhs), ThinVec::new()), | ||
3615 | AssocOp::AssignOp(k) => { | ||
3616 | let aop = match k { | ||
3617 | token::Plus => BinOpKind::Add, | ||
3618 | token::Minus => BinOpKind::Sub, | ||
3619 | token::Star => BinOpKind::Mul, | ||
3620 | token::Slash => BinOpKind::Div, | ||
3621 | token::Percent => BinOpKind::Rem, | ||
3622 | token::Caret => BinOpKind::BitXor, | ||
3623 | token::And => BinOpKind::BitAnd, | ||
3624 | token::Or => BinOpKind::BitOr, | ||
3625 | token::Shl => BinOpKind::Shl, | ||
3626 | token::Shr => BinOpKind::Shr, | ||
3627 | }; | ||
3628 | let aopexpr = self.mk_assign_op(source_map::respan(cur_op_span, aop), lhs, rhs); | ||
3629 | self.mk_expr(span, aopexpr, ThinVec::new()) | ||
3630 | } | ||
3631 | AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotEq => { | ||
3632 | self.bug("AssocOp should have been handled by special case") | ||
3633 | } | ||
3634 | }; | ||
3635 | |||
3636 | if op.fixity() == Fixity::None { break } | ||
3637 | } | ||
3638 | Ok(lhs) | ||
3639 | } | ||
3640 | |||
3641 | fn parse_assoc_op_cast(&mut self, lhs: P<Expr>, lhs_span: Span, | ||
3642 | expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind) | ||
3643 | -> PResult<'a, P<Expr>> { | ||
3644 | let mk_expr = |this: &mut Self, rhs: P<Ty>| { | ||
3645 | this.mk_expr(lhs_span.to(rhs.span), expr_kind(lhs, rhs), ThinVec::new()) | ||
3646 | }; | ||
3647 | |||
3648 | // Save the state of the parser before parsing type normally, in case there is a | ||
3649 | // LessThan comparison after this cast. | ||
3650 | let parser_snapshot_before_type = self.clone(); | ||
3651 | match self.parse_ty_no_plus() { | ||
3652 | Ok(rhs) => { | ||
3653 | Ok(mk_expr(self, rhs)) | ||
3654 | } | ||
3655 | Err(mut type_err) => { | ||
3656 | // Rewind to before attempting to parse the type with generics, to recover | ||
3657 | // from situations like `x as usize < y` in which we first tried to parse | ||
3658 | // `usize < y` as a type with generic arguments. | ||
3659 | let parser_snapshot_after_type = self.clone(); | ||
3660 | mem::replace(self, parser_snapshot_before_type); | ||
3661 | |||
3662 | match self.parse_path(PathStyle::Expr) { | ||
3663 | Ok(path) => { | ||
3664 | let (op_noun, op_verb) = match self.token { | ||
3665 | token::Lt => ("comparison", "comparing"), | ||
3666 | token::BinOp(token::Shl) => ("shift", "shifting"), | ||
3667 | _ => { | ||
3668 | // We can end up here even without `<` being the next token, for | ||
3669 | // example because `parse_ty_no_plus` returns `Err` on keywords, | ||
3670 | // but `parse_path` returns `Ok` on them due to error recovery. | ||
3671 | // Return original error and parser state. | ||
3672 | mem::replace(self, parser_snapshot_after_type); | ||
3673 | return Err(type_err); | ||
3674 | } | ||
3675 | }; | ||
3676 | |||
3677 | // Successfully parsed the type path leaving a `<` yet to parse. | ||
3678 | type_err.cancel(); | ||
3679 | |||
3680 | // Report non-fatal diagnostics, keep `x as usize` as an expression | ||
3681 | // in AST and continue parsing. | ||
3682 | let msg = format!("`<` is interpreted as a start of generic \ | ||
3683 | arguments for `{}`, not a {}", path, op_noun); | ||
3684 | let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg); | ||
3685 | err.span_label(self.look_ahead_span(1).to(parser_snapshot_after_type.span), | ||
3686 | "interpreted as generic arguments"); | ||
3687 | err.span_label(self.span, format!("not interpreted as {}", op_noun)); | ||
3688 | |||
3689 | let expr = mk_expr(self, P(Ty { | ||
3690 | span: path.span, | ||
3691 | node: TyKind::Path(None, path), | ||
3692 | id: ast::DUMMY_NODE_ID | ||
3693 | })); | ||
3694 | |||
3695 | let expr_str = self.sess.source_map().span_to_snippet(expr.span) | ||
3696 | .unwrap_or_else(|_| pprust::expr_to_string(&expr)); | ||
3697 | err.span_suggestion( | ||
3698 | expr.span, | ||
3699 | &format!("try {} the cast value", op_verb), | ||
3700 | format!("({})", expr_str), | ||
3701 | Applicability::MachineApplicable | ||
3702 | ); | ||
3703 | err.emit(); | ||
3704 | |||
3705 | Ok(expr) | ||
3706 | } | ||
3707 | Err(mut path_err) => { | ||
3708 | // Couldn't parse as a path, return original error and parser state. | ||
3709 | path_err.cancel(); | ||
3710 | mem::replace(self, parser_snapshot_after_type); | ||
3711 | Err(type_err) | ||
3712 | } | ||
3713 | } | ||
3714 | } | ||
3715 | } | ||
3716 | } | ||
3717 | |||
3718 | /// Produce an error if comparison operators are chained (RFC #558). | ||
3719 | /// We only need to check lhs, not rhs, because all comparison ops | ||
3720 | /// have same precedence and are left-associative | ||
3721 | fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) { | ||
3722 | debug_assert!(outer_op.is_comparison(), | ||
3723 | "check_no_chained_comparison: {:?} is not comparison", | ||
3724 | outer_op); | ||
3725 | match lhs.node { | ||
3726 | ExprKind::Binary(op, _, _) if op.node.is_comparison() => { | ||
3727 | // respan to include both operators | ||
3728 | let op_span = op.span.to(self.span); | ||
3729 | let mut err = self.diagnostic().struct_span_err(op_span, | ||
3730 | "chained comparison operators require parentheses"); | ||
3731 | if op.node == BinOpKind::Lt && | ||
3732 | *outer_op == AssocOp::Less || // Include `<` to provide this recommendation | ||
3733 | *outer_op == AssocOp::Greater // even in a case like the following: | ||
3734 | { // Foo<Bar<Baz<Qux, ()>>> | ||
3735 | err.help( | ||
3736 | "use `::<...>` instead of `<...>` if you meant to specify type arguments"); | ||
3737 | err.help("or use `(...)` if you meant to specify fn arguments"); | ||
3738 | } | ||
3739 | err.emit(); | ||
3740 | } | ||
3741 | _ => {} | ||
3742 | } | ||
3743 | } | ||
3744 | |||
3745 | /// Parse prefix-forms of range notation: `..expr`, `..`, `..=expr` | ||
3746 | fn parse_prefix_range_expr(&mut self, | ||
3747 | already_parsed_attrs: Option<ThinVec<Attribute>>) | ||
3748 | -> PResult<'a, P<Expr>> { | ||
3749 | // Check for deprecated `...` syntax | ||
3750 | if self.token == token::DotDotDot { | ||
3751 | self.err_dotdotdot_syntax(self.span); | ||
3752 | } | ||
3753 | |||
3754 | debug_assert!([token::DotDot, token::DotDotDot, token::DotDotEq].contains(&self.token), | ||
3755 | "parse_prefix_range_expr: token {:?} is not DotDot/DotDotEq", | ||
3756 | self.token); | ||
3757 | let tok = self.token.clone(); | ||
3758 | let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; | ||
3759 | let lo = self.span; | ||
3760 | let mut hi = self.span; | ||
3761 | self.bump(); | ||
3762 | let opt_end = if self.is_at_start_of_range_notation_rhs() { | ||
3763 | // RHS must be parsed with more associativity than the dots. | ||
3764 | let next_prec = AssocOp::from_token(&tok).unwrap().precedence() + 1; | ||
3765 | Some(self.parse_assoc_expr_with(next_prec, | ||
3766 | LhsExpr::NotYetParsed) | ||
3767 | .map(|x|{ | ||
3768 | hi = x.span; | ||
3769 | x | ||
3770 | })?) | ||
3771 | } else { | ||
3772 | None | ||
3773 | }; | ||
3774 | let limits = if tok == token::DotDot { | ||
3775 | RangeLimits::HalfOpen | ||
3776 | } else { | ||
3777 | RangeLimits::Closed | ||
3778 | }; | ||
3779 | |||
3780 | let r = self.mk_range(None, opt_end, limits)?; | ||
3781 | Ok(self.mk_expr(lo.to(hi), r, attrs)) | ||
3782 | } | ||
3783 | |||
3784 | fn is_at_start_of_range_notation_rhs(&self) -> bool { | ||
3785 | if self.token.can_begin_expr() { | ||
3786 | // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`. | ||
3787 | if self.token == token::OpenDelim(token::Brace) { | ||
3788 | return !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); | ||
3789 | } | ||
3790 | true | ||
3791 | } else { | ||
3792 | false | ||
3793 | } | ||
3794 | } | ||
3795 | |||
3796 | /// Parses an `if` or `if let` expression (`if` token already eaten). | ||
3797 | fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { | ||
3798 | if self.check_keyword(keywords::Let) { | ||
3799 | return self.parse_if_let_expr(attrs); | ||
3800 | } | ||
3801 | let lo = self.prev_span; | ||
3802 | let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; | ||
3803 | |||
3804 | // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then | ||
3805 | // verify that the last statement is either an implicit return (no `;`) or an explicit | ||
3806 | // return. This won't catch blocks with an explicit `return`, but that would be caught by | ||
3807 | // the dead code lint. | ||
3808 | if self.eat_keyword(keywords::Else) || !cond.returns() { | ||
3809 | let sp = self.sess.source_map().next_point(lo); | ||
3810 | let mut err = self.diagnostic() | ||
3811 | .struct_span_err(sp, "missing condition for `if` statemement"); | ||
3812 | err.span_label(sp, "expected if condition here"); | ||
3813 | return Err(err) | ||
3814 | } | ||
3815 | let not_block = self.token != token::OpenDelim(token::Brace); | ||
3816 | let thn = self.parse_block().map_err(|mut err| { | ||
3817 | if not_block { | ||
3818 | err.span_label(lo, "this `if` statement has a condition, but no block"); | ||
3819 | } | ||
3820 | err | ||
3821 | })?; | ||
3822 | let mut els: Option<P<Expr>> = None; | ||
3823 | let mut hi = thn.span; | ||
3824 | if self.eat_keyword(keywords::Else) { | ||
3825 | let elexpr = self.parse_else_expr()?; | ||
3826 | hi = elexpr.span; | ||
3827 | els = Some(elexpr); | ||
3828 | } | ||
3829 | Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs)) | ||
3830 | } | ||
3831 | |||
3832 | /// Parses an `if let` expression (`if` token already eaten). | ||
3833 | fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>) | ||
3834 | -> PResult<'a, P<Expr>> { | ||
3835 | let lo = self.prev_span; | ||
3836 | self.expect_keyword(keywords::Let)?; | ||
3837 | let pats = self.parse_pats()?; | ||
3838 | self.expect(&token::Eq)?; | ||
3839 | let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; | ||
3840 | let thn = self.parse_block()?; | ||
3841 | let (hi, els) = if self.eat_keyword(keywords::Else) { | ||
3842 | let expr = self.parse_else_expr()?; | ||
3843 | (expr.span, Some(expr)) | ||
3844 | } else { | ||
3845 | (thn.span, None) | ||
3846 | }; | ||
3847 | Ok(self.mk_expr(lo.to(hi), ExprKind::IfLet(pats, expr, thn, els), attrs)) | ||
3848 | } | ||
3849 | |||
3850 | /// Parses `move |args| expr`. | ||
3851 | fn parse_lambda_expr(&mut self, | ||
3852 | attrs: ThinVec<Attribute>) | ||
3853 | -> PResult<'a, P<Expr>> | ||
3854 | { | ||
3855 | let lo = self.span; | ||
3856 | let movability = if self.eat_keyword(keywords::Static) { | ||
3857 | Movability::Static | ||
3858 | } else { | ||
3859 | Movability::Movable | ||
3860 | }; | ||
3861 | let asyncness = if self.span.rust_2018() { | ||
3862 | self.parse_asyncness() | ||
3863 | } else { | ||
3864 | IsAsync::NotAsync | ||
3865 | }; | ||
3866 | let capture_clause = if self.eat_keyword(keywords::Move) { | ||
3867 | CaptureBy::Value | ||
3868 | } else { | ||
3869 | CaptureBy::Ref | ||
3870 | }; | ||
3871 | let decl = self.parse_fn_block_decl()?; | ||
3872 | let decl_hi = self.prev_span; | ||
3873 | let body = match decl.output { | ||
3874 | FunctionRetTy::Default(_) => { | ||
3875 | let restrictions = self.restrictions - Restrictions::STMT_EXPR; | ||
3876 | self.parse_expr_res(restrictions, None)? | ||
3877 | }, | ||
3878 | _ => { | ||
3879 | // If an explicit return type is given, require a | ||
3880 | // block to appear (RFC 968). | ||
3881 | let body_lo = self.span; | ||
3882 | self.parse_block_expr(None, body_lo, BlockCheckMode::Default, ThinVec::new())? | ||
3883 | } | ||
3884 | }; | ||
3885 | |||
3886 | Ok(self.mk_expr( | ||
3887 | lo.to(body.span), | ||
3888 | ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)), | ||
3889 | attrs)) | ||
3890 | } | ||
3891 | |||
3892 | // `else` token already eaten | ||
3893 | fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { | ||
3894 | if self.eat_keyword(keywords::If) { | ||
3895 | return self.parse_if_expr(ThinVec::new()); | ||
3896 | } else { | ||
3897 | let blk = self.parse_block()?; | ||
3898 | return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), ThinVec::new())); | ||
3899 | } | ||
3900 | } | ||
3901 | |||
3902 | /// Parse a 'for' .. 'in' expression ('for' token already eaten) | ||
3903 | fn parse_for_expr(&mut self, opt_label: Option<Label>, | ||
3904 | span_lo: Span, | ||
3905 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { | ||
3906 | // Parse: `for <src_pat> in <src_expr> <src_loop_block>` | ||
3907 | |||
3908 | let pat = self.parse_top_level_pat()?; | ||
3909 | if !self.eat_keyword(keywords::In) { | ||
3910 | let in_span = self.prev_span.between(self.span); | ||
3911 | let mut err = self.sess.span_diagnostic | ||
3912 | .struct_span_err(in_span, "missing `in` in `for` loop"); | ||
3913 | err.span_suggestion_short( | ||
3914 | in_span, "try adding `in` here", " in ".into(), | ||
3915 | // has been misleading, at least in the past (closed Issue #48492) | ||
3916 | Applicability::MaybeIncorrect | ||
3917 | ); | ||
3918 | err.emit(); | ||
3919 | } | ||
3920 | let in_span = self.prev_span; | ||
3921 | if self.eat_keyword(keywords::In) { | ||
3922 | // a common typo: `for _ in in bar {}` | ||
3923 | let mut err = self.sess.span_diagnostic.struct_span_err( | ||
3924 | self.prev_span, | ||
3925 | "expected iterable, found keyword `in`", | ||
3926 | ); | ||
3927 | err.span_suggestion_short( | ||
3928 | in_span.until(self.prev_span), | ||
3929 | "remove the duplicated `in`", | ||
3930 | String::new(), | ||
3931 | Applicability::MachineApplicable, | ||
3932 | ); | ||
3933 | err.note("if you meant to use emplacement syntax, it is obsolete (for now, anyway)"); | ||
3934 | err.note("for more information on the status of emplacement syntax, see <\ | ||
3935 | https://github.com/rust-lang/rust/issues/27779#issuecomment-378416911>"); | ||
3936 | err.emit(); | ||
3937 | } | ||
3938 | let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; | ||
3939 | let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?; | ||
3940 | attrs.extend(iattrs); | ||
3941 | |||
3942 | let hi = self.prev_span; | ||
3943 | Ok(self.mk_expr(span_lo.to(hi), ExprKind::ForLoop(pat, expr, loop_block, opt_label), attrs)) | ||
3944 | } | ||
3945 | |||
3946 | /// Parses a `while` or `while let` expression (`while` token already eaten). | ||
3947 | fn parse_while_expr(&mut self, opt_label: Option<Label>, | ||
3948 | span_lo: Span, | ||
3949 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { | ||
3950 | if self.token.is_keyword(keywords::Let) { | ||
3951 | return self.parse_while_let_expr(opt_label, span_lo, attrs); | ||
3952 | } | ||
3953 | let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; | ||
3954 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; | ||
3955 | attrs.extend(iattrs); | ||
3956 | let span = span_lo.to(body.span); | ||
3957 | return Ok(self.mk_expr(span, ExprKind::While(cond, body, opt_label), attrs)); | ||
3958 | } | ||
3959 | |||
3960 | /// Parses a `while let` expression (`while` token already eaten). | ||
3961 | fn parse_while_let_expr(&mut self, opt_label: Option<Label>, | ||
3962 | span_lo: Span, | ||
3963 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { | ||
3964 | self.expect_keyword(keywords::Let)?; | ||
3965 | let pats = self.parse_pats()?; | ||
3966 | self.expect(&token::Eq)?; | ||
3967 | let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; | ||
3968 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; | ||
3969 | attrs.extend(iattrs); | ||
3970 | let span = span_lo.to(body.span); | ||
3971 | return Ok(self.mk_expr(span, ExprKind::WhileLet(pats, expr, body, opt_label), attrs)); | ||
3972 | } | ||
3973 | |||
3974 | // parse `loop {...}`, `loop` token already eaten | ||
3975 | fn parse_loop_expr(&mut self, opt_label: Option<Label>, | ||
3976 | span_lo: Span, | ||
3977 | mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { | ||
3978 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; | ||
3979 | attrs.extend(iattrs); | ||
3980 | let span = span_lo.to(body.span); | ||
3981 | Ok(self.mk_expr(span, ExprKind::Loop(body, opt_label), attrs)) | ||
3982 | } | ||
3983 | |||
3984 | /// Parses an `async move {...}` expression. | ||
3985 | pub fn parse_async_block(&mut self, mut attrs: ThinVec<Attribute>) | ||
3986 | -> PResult<'a, P<Expr>> | ||
3987 | { | ||
3988 | let span_lo = self.span; | ||
3989 | self.expect_keyword(keywords::Async)?; | ||
3990 | let capture_clause = if self.eat_keyword(keywords::Move) { | ||
3991 | CaptureBy::Value | ||
3992 | } else { | ||
3993 | CaptureBy::Ref | ||
3994 | }; | ||
3995 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; | ||
3996 | attrs.extend(iattrs); | ||
3997 | Ok(self.mk_expr( | ||
3998 | span_lo.to(body.span), | ||
3999 | ExprKind::Async(capture_clause, ast::DUMMY_NODE_ID, body), attrs)) | ||
4000 | } | ||
4001 | |||
4002 | /// Parses a `try {...}` expression (`try` token already eaten). | ||
4003 | fn parse_try_block(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>) | ||
4004 | -> PResult<'a, P<Expr>> | ||
4005 | { | ||
4006 | let (iattrs, body) = self.parse_inner_attrs_and_block()?; | ||
4007 | attrs.extend(iattrs); | ||
4008 | Ok(self.mk_expr(span_lo.to(body.span), ExprKind::TryBlock(body), attrs)) | ||
4009 | } | ||
4010 | |||
4011 | // `match` token already eaten | ||
4012 | fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { | ||
4013 | let match_span = self.prev_span; | ||
4014 | let lo = self.prev_span; | ||
4015 | let discriminant = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, | ||
4016 | None)?; | ||
4017 | if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) { | ||
4018 | if self.token == token::Token::Semi { | ||
4019 | e.span_suggestion_short( | ||
4020 | match_span, | ||
4021 | "try removing this `match`", | ||
4022 | String::new(), | ||
4023 | Applicability::MaybeIncorrect // speculative | ||
4024 | ); | ||
4025 | } | ||
4026 | return Err(e) | ||
4027 | } | ||
4028 | attrs.extend(self.parse_inner_attributes()?); | ||
4029 | |||
4030 | let mut arms: Vec<Arm> = Vec::new(); | ||
4031 | while self.token != token::CloseDelim(token::Brace) { | ||
4032 | match self.parse_arm() { | ||
4033 | Ok(arm) => arms.push(arm), | ||
4034 | Err(mut e) => { | ||
4035 | // Recover by skipping to the end of the block. | ||
4036 | e.emit(); | ||
4037 | self.recover_stmt(); | ||
4038 | let span = lo.to(self.span); | ||
4039 | if self.token == token::CloseDelim(token::Brace) { | ||
4040 | self.bump(); | ||
4041 | } | ||
4042 | return Ok(self.mk_expr(span, ExprKind::Match(discriminant, arms), attrs)); | ||
4043 | } | ||
4044 | } | ||
4045 | } | ||
4046 | let hi = self.span; | ||
4047 | self.bump(); | ||
4048 | return Ok(self.mk_expr(lo.to(hi), ExprKind::Match(discriminant, arms), attrs)); | ||
4049 | } | ||
4050 | |||
4051 | crate fn parse_arm(&mut self) -> PResult<'a, Arm> { | ||
4052 | maybe_whole!(self, NtArm, |x| x); | ||
4053 | |||
4054 | let attrs = self.parse_outer_attributes()?; | ||
4055 | let pats = self.parse_pats()?; | ||
4056 | let guard = if self.eat_keyword(keywords::If) { | ||
4057 | Some(Guard::If(self.parse_expr()?)) | ||
4058 | } else { | ||
4059 | None | ||
4060 | }; | ||
4061 | let arrow_span = self.span; | ||
4062 | self.expect(&token::FatArrow)?; | ||
4063 | let arm_start_span = self.span; | ||
4064 | |||
4065 | let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None) | ||
4066 | .map_err(|mut err| { | ||
4067 | err.span_label(arrow_span, "while parsing the `match` arm starting here"); | ||
4068 | err | ||
4069 | })?; | ||
4070 | |||
4071 | let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) | ||
4072 | && self.token != token::CloseDelim(token::Brace); | ||
4073 | |||
4074 | if require_comma { | ||
4075 | let cm = self.sess.source_map(); | ||
4076 | self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) | ||
4077 | .map_err(|mut err| { | ||
4078 | match (cm.span_to_lines(expr.span), cm.span_to_lines(arm_start_span)) { | ||
4079 | (Ok(ref expr_lines), Ok(ref arm_start_lines)) | ||
4080 | if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col | ||
4081 | && expr_lines.lines.len() == 2 | ||
4082 | && self.token == token::FatArrow => { | ||
4083 | // We check whether there's any trailing code in the parse span, | ||
4084 | // if there isn't, we very likely have the following: | ||
4085 | // | ||
4086 | // X | &Y => "y" | ||
4087 | // | -- - missing comma | ||
4088 | // | | | ||
4089 | // | arrow_span | ||
4090 | // X | &X => "x" | ||
4091 | // | - ^^ self.span | ||
4092 | // | | | ||
4093 | // | parsed until here as `"y" & X` | ||
4094 | err.span_suggestion_short( | ||
4095 | cm.next_point(arm_start_span), | ||
4096 | "missing a comma here to end this `match` arm", | ||
4097 | ",".to_owned(), | ||
4098 | Applicability::MachineApplicable | ||
4099 | ); | ||
4100 | } | ||
4101 | _ => { | ||
4102 | err.span_label(arrow_span, | ||
4103 | "while parsing the `match` arm starting here"); | ||
4104 | } | ||
4105 | } | ||
4106 | err | ||
4107 | })?; | ||
4108 | } else { | ||
4109 | self.eat(&token::Comma); | ||
4110 | } | ||
4111 | |||
4112 | Ok(ast::Arm { | ||
4113 | attrs, | ||
4114 | pats, | ||
4115 | guard, | ||
4116 | body: expr, | ||
4117 | }) | ||
4118 | } | ||
4119 | |||
4120 | /// Parses an expression. | ||
4121 | #[inline] | ||
4122 | pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> { | ||
4123 | self.parse_expr_res(Restrictions::empty(), None) | ||
4124 | } | ||
4125 | |||
4126 | /// Evaluates the closure with restrictions in place. | ||
4127 | /// | ||
4128 | /// Afters the closure is evaluated, restrictions are reset. | ||
4129 | fn with_res<F, T>(&mut self, r: Restrictions, f: F) -> T | ||
4130 | where F: FnOnce(&mut Self) -> T | ||
4131 | { | ||
4132 | let old = self.restrictions; | ||
4133 | self.restrictions = r; | ||
4134 | let r = f(self); | ||
4135 | self.restrictions = old; | ||
4136 | return r; | ||
4137 | |||
4138 | } | ||
4139 | |||
4140 | /// Parses an expression, subject to the given restrictions. | ||
4141 | #[inline] | ||
4142 | fn parse_expr_res(&mut self, r: Restrictions, | ||
4143 | already_parsed_attrs: Option<ThinVec<Attribute>>) | ||
4144 | -> PResult<'a, P<Expr>> { | ||
4145 | self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs)) | ||
4146 | } | ||
4147 | |||
4148 | /// Parses the RHS of a local variable declaration (e.g., '= 14;'). | ||
4149 | fn parse_initializer(&mut self, skip_eq: bool) -> PResult<'a, Option<P<Expr>>> { | ||
4150 | if self.eat(&token::Eq) { | ||
4151 | Ok(Some(self.parse_expr()?)) | ||
4152 | } else if skip_eq { | ||
4153 | Ok(Some(self.parse_expr()?)) | ||
4154 | } else { | ||
4155 | Ok(None) | ||
4156 | } | ||
4157 | } | ||
4158 | |||
4159 | /// Parses patterns, separated by '|' s. | ||
4160 | fn parse_pats(&mut self) -> PResult<'a, Vec<P<Pat>>> { | ||
4161 | // Allow a '|' before the pats (RFC 1925 + RFC 2530) | ||
4162 | self.eat(&token::BinOp(token::Or)); | ||
4163 | |||
4164 | let mut pats = Vec::new(); | ||
4165 | loop { | ||
4166 | pats.push(self.parse_top_level_pat()?); | ||
4167 | |||
4168 | if self.token == token::OrOr { | ||
4169 | let mut err = self.struct_span_err(self.span, | ||
4170 | "unexpected token `||` after pattern"); | ||
4171 | err.span_suggestion( | ||
4172 | self.span, | ||
4173 | "use a single `|` to specify multiple patterns", | ||
4174 | "|".to_owned(), | ||
4175 | Applicability::MachineApplicable | ||
4176 | ); | ||
4177 | err.emit(); | ||
4178 | self.bump(); | ||
4179 | } else if self.eat(&token::BinOp(token::Or)) { | ||
4180 | // This is a No-op. Continue the loop to parse the next | ||
4181 | // pattern. | ||
4182 | } else { | ||
4183 | return Ok(pats); | ||
4184 | } | ||
4185 | }; | ||
4186 | } | ||
4187 | |||
4188 | // Parses a parenthesized list of patterns like | ||
4189 | // `()`, `(p)`, `(p,)`, `(p, q)`, or `(p, .., q)`. Returns: | ||
4190 | // - a vector of the patterns that were parsed | ||
4191 | // - an option indicating the index of the `..` element | ||
4192 | // - a boolean indicating whether a trailing comma was present. | ||
4193 | // Trailing commas are significant because (p) and (p,) are different patterns. | ||
4194 | fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> { | ||
4195 | self.expect(&token::OpenDelim(token::Paren))?; | ||
4196 | let result = self.parse_pat_list()?; | ||
4197 | self.expect(&token::CloseDelim(token::Paren))?; | ||
4198 | Ok(result) | ||
4199 | } | ||
4200 | |||
4201 | fn parse_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> { | ||
4202 | let mut fields = Vec::new(); | ||
4203 | let mut ddpos = None; | ||
4204 | let mut trailing_comma = false; | ||
4205 | loop { | ||
4206 | if self.eat(&token::DotDot) { | ||
4207 | if ddpos.is_none() { | ||
4208 | ddpos = Some(fields.len()); | ||
4209 | } else { | ||
4210 | // Emit a friendly error, ignore `..` and continue parsing | ||
4211 | self.struct_span_err( | ||
4212 | self.prev_span, | ||
4213 | "`..` can only be used once per tuple or tuple struct pattern", | ||
4214 | ) | ||
4215 | .span_label(self.prev_span, "can only be used once per pattern") | ||
4216 | .emit(); | ||
4217 | } | ||
4218 | } else if !self.check(&token::CloseDelim(token::Paren)) { | ||
4219 | fields.push(self.parse_pat(None)?); | ||
4220 | } else { | ||
4221 | break | ||
4222 | } | ||
4223 | |||
4224 | trailing_comma = self.eat(&token::Comma); | ||
4225 | if !trailing_comma { | ||
4226 | break | ||
4227 | } | ||
4228 | } | ||
4229 | |||
4230 | if ddpos == Some(fields.len()) && trailing_comma { | ||
4231 | // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed. | ||
4232 | let msg = "trailing comma is not permitted after `..`"; | ||
4233 | self.struct_span_err(self.prev_span, msg) | ||
4234 | .span_label(self.prev_span, msg) | ||
4235 | .emit(); | ||
4236 | } | ||
4237 | |||
4238 | Ok((fields, ddpos, trailing_comma)) | ||
4239 | } | ||
4240 | |||
4241 | fn parse_pat_vec_elements( | ||
4242 | &mut self, | ||
4243 | ) -> PResult<'a, (Vec<P<Pat>>, Option<P<Pat>>, Vec<P<Pat>>)> { | ||
4244 | let mut before = Vec::new(); | ||
4245 | let mut slice = None; | ||
4246 | let mut after = Vec::new(); | ||
4247 | let mut first = true; | ||
4248 | let mut before_slice = true; | ||
4249 | |||
4250 | while self.token != token::CloseDelim(token::Bracket) { | ||
4251 | if first { | ||
4252 | first = false; | ||
4253 | } else { | ||
4254 | self.expect(&token::Comma)?; | ||
4255 | |||
4256 | if self.token == token::CloseDelim(token::Bracket) | ||
4257 | && (before_slice || !after.is_empty()) { | ||
4258 | break | ||
4259 | } | ||
4260 | } | ||
4261 | |||
4262 | if before_slice { | ||
4263 | if self.eat(&token::DotDot) { | ||
4264 | |||
4265 | if self.check(&token::Comma) || | ||
4266 | self.check(&token::CloseDelim(token::Bracket)) { | ||
4267 | slice = Some(P(Pat { | ||
4268 | id: ast::DUMMY_NODE_ID, | ||
4269 | node: PatKind::Wild, | ||
4270 | span: self.prev_span, | ||
4271 | })); | ||
4272 | before_slice = false; | ||
4273 | } | ||
4274 | continue | ||
4275 | } | ||
4276 | } | ||
4277 | |||
4278 | let subpat = self.parse_pat(None)?; | ||
4279 | if before_slice && self.eat(&token::DotDot) { | ||
4280 | slice = Some(subpat); | ||
4281 | before_slice = false; | ||
4282 | } else if before_slice { | ||
4283 | before.push(subpat); | ||
4284 | } else { | ||
4285 | after.push(subpat); | ||
4286 | } | ||
4287 | } | ||
4288 | |||
4289 | Ok((before, slice, after)) | ||
4290 | } | ||
4291 | |||
4292 | fn parse_pat_field( | ||
4293 | &mut self, | ||
4294 | lo: Span, | ||
4295 | attrs: Vec<Attribute> | ||
4296 | ) -> PResult<'a, source_map::Spanned<ast::FieldPat>> { | ||
4297 | // Check if a colon exists one ahead. This means we're parsing a fieldname. | ||
4298 | let hi; | ||
4299 | let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) { | ||
4300 | // Parsing a pattern of the form "fieldname: pat" | ||
4301 | let fieldname = self.parse_field_name()?; | ||
4302 | self.bump(); | ||
4303 | let pat = self.parse_pat(None)?; | ||
4304 | hi = pat.span; | ||
4305 | (pat, fieldname, false) | ||
4306 | } else { | ||
4307 | // Parsing a pattern of the form "(box) (ref) (mut) fieldname" | ||
4308 | let is_box = self.eat_keyword(keywords::Box); | ||
4309 | let boxed_span = self.span; | ||
4310 | let is_ref = self.eat_keyword(keywords::Ref); | ||
4311 | let is_mut = self.eat_keyword(keywords::Mut); | ||
4312 | let fieldname = self.parse_ident()?; | ||
4313 | hi = self.prev_span; | ||
4314 | |||
4315 | let bind_type = match (is_ref, is_mut) { | ||
4316 | (true, true) => BindingMode::ByRef(Mutability::Mutable), | ||
4317 | (true, false) => BindingMode::ByRef(Mutability::Immutable), | ||
4318 | (false, true) => BindingMode::ByValue(Mutability::Mutable), | ||
4319 | (false, false) => BindingMode::ByValue(Mutability::Immutable), | ||
4320 | }; | ||
4321 | let fieldpat = P(Pat { | ||
4322 | id: ast::DUMMY_NODE_ID, | ||
4323 | node: PatKind::Ident(bind_type, fieldname, None), | ||
4324 | span: boxed_span.to(hi), | ||
4325 | }); | ||
4326 | |||
4327 | let subpat = if is_box { | ||
4328 | P(Pat { | ||
4329 | id: ast::DUMMY_NODE_ID, | ||
4330 | node: PatKind::Box(fieldpat), | ||
4331 | span: lo.to(hi), | ||
4332 | }) | ||
4333 | } else { | ||
4334 | fieldpat | ||
4335 | }; | ||
4336 | (subpat, fieldname, true) | ||
4337 | }; | ||
4338 | |||
4339 | Ok(source_map::Spanned { | ||
4340 | span: lo.to(hi), | ||
4341 | node: ast::FieldPat { | ||
4342 | ident: fieldname, | ||
4343 | pat: subpat, | ||
4344 | is_shorthand, | ||
4345 | attrs: attrs.into(), | ||
4346 | } | ||
4347 | }) | ||
4348 | } | ||
4349 | |||
4350 | /// Parses the fields of a struct-like pattern. | ||
4351 | fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<source_map::Spanned<ast::FieldPat>>, bool)> { | ||
4352 | let mut fields = Vec::new(); | ||
4353 | let mut etc = false; | ||
4354 | let mut ate_comma = true; | ||
4355 | let mut delayed_err: Option<DiagnosticBuilder<'a>> = None; | ||
4356 | let mut etc_span = None; | ||
4357 | |||
4358 | while self.token != token::CloseDelim(token::Brace) { | ||
4359 | let attrs = self.parse_outer_attributes()?; | ||
4360 | let lo = self.span; | ||
4361 | |||
4362 | // check that a comma comes after every field | ||
4363 | if !ate_comma { | ||
4364 | let err = self.struct_span_err(self.prev_span, "expected `,`"); | ||
4365 | if let Some(mut delayed) = delayed_err { | ||
4366 | delayed.emit(); | ||
4367 | } | ||
4368 | return Err(err); | ||
4369 | } | ||
4370 | ate_comma = false; | ||
4371 | |||
4372 | if self.check(&token::DotDot) || self.token == token::DotDotDot { | ||
4373 | etc = true; | ||
4374 | let mut etc_sp = self.span; | ||
4375 | |||
4376 | if self.token == token::DotDotDot { // Issue #46718 | ||
4377 | // Accept `...` as if it were `..` to avoid further errors | ||
4378 | let mut err = self.struct_span_err(self.span, | ||
4379 | "expected field pattern, found `...`"); | ||
4380 | err.span_suggestion( | ||
4381 | self.span, | ||
4382 | "to omit remaining fields, use one fewer `.`", | ||
4383 | "..".to_owned(), | ||
4384 | Applicability::MachineApplicable | ||
4385 | ); | ||
4386 | err.emit(); | ||
4387 | } | ||
4388 | self.bump(); // `..` || `...` | ||
4389 | |||
4390 | if self.token == token::CloseDelim(token::Brace) { | ||
4391 | etc_span = Some(etc_sp); | ||
4392 | break; | ||
4393 | } | ||
4394 | let token_str = self.this_token_descr(); | ||
4395 | let mut err = self.fatal(&format!("expected `}}`, found {}", token_str)); | ||
4396 | |||
4397 | err.span_label(self.span, "expected `}`"); | ||
4398 | let mut comma_sp = None; | ||
4399 | if self.token == token::Comma { // Issue #49257 | ||
4400 | etc_sp = etc_sp.to(self.sess.source_map().span_until_non_whitespace(self.span)); | ||
4401 | err.span_label(etc_sp, | ||
4402 | "`..` must be at the end and cannot have a trailing comma"); | ||
4403 | comma_sp = Some(self.span); | ||
4404 | self.bump(); | ||
4405 | ate_comma = true; | ||
4406 | } | ||
4407 | |||
4408 | etc_span = Some(etc_sp.until(self.span)); | ||
4409 | if self.token == token::CloseDelim(token::Brace) { | ||
4410 | // If the struct looks otherwise well formed, recover and continue. | ||
4411 | if let Some(sp) = comma_sp { | ||
4412 | err.span_suggestion_short( | ||
4413 | sp, | ||
4414 | "remove this comma", | ||
4415 | String::new(), | ||
4416 | Applicability::MachineApplicable, | ||
4417 | ); | ||
4418 | } | ||
4419 | err.emit(); | ||
4420 | break; | ||
4421 | } else if self.token.is_ident() && ate_comma { | ||
4422 | // Accept fields coming after `..,`. | ||
4423 | // This way we avoid "pattern missing fields" errors afterwards. | ||
4424 | // We delay this error until the end in order to have a span for a | ||
4425 | // suggested fix. | ||
4426 | if let Some(mut delayed_err) = delayed_err { | ||
4427 | delayed_err.emit(); | ||
4428 | return Err(err); | ||
4429 | } else { | ||
4430 | delayed_err = Some(err); | ||
4431 | } | ||
4432 | } else { | ||
4433 | if let Some(mut err) = delayed_err { | ||
4434 | err.emit(); | ||
4435 | } | ||
4436 | return Err(err); | ||
4437 | } | ||
4438 | } | ||
4439 | |||
4440 | fields.push(match self.parse_pat_field(lo, attrs) { | ||
4441 | Ok(field) => field, | ||
4442 | Err(err) => { | ||
4443 | if let Some(mut delayed_err) = delayed_err { | ||
4444 | delayed_err.emit(); | ||
4445 | } | ||
4446 | return Err(err); | ||
4447 | } | ||
4448 | }); | ||
4449 | ate_comma = self.eat(&token::Comma); | ||
4450 | } | ||
4451 | |||
4452 | if let Some(mut err) = delayed_err { | ||
4453 | if let Some(etc_span) = etc_span { | ||
4454 | err.multipart_suggestion( | ||
4455 | "move the `..` to the end of the field list", | ||
4456 | vec![ | ||
4457 | (etc_span, String::new()), | ||
4458 | (self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })), | ||
4459 | ], | ||
4460 | Applicability::MachineApplicable, | ||
4461 | ); | ||
4462 | } | ||
4463 | err.emit(); | ||
4464 | } | ||
4465 | return Ok((fields, etc)); | ||
4466 | } | ||
4467 | |||
4468 | fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> { | ||
4469 | if self.token.is_path_start() { | ||
4470 | let lo = self.span; | ||
4471 | let (qself, path) = if self.eat_lt() { | ||
4472 | // Parse a qualified path | ||
4473 | let (qself, path) = self.parse_qpath(PathStyle::Expr)?; | ||
4474 | (Some(qself), path) | ||
4475 | } else { | ||
4476 | // Parse an unqualified path | ||
4477 | (None, self.parse_path(PathStyle::Expr)?) | ||
4478 | }; | ||
4479 | let hi = self.prev_span; | ||
4480 | Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path), ThinVec::new())) | ||
4481 | } else { | ||
4482 | self.parse_literal_maybe_minus() | ||
4483 | } | ||
4484 | } | ||
4485 | |||
4486 | // helper function to decide whether to parse as ident binding or to try to do | ||
4487 | // something more complex like range patterns | ||
4488 | fn parse_as_ident(&mut self) -> bool { | ||
4489 | self.look_ahead(1, |t| match *t { | ||
4490 | token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) | | ||
4491 | token::DotDotDot | token::DotDotEq | token::ModSep | token::Not => Some(false), | ||
4492 | // ensure slice patterns [a, b.., c] and [a, b, c..] don't go into the | ||
4493 | // range pattern branch | ||
4494 | token::DotDot => None, | ||
4495 | _ => Some(true), | ||
4496 | }).unwrap_or_else(|| self.look_ahead(2, |t| match *t { | ||
4497 | token::Comma | token::CloseDelim(token::Bracket) => true, | ||
4498 | _ => false, | ||
4499 | })) | ||
4500 | } | ||
4501 | |||
4502 | /// A wrapper around `parse_pat` with some special error handling for the | ||
4503 | /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast | ||
4504 | /// to subpatterns within such). | ||
4505 | fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> { | ||
4506 | let pat = self.parse_pat(None)?; | ||
4507 | if self.token == token::Comma { | ||
4508 | // An unexpected comma after a top-level pattern is a clue that the | ||
4509 | // user (perhaps more accustomed to some other language) forgot the | ||
4510 | // parentheses in what should have been a tuple pattern; return a | ||
4511 | // suggestion-enhanced error here rather than choking on the comma | ||
4512 | // later. | ||
4513 | let comma_span = self.span; | ||
4514 | self.bump(); | ||
4515 | if let Err(mut err) = self.parse_pat_list() { | ||
4516 | // We didn't expect this to work anyway; we just wanted | ||
4517 | // to advance to the end of the comma-sequence so we know | ||
4518 | // the span to suggest parenthesizing | ||
4519 | err.cancel(); | ||
4520 | } | ||
4521 | let seq_span = pat.span.to(self.prev_span); | ||
4522 | let mut err = self.struct_span_err(comma_span, | ||
4523 | "unexpected `,` in pattern"); | ||
4524 | if let Ok(seq_snippet) = self.sess.source_map().span_to_snippet(seq_span) { | ||
4525 | err.span_suggestion( | ||
4526 | seq_span, | ||
4527 | "try adding parentheses to match on a tuple..", | ||
4528 | format!("({})", seq_snippet), | ||
4529 | Applicability::MachineApplicable | ||
4530 | ).span_suggestion( | ||
4531 | seq_span, | ||
4532 | "..or a vertical bar to match on multiple alternatives", | ||
4533 | format!("{}", seq_snippet.replace(",", " |")), | ||
4534 | Applicability::MachineApplicable | ||
4535 | ); | ||
4536 | } | ||
4537 | return Err(err); | ||
4538 | } | ||
4539 | Ok(pat) | ||
4540 | } | ||
4541 | |||
4542 | /// Parses a pattern. | ||
4543 | pub fn parse_pat(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> { | ||
4544 | self.parse_pat_with_range_pat(true, expected) | ||
4545 | } | ||
4546 | |||
4547 | /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are | ||
4548 | /// allowed). | ||
4549 | fn parse_pat_with_range_pat( | ||
4550 | &mut self, | ||
4551 | allow_range_pat: bool, | ||
4552 | expected: Option<&'static str>, | ||
4553 | ) -> PResult<'a, P<Pat>> { | ||
4554 | maybe_whole!(self, NtPat, |x| x); | ||
4555 | |||
4556 | let lo = self.span; | ||
4557 | let pat; | ||
4558 | match self.token { | ||
4559 | token::BinOp(token::And) | token::AndAnd => { | ||
4560 | // Parse &pat / &mut pat | ||
4561 | self.expect_and()?; | ||
4562 | let mutbl = self.parse_mutability(); | ||
4563 | if let token::Lifetime(ident) = self.token { | ||
4564 | let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", | ||
4565 | ident)); | ||
4566 | err.span_label(self.span, "unexpected lifetime"); | ||
4567 | return Err(err); | ||
4568 | } | ||
4569 | let subpat = self.parse_pat_with_range_pat(false, expected)?; | ||
4570 | pat = PatKind::Ref(subpat, mutbl); | ||
4571 | } | ||
4572 | token::OpenDelim(token::Paren) => { | ||
4573 | // Parse (pat,pat,pat,...) as tuple pattern | ||
4574 | let (fields, ddpos, trailing_comma) = self.parse_parenthesized_pat_list()?; | ||
4575 | pat = if fields.len() == 1 && ddpos.is_none() && !trailing_comma { | ||
4576 | PatKind::Paren(fields.into_iter().nth(0).unwrap()) | ||
4577 | } else { | ||
4578 | PatKind::Tuple(fields, ddpos) | ||
4579 | }; | ||
4580 | } | ||
4581 | token::OpenDelim(token::Bracket) => { | ||
4582 | // Parse [pat,pat,...] as slice pattern | ||
4583 | self.bump(); | ||
4584 | let (before, slice, after) = self.parse_pat_vec_elements()?; | ||
4585 | self.expect(&token::CloseDelim(token::Bracket))?; | ||
4586 | pat = PatKind::Slice(before, slice, after); | ||
4587 | } | ||
4588 | // At this point, token != &, &&, (, [ | ||
4589 | _ => if self.eat_keyword(keywords::Underscore) { | ||
4590 | // Parse _ | ||
4591 | pat = PatKind::Wild; | ||
4592 | } else if self.eat_keyword(keywords::Mut) { | ||
4593 | // Parse mut ident @ pat / mut ref ident @ pat | ||
4594 | let mutref_span = self.prev_span.to(self.span); | ||
4595 | let binding_mode = if self.eat_keyword(keywords::Ref) { | ||
4596 | self.diagnostic() | ||
4597 | .struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect") | ||
4598 | .span_suggestion( | ||
4599 | mutref_span, | ||
4600 | "try switching the order", | ||
4601 | "ref mut".into(), | ||
4602 | Applicability::MachineApplicable | ||
4603 | ).emit(); | ||
4604 | BindingMode::ByRef(Mutability::Mutable) | ||
4605 | } else { | ||
4606 | BindingMode::ByValue(Mutability::Mutable) | ||
4607 | }; | ||
4608 | pat = self.parse_pat_ident(binding_mode)?; | ||
4609 | } else if self.eat_keyword(keywords::Ref) { | ||
4610 | // Parse ref ident @ pat / ref mut ident @ pat | ||
4611 | let mutbl = self.parse_mutability(); | ||
4612 | pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?; | ||
4613 | } else if self.eat_keyword(keywords::Box) { | ||
4614 | // Parse box pat | ||
4615 | let subpat = self.parse_pat_with_range_pat(false, None)?; | ||
4616 | pat = PatKind::Box(subpat); | ||
4617 | } else if self.token.is_ident() && !self.token.is_reserved_ident() && | ||
4618 | self.parse_as_ident() { | ||
4619 | // Parse ident @ pat | ||
4620 | // This can give false positives and parse nullary enums, | ||
4621 | // they are dealt with later in resolve | ||
4622 | let binding_mode = BindingMode::ByValue(Mutability::Immutable); | ||
4623 | pat = self.parse_pat_ident(binding_mode)?; | ||
4624 | } else if self.token.is_path_start() { | ||
4625 | // Parse pattern starting with a path | ||
4626 | let (qself, path) = if self.eat_lt() { | ||
4627 | // Parse a qualified path | ||
4628 | let (qself, path) = self.parse_qpath(PathStyle::Expr)?; | ||
4629 | (Some(qself), path) | ||
4630 | } else { | ||
4631 | // Parse an unqualified path | ||
4632 | (None, self.parse_path(PathStyle::Expr)?) | ||
4633 | }; | ||
4634 | match self.token { | ||
4635 | token::Not if qself.is_none() => { | ||
4636 | // Parse macro invocation | ||
4637 | self.bump(); | ||
4638 | let (delim, tts) = self.expect_delimited_token_tree()?; | ||
4639 | let mac = respan(lo.to(self.prev_span), Mac_ { path, tts, delim }); | ||
4640 | pat = PatKind::Mac(mac); | ||
4641 | } | ||
4642 | token::DotDotDot | token::DotDotEq | token::DotDot => { | ||
4643 | let end_kind = match self.token { | ||
4644 | token::DotDot => RangeEnd::Excluded, | ||
4645 | token::DotDotDot => RangeEnd::Included(RangeSyntax::DotDotDot), | ||
4646 | token::DotDotEq => RangeEnd::Included(RangeSyntax::DotDotEq), | ||
4647 | _ => panic!("can only parse `..`/`...`/`..=` for ranges \ | ||
4648 | (checked above)"), | ||
4649 | }; | ||
4650 | let op_span = self.span; | ||
4651 | // Parse range | ||
4652 | let span = lo.to(self.prev_span); | ||
4653 | let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new()); | ||
4654 | self.bump(); | ||
4655 | let end = self.parse_pat_range_end()?; | ||
4656 | let op = Spanned { span: op_span, node: end_kind }; | ||
4657 | pat = PatKind::Range(begin, end, op); | ||
4658 | } | ||
4659 | token::OpenDelim(token::Brace) => { | ||
4660 | if qself.is_some() { | ||
4661 | let msg = "unexpected `{` after qualified path"; | ||
4662 | let mut err = self.fatal(msg); | ||
4663 | err.span_label(self.span, msg); | ||
4664 | return Err(err); | ||
4665 | } | ||
4666 | // Parse struct pattern | ||
4667 | self.bump(); | ||
4668 | let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { | ||
4669 | e.emit(); | ||
4670 | self.recover_stmt(); | ||
4671 | (vec![], false) | ||
4672 | }); | ||
4673 | self.bump(); | ||
4674 | pat = PatKind::Struct(path, fields, etc); | ||
4675 | } | ||
4676 | token::OpenDelim(token::Paren) => { | ||
4677 | if qself.is_some() { | ||
4678 | let msg = "unexpected `(` after qualified path"; | ||
4679 | let mut err = self.fatal(msg); | ||
4680 | err.span_label(self.span, msg); | ||
4681 | return Err(err); | ||
4682 | } | ||
4683 | // Parse tuple struct or enum pattern | ||
4684 | let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?; | ||
4685 | pat = PatKind::TupleStruct(path, fields, ddpos) | ||
4686 | } | ||
4687 | _ => pat = PatKind::Path(qself, path), | ||
4688 | } | ||
4689 | } else { | ||
4690 | // Try to parse everything else as literal with optional minus | ||
4691 | match self.parse_literal_maybe_minus() { | ||
4692 | Ok(begin) => { | ||
4693 | let op_span = self.span; | ||
4694 | if self.check(&token::DotDot) || self.check(&token::DotDotEq) || | ||
4695 | self.check(&token::DotDotDot) { | ||
4696 | let end_kind = if self.eat(&token::DotDotDot) { | ||
4697 | RangeEnd::Included(RangeSyntax::DotDotDot) | ||
4698 | } else if self.eat(&token::DotDotEq) { | ||
4699 | RangeEnd::Included(RangeSyntax::DotDotEq) | ||
4700 | } else if self.eat(&token::DotDot) { | ||
4701 | RangeEnd::Excluded | ||
4702 | } else { | ||
4703 | panic!("impossible case: we already matched \ | ||
4704 | on a range-operator token") | ||
4705 | }; | ||
4706 | let end = self.parse_pat_range_end()?; | ||
4707 | let op = Spanned { span: op_span, node: end_kind }; | ||
4708 | pat = PatKind::Range(begin, end, op); | ||
4709 | } else { | ||
4710 | pat = PatKind::Lit(begin); | ||
4711 | } | ||
4712 | } | ||
4713 | Err(mut err) => { | ||
4714 | self.cancel(&mut err); | ||
4715 | let expected = expected.unwrap_or("pattern"); | ||
4716 | let msg = format!( | ||
4717 | "expected {}, found {}", | ||
4718 | expected, | ||
4719 | self.this_token_descr(), | ||
4720 | ); | ||
4721 | let mut err = self.fatal(&msg); | ||
4722 | err.span_label(self.span, format!("expected {}", expected)); | ||
4723 | return Err(err); | ||
4724 | } | ||
4725 | } | ||
4726 | } | ||
4727 | } | ||
4728 | |||
4729 | let pat = Pat { node: pat, span: lo.to(self.prev_span), id: ast::DUMMY_NODE_ID }; | ||
4730 | let pat = self.maybe_recover_from_bad_qpath(pat, true)?; | ||
4731 | |||
4732 | if !allow_range_pat { | ||
4733 | match pat.node { | ||
4734 | PatKind::Range( | ||
4735 | _, _, Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. } | ||
4736 | ) => {}, | ||
4737 | PatKind::Range(..) => { | ||
4738 | let mut err = self.struct_span_err( | ||
4739 | pat.span, | ||
4740 | "the range pattern here has ambiguous interpretation", | ||
4741 | ); | ||
4742 | err.span_suggestion( | ||
4743 | pat.span, | ||
4744 | "add parentheses to clarify the precedence", | ||
4745 | format!("({})", pprust::pat_to_string(&pat)), | ||
4746 | // "ambiguous interpretation" implies that we have to be guessing | ||
4747 | Applicability::MaybeIncorrect | ||
4748 | ); | ||
4749 | return Err(err); | ||
4750 | } | ||
4751 | _ => {} | ||
4752 | } | ||
4753 | } | ||
4754 | |||
4755 | Ok(P(pat)) | ||
4756 | } | ||
4757 | |||
4758 | /// Parses `ident` or `ident @ pat`. | ||
4759 | /// used by the copy foo and ref foo patterns to give a good | ||
4760 | /// error message when parsing mistakes like `ref foo(a, b)`. | ||
4761 | fn parse_pat_ident(&mut self, | ||
4762 | binding_mode: ast::BindingMode) | ||
4763 | -> PResult<'a, PatKind> { | ||
4764 | let ident = self.parse_ident()?; | ||
4765 | let sub = if self.eat(&token::At) { | ||
4766 | Some(self.parse_pat(Some("binding pattern"))?) | ||
4767 | } else { | ||
4768 | None | ||
4769 | }; | ||
4770 | |||
4771 | // just to be friendly, if they write something like | ||
4772 | // ref Some(i) | ||
4773 | // we end up here with ( as the current token. This shortly | ||
4774 | // leads to a parse error. Note that if there is no explicit | ||
4775 | // binding mode then we do not end up here, because the lookahead | ||
4776 | // will direct us over to parse_enum_variant() | ||
4777 | if self.token == token::OpenDelim(token::Paren) { | ||
4778 | return Err(self.span_fatal( | ||
4779 | self.prev_span, | ||
4780 | "expected identifier, found enum pattern")) | ||
4781 | } | ||
4782 | |||
4783 | Ok(PatKind::Ident(binding_mode, ident, sub)) | ||
4784 | } | ||
4785 | |||
4786 | /// Parses a local variable declaration. | ||
4787 | fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> { | ||
4788 | let lo = self.prev_span; | ||
4789 | let pat = self.parse_top_level_pat()?; | ||
4790 | |||
4791 | let (err, ty) = if self.eat(&token::Colon) { | ||
4792 | // Save the state of the parser before parsing type normally, in case there is a `:` | ||
4793 | // instead of an `=` typo. | ||
4794 | let parser_snapshot_before_type = self.clone(); | ||
4795 | let colon_sp = self.prev_span; | ||
4796 | match self.parse_ty() { | ||
4797 | Ok(ty) => (None, Some(ty)), | ||
4798 | Err(mut err) => { | ||
4799 | // Rewind to before attempting to parse the type and continue parsing | ||
4800 | let parser_snapshot_after_type = self.clone(); | ||
4801 | mem::replace(self, parser_snapshot_before_type); | ||
4802 | |||
4803 | let snippet = self.sess.source_map().span_to_snippet(pat.span).unwrap(); | ||
4804 | err.span_label(pat.span, format!("while parsing the type for `{}`", snippet)); | ||
4805 | (Some((parser_snapshot_after_type, colon_sp, err)), None) | ||
4806 | } | ||
4807 | } | ||
4808 | } else { | ||
4809 | (None, None) | ||
4810 | }; | ||
4811 | let init = match (self.parse_initializer(err.is_some()), err) { | ||
4812 | (Ok(init), None) => { // init parsed, ty parsed | ||
4813 | init | ||
4814 | } | ||
4815 | (Ok(init), Some((_, colon_sp, mut err))) => { // init parsed, ty error | ||
4816 | // Could parse the type as if it were the initializer, it is likely there was a | ||
4817 | // typo in the code: `:` instead of `=`. Add suggestion and emit the error. | ||
4818 | err.span_suggestion_short( | ||
4819 | colon_sp, | ||
4820 | "use `=` if you meant to assign", | ||
4821 | "=".to_string(), | ||
4822 | Applicability::MachineApplicable | ||
4823 | ); | ||
4824 | err.emit(); | ||
4825 | // As this was parsed successfully, continue as if the code has been fixed for the | ||
4826 | // rest of the file. It will still fail due to the emitted error, but we avoid | ||
4827 | // extra noise. | ||
4828 | init | ||
4829 | } | ||
4830 | (Err(mut init_err), Some((snapshot, _, ty_err))) => { // init error, ty error | ||
4831 | init_err.cancel(); | ||
4832 | // Couldn't parse the type nor the initializer, only raise the type error and | ||
4833 | // return to the parser state before parsing the type as the initializer. | ||
4834 | // let x: <parse_error>; | ||
4835 | mem::replace(self, snapshot); | ||
4836 | return Err(ty_err); | ||
4837 | } | ||
4838 | (Err(err), None) => { // init error, ty parsed | ||
4839 | // Couldn't parse the initializer and we're not attempting to recover a failed | ||
4840 | // parse of the type, return the error. | ||
4841 | return Err(err); | ||
4842 | } | ||
4843 | }; | ||
4844 | let hi = if self.token == token::Semi { | ||
4845 | self.span | ||
4846 | } else { | ||
4847 | self.prev_span | ||
4848 | }; | ||
4849 | Ok(P(ast::Local { | ||
4850 | ty, | ||
4851 | pat, | ||
4852 | init, | ||
4853 | id: ast::DUMMY_NODE_ID, | ||
4854 | span: lo.to(hi), | ||
4855 | attrs, | ||
4856 | })) | ||
4857 | } | ||
4858 | |||
4859 | /// Parses a structure field. | ||
4860 | fn parse_name_and_ty(&mut self, | ||
4861 | lo: Span, | ||
4862 | vis: Visibility, | ||
4863 | attrs: Vec<Attribute>) | ||
4864 | -> PResult<'a, StructField> { | ||
4865 | let name = self.parse_ident()?; | ||
4866 | self.expect(&token::Colon)?; | ||
4867 | let ty = self.parse_ty()?; | ||
4868 | Ok(StructField { | ||
4869 | span: lo.to(self.prev_span), | ||
4870 | ident: Some(name), | ||
4871 | vis, | ||
4872 | id: ast::DUMMY_NODE_ID, | ||
4873 | ty, | ||
4874 | attrs, | ||
4875 | }) | ||
4876 | } | ||
4877 | |||
4878 | /// Emits an expected-item-after-attributes error. | ||
4879 | fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { | ||
4880 | let message = match attrs.last() { | ||
4881 | Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment", | ||
4882 | _ => "expected item after attributes", | ||
4883 | }; | ||
4884 | |||
4885 | let mut err = self.diagnostic().struct_span_err(self.prev_span, message); | ||
4886 | if attrs.last().unwrap().is_sugared_doc { | ||
4887 | err.span_label(self.prev_span, "this doc comment doesn't document anything"); | ||
4888 | } | ||
4889 | Err(err) | ||
4890 | } | ||
4891 | |||
4892 | /// Parse a statement. This stops just before trailing semicolons on everything but items. | ||
4893 | /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. | ||
4894 | pub fn parse_stmt(&mut self) -> PResult<'a, Option<Stmt>> { | ||
4895 | Ok(self.parse_stmt_(true)) | ||
4896 | } | ||
4897 | |||
4898 | // Eat tokens until we can be relatively sure we reached the end of the | ||
4899 | // statement. This is something of a best-effort heuristic. | ||
4900 | // | ||
4901 | // We terminate when we find an unmatched `}` (without consuming it). | ||
4902 | fn recover_stmt(&mut self) { | ||
4903 | self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) | ||
4904 | } | ||
4905 | |||
4906 | // If `break_on_semi` is `Break`, then we will stop consuming tokens after | ||
4907 | // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is | ||
4908 | // approximate - it can mean we break too early due to macros, but that | ||
4909 | // should only lead to sub-optimal recovery, not inaccurate parsing). | ||
4910 | // | ||
4911 | // If `break_on_block` is `Break`, then we will stop consuming tokens | ||
4912 | // after finding (and consuming) a brace-delimited block. | ||
4913 | fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { | ||
4914 | let mut brace_depth = 0; | ||
4915 | let mut bracket_depth = 0; | ||
4916 | let mut in_block = false; | ||
4917 | debug!("recover_stmt_ enter loop (semi={:?}, block={:?})", | ||
4918 | break_on_semi, break_on_block); | ||
4919 | loop { | ||
4920 | debug!("recover_stmt_ loop {:?}", self.token); | ||
4921 | match self.token { | ||
4922 | token::OpenDelim(token::DelimToken::Brace) => { | ||
4923 | brace_depth += 1; | ||
4924 | self.bump(); | ||
4925 | if break_on_block == BlockMode::Break && | ||
4926 | brace_depth == 1 && | ||
4927 | bracket_depth == 0 { | ||
4928 | in_block = true; | ||
4929 | } | ||
4930 | } | ||
4931 | token::OpenDelim(token::DelimToken::Bracket) => { | ||
4932 | bracket_depth += 1; | ||
4933 | self.bump(); | ||
4934 | } | ||
4935 | token::CloseDelim(token::DelimToken::Brace) => { | ||
4936 | if brace_depth == 0 { | ||
4937 | debug!("recover_stmt_ return - close delim {:?}", self.token); | ||
4938 | break; | ||
4939 | } | ||
4940 | brace_depth -= 1; | ||
4941 | self.bump(); | ||
4942 | if in_block && bracket_depth == 0 && brace_depth == 0 { | ||
4943 | debug!("recover_stmt_ return - block end {:?}", self.token); | ||
4944 | break; | ||
4945 | } | ||
4946 | } | ||
4947 | token::CloseDelim(token::DelimToken::Bracket) => { | ||
4948 | bracket_depth -= 1; | ||
4949 | if bracket_depth < 0 { | ||
4950 | bracket_depth = 0; | ||
4951 | } | ||
4952 | self.bump(); | ||
4953 | } | ||
4954 | token::Eof => { | ||
4955 | debug!("recover_stmt_ return - Eof"); | ||
4956 | break; | ||
4957 | } | ||
4958 | token::Semi => { | ||
4959 | self.bump(); | ||
4960 | if break_on_semi == SemiColonMode::Break && | ||
4961 | brace_depth == 0 && | ||
4962 | bracket_depth == 0 { | ||
4963 | debug!("recover_stmt_ return - Semi"); | ||
4964 | break; | ||
4965 | } | ||
4966 | } | ||
4967 | token::Comma => { | ||
4968 | if break_on_semi == SemiColonMode::Comma && | ||
4969 | brace_depth == 0 && | ||
4970 | bracket_depth == 0 { | ||
4971 | debug!("recover_stmt_ return - Semi"); | ||
4972 | break; | ||
4973 | } else { | ||
4974 | self.bump(); | ||
4975 | } | ||
4976 | } | ||
4977 | _ => { | ||
4978 | self.bump() | ||
4979 | } | ||
4980 | } | ||
4981 | } | ||
4982 | } | ||
4983 | |||
4984 | fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> { | ||
4985 | self.parse_stmt_without_recovery(macro_legacy_warnings).unwrap_or_else(|mut e| { | ||
4986 | e.emit(); | ||
4987 | self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); | ||
4988 | None | ||
4989 | }) | ||
4990 | } | ||
4991 | |||
4992 | fn is_async_block(&mut self) -> bool { | ||
4993 | self.token.is_keyword(keywords::Async) && | ||
4994 | ( | ||
4995 | ( // `async move {` | ||
4996 | self.look_ahead(1, |t| t.is_keyword(keywords::Move)) && | ||
4997 | self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) | ||
4998 | ) || ( // `async {` | ||
4999 | self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) | ||
5000 | ) | ||
5001 | ) | ||
5002 | } | ||
5003 | |||
5004 | fn is_do_catch_block(&mut self) -> bool { | ||
5005 | self.token.is_keyword(keywords::Do) && | ||
5006 | self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) && | ||
5007 | self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) && | ||
5008 | !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) | ||
5009 | } | ||
5010 | |||
5011 | fn is_try_block(&mut self) -> bool { | ||
5012 | self.token.is_keyword(keywords::Try) && | ||
5013 | self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) && | ||
5014 | self.span.rust_2018() && | ||
5015 | // prevent `while try {} {}`, `if try {} {} else {}`, etc. | ||
5016 | !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) | ||
5017 | } | ||
5018 | |||
5019 | fn is_union_item(&self) -> bool { | ||
5020 | self.token.is_keyword(keywords::Union) && | ||
5021 | self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) | ||
5022 | } | ||
5023 | |||
5024 | fn is_crate_vis(&self) -> bool { | ||
5025 | self.token.is_keyword(keywords::Crate) && self.look_ahead(1, |t| t != &token::ModSep) | ||
5026 | } | ||
5027 | |||
5028 | fn is_existential_type_decl(&self) -> bool { | ||
5029 | self.token.is_keyword(keywords::Existential) && | ||
5030 | self.look_ahead(1, |t| t.is_keyword(keywords::Type)) | ||
5031 | } | ||
5032 | |||
5033 | fn is_auto_trait_item(&mut self) -> bool { | ||
5034 | // auto trait | ||
5035 | (self.token.is_keyword(keywords::Auto) | ||
5036 | && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))) | ||
5037 | || // unsafe auto trait | ||
5038 | (self.token.is_keyword(keywords::Unsafe) && | ||
5039 | self.look_ahead(1, |t| t.is_keyword(keywords::Auto)) && | ||
5040 | self.look_ahead(2, |t| t.is_keyword(keywords::Trait))) | ||
5041 | } | ||
5042 | |||
5043 | fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span) | ||
5044 | -> PResult<'a, Option<P<Item>>> { | ||
5045 | let token_lo = self.span; | ||
5046 | let (ident, def) = match self.token { | ||
5047 | token::Ident(ident, false) if ident.name == keywords::Macro.name() => { | ||
5048 | self.bump(); | ||
5049 | let ident = self.parse_ident()?; | ||
5050 | let tokens = if self.check(&token::OpenDelim(token::Brace)) { | ||
5051 | match self.parse_token_tree() { | ||
5052 | TokenTree::Delimited(_, _, tts) => tts, | ||
5053 | _ => unreachable!(), | ||
5054 | } | ||
5055 | } else if self.check(&token::OpenDelim(token::Paren)) { | ||
5056 | let args = self.parse_token_tree(); | ||
5057 | let body = if self.check(&token::OpenDelim(token::Brace)) { | ||
5058 | self.parse_token_tree() | ||
5059 | } else { | ||
5060 | self.unexpected()?; | ||
5061 | unreachable!() | ||
5062 | }; | ||
5063 | TokenStream::new(vec![ | ||
5064 | args.into(), | ||
5065 | TokenTree::Token(token_lo.to(self.prev_span), token::FatArrow).into(), | ||
5066 | body.into(), | ||
5067 | ]) | ||
5068 | } else { | ||
5069 | self.unexpected()?; | ||
5070 | unreachable!() | ||
5071 | }; | ||
5072 | |||
5073 | (ident, ast::MacroDef { tokens: tokens.into(), legacy: false }) | ||
5074 | } | ||
5075 | token::Ident(ident, _) if ident.name == "macro_rules" && | ||
5076 | self.look_ahead(1, |t| *t == token::Not) => { | ||
5077 | let prev_span = self.prev_span; | ||
5078 | self.complain_if_pub_macro(&vis.node, prev_span); | ||
5079 | self.bump(); | ||
5080 | self.bump(); | ||
5081 | |||
5082 | let ident = self.parse_ident()?; | ||
5083 | let (delim, tokens) = self.expect_delimited_token_tree()?; | ||
5084 | if delim != MacDelimiter::Brace { | ||
5085 | if !self.eat(&token::Semi) { | ||
5086 | let msg = "macros that expand to items must either \ | ||
5087 | be surrounded with braces or followed by a semicolon"; | ||
5088 | self.span_err(self.prev_span, msg); | ||
5089 | } | ||
5090 | } | ||
5091 | |||
5092 | (ident, ast::MacroDef { tokens: tokens, legacy: true }) | ||
5093 | } | ||
5094 | _ => return Ok(None), | ||
5095 | }; | ||
5096 | |||
5097 | let span = lo.to(self.prev_span); | ||
5098 | Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec()))) | ||
5099 | } | ||
5100 | |||
5101 | fn parse_stmt_without_recovery(&mut self, | ||
5102 | macro_legacy_warnings: bool) | ||
5103 | -> PResult<'a, Option<Stmt>> { | ||
5104 | maybe_whole!(self, NtStmt, |x| Some(x)); | ||
5105 | |||
5106 | let attrs = self.parse_outer_attributes()?; | ||
5107 | let lo = self.span; | ||
5108 | |||
5109 | Ok(Some(if self.eat_keyword(keywords::Let) { | ||
5110 | Stmt { | ||
5111 | id: ast::DUMMY_NODE_ID, | ||
5112 | node: StmtKind::Local(self.parse_local(attrs.into())?), | ||
5113 | span: lo.to(self.prev_span), | ||
5114 | } | ||
5115 | } else if let Some(macro_def) = self.eat_macro_def( | ||
5116 | &attrs, | ||
5117 | &source_map::respan(lo, VisibilityKind::Inherited), | ||
5118 | lo, | ||
5119 | )? { | ||
5120 | Stmt { | ||
5121 | id: ast::DUMMY_NODE_ID, | ||
5122 | node: StmtKind::Item(macro_def), | ||
5123 | span: lo.to(self.prev_span), | ||
5124 | } | ||
5125 | // Starts like a simple path, being careful to avoid contextual keywords | ||
5126 | // such as a union items, item with `crate` visibility or auto trait items. | ||
5127 | // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts | ||
5128 | // like a path (1 token), but it fact not a path. | ||
5129 | // `union::b::c` - path, `union U { ... }` - not a path. | ||
5130 | // `crate::b::c` - path, `crate struct S;` - not a path. | ||
5131 | } else if self.token.is_path_start() && | ||
5132 | !self.token.is_qpath_start() && | ||
5133 | !self.is_union_item() && | ||
5134 | !self.is_crate_vis() && | ||
5135 | !self.is_existential_type_decl() && | ||
5136 | !self.is_auto_trait_item() { | ||
5137 | let pth = self.parse_path(PathStyle::Expr)?; | ||
5138 | |||
5139 | if !self.eat(&token::Not) { | ||
5140 | let expr = if self.check(&token::OpenDelim(token::Brace)) { | ||
5141 | self.parse_struct_expr(lo, pth, ThinVec::new())? | ||
5142 | } else { | ||
5143 | let hi = self.prev_span; | ||
5144 | self.mk_expr(lo.to(hi), ExprKind::Path(None, pth), ThinVec::new()) | ||
5145 | }; | ||
5146 | |||
5147 | let expr = self.with_res(Restrictions::STMT_EXPR, |this| { | ||
5148 | let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?; | ||
5149 | this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr)) | ||
5150 | })?; | ||
5151 | |||
5152 | return Ok(Some(Stmt { | ||
5153 | id: ast::DUMMY_NODE_ID, | ||
5154 | node: StmtKind::Expr(expr), | ||
5155 | span: lo.to(self.prev_span), | ||
5156 | })); | ||
5157 | } | ||
5158 | |||
5159 | // it's a macro invocation | ||
5160 | let id = match self.token { | ||
5161 | token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier | ||
5162 | _ => self.parse_ident()?, | ||
5163 | }; | ||
5164 | |||
5165 | // check that we're pointing at delimiters (need to check | ||
5166 | // again after the `if`, because of `parse_ident` | ||
5167 | // consuming more tokens). | ||
5168 | match self.token { | ||
5169 | token::OpenDelim(_) => {} | ||
5170 | _ => { | ||
5171 | // we only expect an ident if we didn't parse one | ||
5172 | // above. | ||
5173 | let ident_str = if id.name == keywords::Invalid.name() { | ||
5174 | "identifier, " | ||
5175 | } else { | ||
5176 | "" | ||
5177 | }; | ||
5178 | let tok_str = self.this_token_descr(); | ||
5179 | let mut err = self.fatal(&format!("expected {}`(` or `{{`, found {}", | ||
5180 | ident_str, | ||
5181 | tok_str)); | ||
5182 | err.span_label(self.span, format!("expected {}`(` or `{{`", ident_str)); | ||
5183 | return Err(err) | ||
5184 | }, | ||
5185 | } | ||
5186 | |||
5187 | let (delim, tts) = self.expect_delimited_token_tree()?; | ||
5188 | let hi = self.prev_span; | ||
5189 | |||
5190 | let style = if delim == MacDelimiter::Brace { | ||
5191 | MacStmtStyle::Braces | ||
5192 | } else { | ||
5193 | MacStmtStyle::NoBraces | ||
5194 | }; | ||
5195 | |||
5196 | if id.name == keywords::Invalid.name() { | ||
5197 | let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim }); | ||
5198 | let node = if delim == MacDelimiter::Brace || | ||
5199 | self.token == token::Semi || self.token == token::Eof { | ||
5200 | StmtKind::Mac(P((mac, style, attrs.into()))) | ||
5201 | } | ||
5202 | // We used to incorrectly stop parsing macro-expanded statements here. | ||
5203 | // If the next token will be an error anyway but could have parsed with the | ||
5204 | // earlier behavior, stop parsing here and emit a warning to avoid breakage. | ||
5205 | else if macro_legacy_warnings && self.token.can_begin_expr() && match self.token { | ||
5206 | // These can continue an expression, so we can't stop parsing and warn. | ||
5207 | token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) | | ||
5208 | token::BinOp(token::Minus) | token::BinOp(token::Star) | | ||
5209 | token::BinOp(token::And) | token::BinOp(token::Or) | | ||
5210 | token::AndAnd | token::OrOr | | ||
5211 | token::DotDot | token::DotDotDot | token::DotDotEq => false, | ||
5212 | _ => true, | ||
5213 | } { | ||
5214 | self.warn_missing_semicolon(); | ||
5215 | StmtKind::Mac(P((mac, style, attrs.into()))) | ||
5216 | } else { | ||
5217 | let e = self.mk_mac_expr(lo.to(hi), mac.node, ThinVec::new()); | ||
5218 | let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?; | ||
5219 | let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; | ||
5220 | StmtKind::Expr(e) | ||
5221 | }; | ||
5222 | Stmt { | ||
5223 | id: ast::DUMMY_NODE_ID, | ||
5224 | span: lo.to(hi), | ||
5225 | node, | ||
5226 | } | ||
5227 | } else { | ||
5228 | // if it has a special ident, it's definitely an item | ||
5229 | // | ||
5230 | // Require a semicolon or braces. | ||
5231 | if style != MacStmtStyle::Braces { | ||
5232 | if !self.eat(&token::Semi) { | ||
5233 | self.span_err(self.prev_span, | ||
5234 | "macros that expand to items must \ | ||
5235 | either be surrounded with braces or \ | ||
5236 | followed by a semicolon"); | ||
5237 | } | ||
5238 | } | ||
5239 | let span = lo.to(hi); | ||
5240 | Stmt { | ||
5241 | id: ast::DUMMY_NODE_ID, | ||
5242 | span, | ||
5243 | node: StmtKind::Item({ | ||
5244 | self.mk_item( | ||
5245 | span, id /*id is good here*/, | ||
5246 | ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })), | ||
5247 | respan(lo, VisibilityKind::Inherited), | ||
5248 | attrs) | ||
5249 | }), | ||
5250 | } | ||
5251 | } | ||
5252 | } else { | ||
5253 | // FIXME: Bad copy of attrs | ||
5254 | let old_directory_ownership = | ||
5255 | mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); | ||
5256 | let item = self.parse_item_(attrs.clone(), false, true)?; | ||
5257 | self.directory.ownership = old_directory_ownership; | ||
5258 | |||
5259 | match item { | ||
5260 | Some(i) => Stmt { | ||
5261 | id: ast::DUMMY_NODE_ID, | ||
5262 | span: lo.to(i.span), | ||
5263 | node: StmtKind::Item(i), | ||
5264 | }, | ||
5265 | None => { | ||
5266 | let unused_attrs = |attrs: &[Attribute], s: &mut Self| { | ||
5267 | if !attrs.is_empty() { | ||
5268 | if s.prev_token_kind == PrevTokenKind::DocComment { | ||
5269 | s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit(); | ||
5270 | } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) { | ||
5271 | s.span_err(s.span, "expected statement after outer attribute"); | ||
5272 | } | ||
5273 | } | ||
5274 | }; | ||
5275 | |||
5276 | // Do not attempt to parse an expression if we're done here. | ||
5277 | if self.token == token::Semi { | ||
5278 | unused_attrs(&attrs, self); | ||
5279 | self.bump(); | ||
5280 | return Ok(None); | ||
5281 | } | ||
5282 | |||
5283 | if self.token == token::CloseDelim(token::Brace) { | ||
5284 | unused_attrs(&attrs, self); | ||
5285 | return Ok(None); | ||
5286 | } | ||
5287 | |||
5288 | // Remainder are line-expr stmts. | ||
5289 | let e = self.parse_expr_res( | ||
5290 | Restrictions::STMT_EXPR, Some(attrs.into()))?; | ||
5291 | Stmt { | ||
5292 | id: ast::DUMMY_NODE_ID, | ||
5293 | span: lo.to(e.span), | ||
5294 | node: StmtKind::Expr(e), | ||
5295 | } | ||
5296 | } | ||
5297 | } | ||
5298 | })) | ||
5299 | } | ||
5300 | |||
5301 | /// Checks if this expression is a successfully parsed statement. | ||
5302 | fn expr_is_complete(&mut self, e: &Expr) -> bool { | ||
5303 | self.restrictions.contains(Restrictions::STMT_EXPR) && | ||
5304 | !classify::expr_requires_semi_to_be_stmt(e) | ||
5305 | } | ||
5306 | |||
5307 | /// Parses a block. No inner attributes are allowed. | ||
5308 | pub fn parse_block(&mut self) -> PResult<'a, P<Block>> { | ||
5309 | maybe_whole!(self, NtBlock, |x| x); | ||
5310 | |||
5311 | let lo = self.span; | ||
5312 | |||
5313 | if !self.eat(&token::OpenDelim(token::Brace)) { | ||
5314 | let sp = self.span; | ||
5315 | let tok = self.this_token_descr(); | ||
5316 | let mut e = self.span_fatal(sp, &format!("expected `{{`, found {}", tok)); | ||
5317 | let do_not_suggest_help = | ||
5318 | self.token.is_keyword(keywords::In) || self.token == token::Colon; | ||
5319 | |||
5320 | if self.token.is_ident_named("and") { | ||
5321 | e.span_suggestion_short( | ||
5322 | self.span, | ||
5323 | "use `&&` instead of `and` for the boolean operator", | ||
5324 | "&&".to_string(), | ||
5325 | Applicability::MaybeIncorrect, | ||
5326 | ); | ||
5327 | } | ||
5328 | if self.token.is_ident_named("or") { | ||
5329 | e.span_suggestion_short( | ||
5330 | self.span, | ||
5331 | "use `||` instead of `or` for the boolean operator", | ||
5332 | "||".to_string(), | ||
5333 | Applicability::MaybeIncorrect, | ||
5334 | ); | ||
5335 | } | ||
5336 | |||
5337 | // Check to see if the user has written something like | ||
5338 | // | ||
5339 | // if (cond) | ||
5340 | // bar; | ||
5341 | // | ||
5342 | // Which is valid in other languages, but not Rust. | ||
5343 | match self.parse_stmt_without_recovery(false) { | ||
5344 | Ok(Some(stmt)) => { | ||
5345 | if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) | ||
5346 | || do_not_suggest_help { | ||
5347 | // if the next token is an open brace (e.g., `if a b {`), the place- | ||
5348 | // inside-a-block suggestion would be more likely wrong than right | ||
5349 | e.span_label(sp, "expected `{`"); | ||
5350 | return Err(e); | ||
5351 | } | ||
5352 | let mut stmt_span = stmt.span; | ||
5353 | // expand the span to include the semicolon, if it exists | ||
5354 | if self.eat(&token::Semi) { | ||
5355 | stmt_span = stmt_span.with_hi(self.prev_span.hi()); | ||
5356 | } | ||
5357 | let sugg = pprust::to_string(|s| { | ||
5358 | use crate::print::pprust::{PrintState, INDENT_UNIT}; | ||
5359 | s.ibox(INDENT_UNIT)?; | ||
5360 | s.bopen()?; | ||
5361 | s.print_stmt(&stmt)?; | ||
5362 | s.bclose_maybe_open(stmt.span, INDENT_UNIT, false) | ||
5363 | }); | ||
5364 | e.span_suggestion( | ||
5365 | stmt_span, | ||
5366 | "try placing this code inside a block", | ||
5367 | sugg, | ||
5368 | // speculative, has been misleading in the past (closed Issue #46836) | ||
5369 | Applicability::MaybeIncorrect | ||
5370 | ); | ||
5371 | } | ||
5372 | Err(mut e) => { | ||
5373 | self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); | ||
5374 | self.cancel(&mut e); | ||
5375 | } | ||
5376 | _ => () | ||
5377 | } | ||
5378 | e.span_label(sp, "expected `{`"); | ||
5379 | return Err(e); | ||
5380 | } | ||
5381 | |||
5382 | self.parse_block_tail(lo, BlockCheckMode::Default) | ||
5383 | } | ||
5384 | |||
5385 | /// Parses a block. Inner attributes are allowed. | ||
5386 | fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec<Attribute>, P<Block>)> { | ||
5387 | maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); | ||
5388 | |||
5389 | let lo = self.span; | ||
5390 | self.expect(&token::OpenDelim(token::Brace))?; | ||
5391 | Ok((self.parse_inner_attributes()?, | ||
5392 | self.parse_block_tail(lo, BlockCheckMode::Default)?)) | ||
5393 | } | ||
5394 | |||
5395 | /// Parses the rest of a block expression or function body. | ||
5396 | /// Precondition: already parsed the '{'. | ||
5397 | fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P<Block>> { | ||
5398 | let mut stmts = vec![]; | ||
5399 | while !self.eat(&token::CloseDelim(token::Brace)) { | ||
5400 | let stmt = match self.parse_full_stmt(false) { | ||
5401 | Err(mut err) => { | ||
5402 | err.emit(); | ||
5403 | self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); | ||
5404 | Some(Stmt { | ||
5405 | id: ast::DUMMY_NODE_ID, | ||
5406 | node: StmtKind::Expr(DummyResult::raw_expr(self.span, true)), | ||
5407 | span: self.span, | ||
5408 | }) | ||
5409 | } | ||
5410 | Ok(stmt) => stmt, | ||
5411 | }; | ||
5412 | if let Some(stmt) = stmt { | ||
5413 | stmts.push(stmt); | ||
5414 | } else if self.token == token::Eof { | ||
5415 | break; | ||
5416 | } else { | ||
5417 | // Found only `;` or `}`. | ||
5418 | continue; | ||
5419 | }; | ||
5420 | } | ||
5421 | Ok(P(ast::Block { | ||
5422 | stmts, | ||
5423 | id: ast::DUMMY_NODE_ID, | ||
5424 | rules: s, | ||
5425 | span: lo.to(self.prev_span), | ||
5426 | })) | ||
5427 | } | ||
5428 | |||
5429 | /// Parses a statement, including the trailing semicolon. | ||
5430 | crate fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option<Stmt>> { | ||
5431 | // skip looking for a trailing semicolon when we have an interpolated statement | ||
5432 | maybe_whole!(self, NtStmt, |x| Some(x)); | ||
5433 | |||
5434 | let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? { | ||
5435 | Some(stmt) => stmt, | ||
5436 | None => return Ok(None), | ||
5437 | }; | ||
5438 | |||
5439 | match stmt.node { | ||
5440 | StmtKind::Expr(ref expr) if self.token != token::Eof => { | ||
5441 | // expression without semicolon | ||
5442 | if classify::expr_requires_semi_to_be_stmt(expr) { | ||
5443 | // Just check for errors and recover; do not eat semicolon yet. | ||
5444 | if let Err(mut e) = | ||
5445 | self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)]) | ||
5446 | { | ||
5447 | e.emit(); | ||
5448 | self.recover_stmt(); | ||
5449 | } | ||
5450 | } | ||
5451 | } | ||
5452 | StmtKind::Local(..) => { | ||
5453 | // We used to incorrectly allow a macro-expanded let statement to lack a semicolon. | ||
5454 | if macro_legacy_warnings && self.token != token::Semi { | ||
5455 | self.warn_missing_semicolon(); | ||
5456 | } else { | ||
5457 | self.expect_one_of(&[], &[token::Semi])?; | ||
5458 | } | ||
5459 | } | ||
5460 | _ => {} | ||
5461 | } | ||
5462 | |||
5463 | if self.eat(&token::Semi) { | ||
5464 | stmt = stmt.add_trailing_semicolon(); | ||
5465 | } | ||
5466 | |||
5467 | stmt.span = stmt.span.with_hi(self.prev_span.hi()); | ||
5468 | Ok(Some(stmt)) | ||
5469 | } | ||
5470 | |||
5471 | fn warn_missing_semicolon(&self) { | ||
5472 | self.diagnostic().struct_span_warn(self.span, { | ||
5473 | &format!("expected `;`, found {}", self.this_token_descr()) | ||
5474 | }).note({ | ||
5475 | "This was erroneously allowed and will become a hard error in a future release" | ||
5476 | }).emit(); | ||
5477 | } | ||
5478 | |||
5479 | fn err_dotdotdot_syntax(&self, span: Span) { | ||
5480 | self.diagnostic().struct_span_err(span, { | ||
5481 | "unexpected token: `...`" | ||
5482 | }).span_suggestion( | ||
5483 | span, "use `..` for an exclusive range", "..".to_owned(), | ||
5484 | Applicability::MaybeIncorrect | ||
5485 | ).span_suggestion( | ||
5486 | span, "or `..=` for an inclusive range", "..=".to_owned(), | ||
5487 | Applicability::MaybeIncorrect | ||
5488 | ).emit(); | ||
5489 | } | ||
5490 | |||
5491 | /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`. | ||
5492 | /// | ||
5493 | /// ``` | ||
5494 | /// BOUND = TY_BOUND | LT_BOUND | ||
5495 | /// LT_BOUND = LIFETIME (e.g., `'a`) | ||
5496 | /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) | ||
5497 | /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`) | ||
5498 | /// ``` | ||
5499 | fn parse_generic_bounds_common(&mut self, | ||
5500 | allow_plus: bool, | ||
5501 | colon_span: Option<Span>) -> PResult<'a, GenericBounds> { | ||
5502 | let mut bounds = Vec::new(); | ||
5503 | let mut negative_bounds = Vec::new(); | ||
5504 | let mut last_plus_span = None; | ||
5505 | loop { | ||
5506 | // This needs to be synchronized with `Token::can_begin_bound`. | ||
5507 | let is_bound_start = self.check_path() || self.check_lifetime() || | ||
5508 | self.check(&token::Not) || // used for error reporting only | ||
5509 | self.check(&token::Question) || | ||
5510 | self.check_keyword(keywords::For) || | ||
5511 | self.check(&token::OpenDelim(token::Paren)); | ||
5512 | if is_bound_start { | ||
5513 | let lo = self.span; | ||
5514 | let has_parens = self.eat(&token::OpenDelim(token::Paren)); | ||
5515 | let inner_lo = self.span; | ||
5516 | let is_negative = self.eat(&token::Not); | ||
5517 | let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None }; | ||
5518 | if self.token.is_lifetime() { | ||
5519 | if let Some(question_span) = question { | ||
5520 | self.span_err(question_span, | ||
5521 | "`?` may only modify trait bounds, not lifetime bounds"); | ||
5522 | } | ||
5523 | bounds.push(GenericBound::Outlives(self.expect_lifetime())); | ||
5524 | if has_parens { | ||
5525 | let inner_span = inner_lo.to(self.prev_span); | ||
5526 | self.expect(&token::CloseDelim(token::Paren))?; | ||
5527 | let mut err = self.struct_span_err( | ||
5528 | lo.to(self.prev_span), | ||
5529 | "parenthesized lifetime bounds are not supported" | ||
5530 | ); | ||
5531 | if let Ok(snippet) = self.sess.source_map().span_to_snippet(inner_span) { | ||
5532 | err.span_suggestion_short( | ||
5533 | lo.to(self.prev_span), | ||
5534 | "remove the parentheses", | ||
5535 | snippet.to_owned(), | ||
5536 | Applicability::MachineApplicable | ||
5537 | ); | ||
5538 | } | ||
5539 | err.emit(); | ||
5540 | } | ||
5541 | } else { | ||
5542 | let lifetime_defs = self.parse_late_bound_lifetime_defs()?; | ||
5543 | let path = self.parse_path(PathStyle::Type)?; | ||
5544 | if has_parens { | ||
5545 | self.expect(&token::CloseDelim(token::Paren))?; | ||
5546 | } | ||
5547 | let poly_span = lo.to(self.prev_span); | ||
5548 | if is_negative { | ||
5549 | negative_bounds.push( | ||
5550 | last_plus_span.or(colon_span).unwrap() | ||
5551 | .to(poly_span)); | ||
5552 | } else { | ||
5553 | let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span); | ||
5554 | let modifier = if question.is_some() { | ||
5555 | TraitBoundModifier::Maybe | ||
5556 | } else { | ||
5557 | TraitBoundModifier::None | ||
5558 | }; | ||
5559 | bounds.push(GenericBound::Trait(poly_trait, modifier)); | ||
5560 | } | ||
5561 | } | ||
5562 | } else { | ||
5563 | break | ||
5564 | } | ||
5565 | |||
5566 | if !allow_plus || !self.eat_plus() { | ||
5567 | break | ||
5568 | } else { | ||
5569 | last_plus_span = Some(self.prev_span); | ||
5570 | } | ||
5571 | } | ||
5572 | |||
5573 | if !negative_bounds.is_empty() { | ||
5574 | let plural = negative_bounds.len() > 1; | ||
5575 | let mut err = self.struct_span_err(negative_bounds, | ||
5576 | "negative trait bounds are not supported"); | ||
5577 | let bound_list = colon_span.unwrap().to(self.prev_span); | ||
5578 | let mut new_bound_list = String::new(); | ||
5579 | if !bounds.is_empty() { | ||
5580 | let mut snippets = bounds.iter().map(|bound| bound.span()) | ||
5581 | .map(|span| self.sess.source_map().span_to_snippet(span)); | ||
5582 | while let Some(Ok(snippet)) = snippets.next() { | ||
5583 | new_bound_list.push_str(" + "); | ||
5584 | new_bound_list.push_str(&snippet); | ||
5585 | } | ||
5586 | new_bound_list = new_bound_list.replacen(" +", ":", 1); | ||
5587 | } | ||
5588 | err.span_suggestion_short(bound_list, | ||
5589 | &format!("remove the trait bound{}", | ||
5590 | if plural { "s" } else { "" }), | ||
5591 | new_bound_list, | ||
5592 | Applicability::MachineApplicable); | ||
5593 | err.emit(); | ||
5594 | } | ||
5595 | |||
5596 | return Ok(bounds); | ||
5597 | } | ||
5598 | |||
5599 | fn parse_generic_bounds(&mut self, colon_span: Option<Span>) -> PResult<'a, GenericBounds> { | ||
5600 | self.parse_generic_bounds_common(true, colon_span) | ||
5601 | } | ||
5602 | |||
5603 | /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. | ||
5604 | /// | ||
5605 | /// ``` | ||
5606 | /// BOUND = LT_BOUND (e.g., `'a`) | ||
5607 | /// ``` | ||
5608 | fn parse_lt_param_bounds(&mut self) -> GenericBounds { | ||
5609 | let mut lifetimes = Vec::new(); | ||
5610 | while self.check_lifetime() { | ||
5611 | lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime())); | ||
5612 | |||
5613 | if !self.eat_plus() { | ||
5614 | break | ||
5615 | } | ||
5616 | } | ||
5617 | lifetimes | ||
5618 | } | ||
5619 | |||
5620 | /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`. | ||
5621 | fn parse_ty_param(&mut self, | ||
5622 | preceding_attrs: Vec<Attribute>) | ||
5623 | -> PResult<'a, GenericParam> { | ||
5624 | let ident = self.parse_ident()?; | ||
5625 | |||
5626 | // Parse optional colon and param bounds. | ||
5627 | let bounds = if self.eat(&token::Colon) { | ||
5628 | self.parse_generic_bounds(None)? | ||
5629 | } else { | ||
5630 | Vec::new() | ||
5631 | }; | ||
5632 | |||
5633 | let default = if self.eat(&token::Eq) { | ||
5634 | Some(self.parse_ty()?) | ||
5635 | } else { | ||
5636 | None | ||
5637 | }; | ||
5638 | |||
5639 | Ok(GenericParam { | ||
5640 | ident, | ||
5641 | id: ast::DUMMY_NODE_ID, | ||
5642 | attrs: preceding_attrs.into(), | ||
5643 | bounds, | ||
5644 | kind: GenericParamKind::Type { | ||
5645 | default, | ||
5646 | } | ||
5647 | }) | ||
5648 | } | ||
5649 | |||
5650 | /// Parses the following grammar: | ||
5651 | /// | ||
5652 | /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] | ||
5653 | fn parse_trait_item_assoc_ty(&mut self) | ||
5654 | -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> { | ||
5655 | let ident = self.parse_ident()?; | ||
5656 | let mut generics = self.parse_generics()?; | ||
5657 | |||
5658 | // Parse optional colon and param bounds. | ||
5659 | let bounds = if self.eat(&token::Colon) { | ||
5660 | self.parse_generic_bounds(None)? | ||
5661 | } else { | ||
5662 | Vec::new() | ||
5663 | }; | ||
5664 | generics.where_clause = self.parse_where_clause()?; | ||
5665 | |||
5666 | let default = if self.eat(&token::Eq) { | ||
5667 | Some(self.parse_ty()?) | ||
5668 | } else { | ||
5669 | None | ||
5670 | }; | ||
5671 | self.expect(&token::Semi)?; | ||
5672 | |||
5673 | Ok((ident, TraitItemKind::Type(bounds, default), generics)) | ||
5674 | } | ||
5675 | |||
5676 | fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> { | ||
5677 | self.expect_keyword(keywords::Const)?; | ||
5678 | let ident = self.parse_ident()?; | ||
5679 | self.expect(&token::Colon)?; | ||
5680 | let ty = self.parse_ty()?; | ||
5681 | |||
5682 | Ok(GenericParam { | ||
5683 | ident, | ||
5684 | id: ast::DUMMY_NODE_ID, | ||
5685 | attrs: preceding_attrs.into(), | ||
5686 | bounds: Vec::new(), | ||
5687 | kind: GenericParamKind::Const { | ||
5688 | ty, | ||
5689 | } | ||
5690 | }) | ||
5691 | } | ||
5692 | |||
5693 | /// Parses a (possibly empty) list of lifetime and type parameters, possibly including | ||
5694 | /// a trailing comma and erroneous trailing attributes. | ||
5695 | crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> { | ||
5696 | let mut params = Vec::new(); | ||
5697 | loop { | ||
5698 | let attrs = self.parse_outer_attributes()?; | ||
5699 | if self.check_lifetime() { | ||
5700 | let lifetime = self.expect_lifetime(); | ||
5701 | // Parse lifetime parameter. | ||
5702 | let bounds = if self.eat(&token::Colon) { | ||
5703 | self.parse_lt_param_bounds() | ||
5704 | } else { | ||
5705 | Vec::new() | ||
5706 | }; | ||
5707 | params.push(ast::GenericParam { | ||
5708 | ident: lifetime.ident, | ||
5709 | id: lifetime.id, | ||
5710 | attrs: attrs.into(), | ||
5711 | bounds, | ||
5712 | kind: ast::GenericParamKind::Lifetime, | ||
5713 | }); | ||
5714 | } else if self.check_keyword(keywords::Const) { | ||
5715 | // Parse const parameter. | ||
5716 | params.push(self.parse_const_param(attrs)?); | ||
5717 | } else if self.check_ident() { | ||
5718 | // Parse type parameter. | ||
5719 | params.push(self.parse_ty_param(attrs)?); | ||
5720 | } else { | ||
5721 | // Check for trailing attributes and stop parsing. | ||
5722 | if !attrs.is_empty() { | ||
5723 | if !params.is_empty() { | ||
5724 | self.struct_span_err( | ||
5725 | attrs[0].span, | ||
5726 | &format!("trailing attribute after generic parameter"), | ||
5727 | ) | ||
5728 | .span_label(attrs[0].span, "attributes must go before parameters") | ||
5729 | .emit(); | ||
5730 | } else { | ||
5731 | self.struct_span_err( | ||
5732 | attrs[0].span, | ||
5733 | &format!("attribute without generic parameters"), | ||
5734 | ) | ||
5735 | .span_label( | ||
5736 | attrs[0].span, | ||
5737 | "attributes are only permitted when preceding parameters", | ||
5738 | ) | ||
5739 | .emit(); | ||
5740 | } | ||
5741 | } | ||
5742 | break | ||
5743 | } | ||
5744 | |||
5745 | if !self.eat(&token::Comma) { | ||
5746 | break | ||
5747 | } | ||
5748 | } | ||
5749 | Ok(params) | ||
5750 | } | ||
5751 | |||
5752 | /// Parses a set of optional generic type parameter declarations. Where | ||
5753 | /// clauses are not parsed here, and must be added later via | ||
5754 | /// `parse_where_clause()`. | ||
5755 | /// | ||
5756 | /// matches generics = ( ) | ( < > ) | ( < typaramseq ( , )? > ) | ( < lifetimes ( , )? > ) | ||
5757 | /// | ( < lifetimes , typaramseq ( , )? > ) | ||
5758 | /// where typaramseq = ( typaram ) | ( typaram , typaramseq ) | ||
5759 | fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { | ||
5760 | maybe_whole!(self, NtGenerics, |x| x); | ||
5761 | |||
5762 | let span_lo = self.span; | ||
5763 | if self.eat_lt() { | ||
5764 | let params = self.parse_generic_params()?; | ||
5765 | self.expect_gt()?; | ||
5766 | Ok(ast::Generics { | ||
5767 | params, | ||
5768 | where_clause: WhereClause { | ||
5769 | id: ast::DUMMY_NODE_ID, | ||
5770 | predicates: Vec::new(), | ||
5771 | span: syntax_pos::DUMMY_SP, | ||
5772 | }, | ||
5773 | span: span_lo.to(self.prev_span), | ||
5774 | }) | ||
5775 | } else { | ||
5776 | Ok(ast::Generics::default()) | ||
5777 | } | ||
5778 | } | ||
5779 | |||
5780 | /// Parses generic args (within a path segment) with recovery for extra leading angle brackets. | ||
5781 | /// For the purposes of understanding the parsing logic of generic arguments, this function | ||
5782 | /// can be thought of being the same as just calling `self.parse_generic_args()` if the source | ||
5783 | /// had the correct amount of leading angle brackets. | ||
5784 | /// | ||
5785 | /// ```ignore (diagnostics) | ||
5786 | /// bar::<<<<T as Foo>::Output>(); | ||
5787 | /// ^^ help: remove extra angle brackets | ||
5788 | /// ``` | ||
5789 | fn parse_generic_args_with_leaning_angle_bracket_recovery( | ||
5790 | &mut self, | ||
5791 | style: PathStyle, | ||
5792 | lo: Span, | ||
5793 | ) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> { | ||
5794 | // We need to detect whether there are extra leading left angle brackets and produce an | ||
5795 | // appropriate error and suggestion. This cannot be implemented by looking ahead at | ||
5796 | // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens | ||
5797 | // then there won't be matching `>` tokens to find. | ||
5798 | // | ||
5799 | // To explain how this detection works, consider the following example: | ||
5800 | // | ||
5801 | // ```ignore (diagnostics) | ||
5802 | // bar::<<<<T as Foo>::Output>(); | ||
5803 | // ^^ help: remove extra angle brackets | ||
5804 | // ``` | ||
5805 | // | ||
5806 | // Parsing of the left angle brackets starts in this function. We start by parsing the | ||
5807 | // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via | ||
5808 | // `eat_lt`): | ||
5809 | // | ||
5810 | // *Upcoming tokens:* `<<<<T as Foo>::Output>;` | ||
5811 | // *Unmatched count:* 1 | ||
5812 | // *`parse_path_segment` calls deep:* 0 | ||
5813 | // | ||
5814 | // This has the effect of recursing as this function is called if a `<` character | ||
5815 | // is found within the expected generic arguments: | ||
5816 | // | ||
5817 | // *Upcoming tokens:* `<<<T as Foo>::Output>;` | ||
5818 | // *Unmatched count:* 2 | ||
5819 | // *`parse_path_segment` calls deep:* 1 | ||
5820 | // | ||
5821 | // Eventually we will have recursed until having consumed all of the `<` tokens and | ||
5822 | // this will be reflected in the count: | ||
5823 | // | ||
5824 | // *Upcoming tokens:* `T as Foo>::Output>;` | ||
5825 | // *Unmatched count:* 4 | ||
5826 | // `parse_path_segment` calls deep:* 3 | ||
5827 | // | ||
5828 | // The parser will continue until reaching the first `>` - this will decrement the | ||
5829 | // unmatched angle bracket count and return to the parent invocation of this function | ||
5830 | // having succeeded in parsing: | ||
5831 | // | ||
5832 | // *Upcoming tokens:* `::Output>;` | ||
5833 | // *Unmatched count:* 3 | ||
5834 | // *`parse_path_segment` calls deep:* 2 | ||
5835 | // | ||
5836 | // This will continue until the next `>` character which will also return successfully | ||
5837 | // to the parent invocation of this function and decrement the count: | ||
5838 | // | ||
5839 | // *Upcoming tokens:* `;` | ||
5840 | // *Unmatched count:* 2 | ||
5841 | // *`parse_path_segment` calls deep:* 1 | ||
5842 | // | ||
5843 | // At this point, this function will expect to find another matching `>` character but | ||
5844 | // won't be able to and will return an error. This will continue all the way up the | ||
5845 | // call stack until the first invocation: | ||
5846 | // | ||
5847 | // *Upcoming tokens:* `;` | ||
5848 | // *Unmatched count:* 2 | ||
5849 | // *`parse_path_segment` calls deep:* 0 | ||
5850 | // | ||
5851 | // In doing this, we have managed to work out how many unmatched leading left angle | ||
5852 | // brackets there are, but we cannot recover as the unmatched angle brackets have | ||
5853 | // already been consumed. To remedy this, we keep a snapshot of the parser state | ||
5854 | // before we do the above. We can then inspect whether we ended up with a parsing error | ||
5855 | // and unmatched left angle brackets and if so, restore the parser state before we | ||
5856 | // consumed any `<` characters to emit an error and consume the erroneous tokens to | ||
5857 | // recover by attempting to parse again. | ||
5858 | // | ||
5859 | // In practice, the recursion of this function is indirect and there will be other | ||
5860 | // locations that consume some `<` characters - as long as we update the count when | ||
5861 | // this happens, it isn't an issue. | ||
5862 | |||
5863 | let is_first_invocation = style == PathStyle::Expr; | ||
5864 | // Take a snapshot before attempting to parse - we can restore this later. | ||
5865 | let snapshot = if is_first_invocation { | ||
5866 | Some(self.clone()) | ||
5867 | } else { | ||
5868 | None | ||
5869 | }; | ||
5870 | |||
5871 | debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)"); | ||
5872 | match self.parse_generic_args() { | ||
5873 | Ok(value) => Ok(value), | ||
5874 | Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => { | ||
5875 | // Cancel error from being unable to find `>`. We know the error | ||
5876 | // must have been this due to a non-zero unmatched angle bracket | ||
5877 | // count. | ||
5878 | e.cancel(); | ||
5879 | |||
5880 | // Swap `self` with our backup of the parser state before attempting to parse | ||
5881 | // generic arguments. | ||
5882 | let snapshot = mem::replace(self, snapshot.unwrap()); | ||
5883 | |||
5884 | debug!( | ||
5885 | "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \ | ||
5886 | snapshot.count={:?}", | ||
5887 | snapshot.unmatched_angle_bracket_count, | ||
5888 | ); | ||
5889 | |||
5890 | // Eat the unmatched angle brackets. | ||
5891 | for _ in 0..snapshot.unmatched_angle_bracket_count { | ||
5892 | self.eat_lt(); | ||
5893 | } | ||
5894 | |||
5895 | // Make a span over ${unmatched angle bracket count} characters. | ||
5896 | let span = lo.with_hi( | ||
5897 | lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count) | ||
5898 | ); | ||
5899 | let plural = snapshot.unmatched_angle_bracket_count > 1; | ||
5900 | self.diagnostic() | ||
5901 | .struct_span_err( | ||
5902 | span, | ||
5903 | &format!( | ||
5904 | "unmatched angle bracket{}", | ||
5905 | if plural { "s" } else { "" } | ||
5906 | ), | ||
5907 | ) | ||
5908 | .span_suggestion( | ||
5909 | span, | ||
5910 | &format!( | ||
5911 | "remove extra angle bracket{}", | ||
5912 | if plural { "s" } else { "" } | ||
5913 | ), | ||
5914 | String::new(), | ||
5915 | Applicability::MachineApplicable, | ||
5916 | ) | ||
5917 | .emit(); | ||
5918 | |||
5919 | // Try again without unmatched angle bracket characters. | ||
5920 | self.parse_generic_args() | ||
5921 | }, | ||
5922 | Err(e) => Err(e), | ||
5923 | } | ||
5924 | } | ||
5925 | |||
5926 | /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings, | ||
5927 | /// possibly including trailing comma. | ||
5928 | fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> { | ||
5929 | let mut args = Vec::new(); | ||
5930 | let mut bindings = Vec::new(); | ||
5931 | let mut misplaced_assoc_ty_bindings: Vec<Span> = Vec::new(); | ||
5932 | let mut assoc_ty_bindings: Vec<Span> = Vec::new(); | ||
5933 | |||
5934 | let args_lo = self.span; | ||
5935 | |||
5936 | loop { | ||
5937 | if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { | ||
5938 | // Parse lifetime argument. | ||
5939 | args.push(GenericArg::Lifetime(self.expect_lifetime())); | ||
5940 | misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings); | ||
5941 | } else if self.check_ident() && self.look_ahead(1, |t| t == &token::Eq) { | ||
5942 | // Parse associated type binding. | ||
5943 | let lo = self.span; | ||
5944 | let ident = self.parse_ident()?; | ||
5945 | self.bump(); | ||
5946 | let ty = self.parse_ty()?; | ||
5947 | let span = lo.to(self.prev_span); | ||
5948 | bindings.push(TypeBinding { | ||
5949 | id: ast::DUMMY_NODE_ID, | ||
5950 | ident, | ||
5951 | ty, | ||
5952 | span, | ||
5953 | }); | ||
5954 | assoc_ty_bindings.push(span); | ||
5955 | } else if self.check_const_arg() { | ||
5956 | // FIXME(const_generics): to distinguish between idents for types and consts, | ||
5957 | // we should introduce a GenericArg::Ident in the AST and distinguish when | ||
5958 | // lowering to the HIR. For now, idents for const args are not permitted. | ||
5959 | |||
5960 | // Parse const argument. | ||
5961 | let expr = if let token::OpenDelim(token::Brace) = self.token { | ||
5962 | self.parse_block_expr(None, self.span, BlockCheckMode::Default, ThinVec::new())? | ||
5963 | } else if self.token.is_ident() { | ||
5964 | // FIXME(const_generics): to distinguish between idents for types and consts, | ||
5965 | // we should introduce a GenericArg::Ident in the AST and distinguish when | ||
5966 | // lowering to the HIR. For now, idents for const args are not permitted. | ||
5967 | return Err( | ||
5968 | self.fatal("identifiers may currently not be used for const generics") | ||
5969 | ); | ||
5970 | } else { | ||
5971 | // FIXME(const_generics): this currently conflicts with emplacement syntax | ||
5972 | // with negative integer literals. | ||
5973 | self.parse_literal_maybe_minus()? | ||
5974 | }; | ||
5975 | let value = AnonConst { | ||
5976 | id: ast::DUMMY_NODE_ID, | ||
5977 | value: expr, | ||
5978 | }; | ||
5979 | args.push(GenericArg::Const(value)); | ||
5980 | misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings); | ||
5981 | } else if self.check_type() { | ||
5982 | // Parse type argument. | ||
5983 | args.push(GenericArg::Type(self.parse_ty()?)); | ||
5984 | misplaced_assoc_ty_bindings.append(&mut assoc_ty_bindings); | ||
5985 | } else { | ||
5986 | break | ||
5987 | } | ||
5988 | |||
5989 | if !self.eat(&token::Comma) { | ||
5990 | break | ||
5991 | } | ||
5992 | } | ||
5993 | |||
5994 | // FIXME: we would like to report this in ast_validation instead, but we currently do not | ||
5995 | // preserve ordering of generic parameters with respect to associated type binding, so we | ||
5996 | // lose that information after parsing. | ||
5997 | if misplaced_assoc_ty_bindings.len() > 0 { | ||
5998 | let mut err = self.struct_span_err( | ||
5999 | args_lo.to(self.prev_span), | ||
6000 | "associated type bindings must be declared after generic parameters", | ||
6001 | ); | ||
6002 | for span in misplaced_assoc_ty_bindings { | ||
6003 | err.span_label( | ||
6004 | span, | ||
6005 | "this associated type binding should be moved after the generic parameters", | ||
6006 | ); | ||
6007 | } | ||
6008 | err.emit(); | ||
6009 | } | ||
6010 | |||
6011 | Ok((args, bindings)) | ||
6012 | } | ||
6013 | |||
6014 | /// Parses an optional where-clause and places it in `generics`. | ||
6015 | /// | ||
6016 | /// ```ignore (only-for-syntax-highlight) | ||
6017 | /// where T : Trait<U, V> + 'b, 'a : 'b | ||
6018 | /// ``` | ||
6019 | fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> { | ||
6020 | maybe_whole!(self, NtWhereClause, |x| x); | ||
6021 | |||
6022 | let mut where_clause = WhereClause { | ||
6023 | id: ast::DUMMY_NODE_ID, | ||
6024 | predicates: Vec::new(), | ||
6025 | span: syntax_pos::DUMMY_SP, | ||
6026 | }; | ||
6027 | |||
6028 | if !self.eat_keyword(keywords::Where) { | ||
6029 | return Ok(where_clause); | ||
6030 | } | ||
6031 | let lo = self.prev_span; | ||
6032 | |||
6033 | // We are considering adding generics to the `where` keyword as an alternative higher-rank | ||
6034 | // parameter syntax (as in `where<'a>` or `where<T>`. To avoid that being a breaking | ||
6035 | // change we parse those generics now, but report an error. | ||
6036 | if self.choose_generics_over_qpath() { | ||
6037 | let generics = self.parse_generics()?; | ||
6038 | self.struct_span_err( | ||
6039 | generics.span, | ||
6040 | "generic parameters on `where` clauses are reserved for future use", | ||
6041 | ) | ||
6042 | .span_label(generics.span, "currently unsupported") | ||
6043 | .emit(); | ||
6044 | } | ||
6045 | |||
6046 | loop { | ||
6047 | let lo = self.span; | ||
6048 | if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { | ||
6049 | let lifetime = self.expect_lifetime(); | ||
6050 | // Bounds starting with a colon are mandatory, but possibly empty. | ||
6051 | self.expect(&token::Colon)?; | ||
6052 | let bounds = self.parse_lt_param_bounds(); | ||
6053 | where_clause.predicates.push(ast::WherePredicate::RegionPredicate( | ||
6054 | ast::WhereRegionPredicate { | ||
6055 | span: lo.to(self.prev_span), | ||
6056 | lifetime, | ||
6057 | bounds, | ||
6058 | } | ||
6059 | )); | ||
6060 | } else if self.check_type() { | ||
6061 | // Parse optional `for<'a, 'b>`. | ||
6062 | // This `for` is parsed greedily and applies to the whole predicate, | ||
6063 | // the bounded type can have its own `for` applying only to it. | ||
6064 | // Example 1: for<'a> Trait1<'a>: Trait2<'a /*ok*/> | ||
6065 | // Example 2: (for<'a> Trait1<'a>): Trait2<'a /*not ok*/> | ||
6066 | // Example 3: for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /*ok*/, 'b /*not ok*/> | ||
6067 | let lifetime_defs = self.parse_late_bound_lifetime_defs()?; | ||
6068 | |||
6069 | // Parse type with mandatory colon and (possibly empty) bounds, | ||
6070 | // or with mandatory equality sign and the second type. | ||
6071 | let ty = self.parse_ty()?; | ||
6072 | if self.eat(&token::Colon) { | ||
6073 | let bounds = self.parse_generic_bounds(None)?; | ||
6074 | where_clause.predicates.push(ast::WherePredicate::BoundPredicate( | ||
6075 | ast::WhereBoundPredicate { | ||
6076 | span: lo.to(self.prev_span), | ||
6077 | bound_generic_params: lifetime_defs, | ||
6078 | bounded_ty: ty, | ||
6079 | bounds, | ||
6080 | } | ||
6081 | )); | ||
6082 | // FIXME: Decide what should be used here, `=` or `==`. | ||
6083 | // FIXME: We are just dropping the binders in lifetime_defs on the floor here. | ||
6084 | } else if self.eat(&token::Eq) || self.eat(&token::EqEq) { | ||
6085 | let rhs_ty = self.parse_ty()?; | ||
6086 | where_clause.predicates.push(ast::WherePredicate::EqPredicate( | ||
6087 | ast::WhereEqPredicate { | ||
6088 | span: lo.to(self.prev_span), | ||
6089 | lhs_ty: ty, | ||
6090 | rhs_ty, | ||
6091 | id: ast::DUMMY_NODE_ID, | ||
6092 | } | ||
6093 | )); | ||
6094 | } else { | ||
6095 | return self.unexpected(); | ||
6096 | } | ||
6097 | } else { | ||
6098 | break | ||
6099 | } | ||
6100 | |||
6101 | if !self.eat(&token::Comma) { | ||
6102 | break | ||
6103 | } | ||
6104 | } | ||
6105 | |||
6106 | where_clause.span = lo.to(self.prev_span); | ||
6107 | Ok(where_clause) | ||
6108 | } | ||
6109 | |||
6110 | fn parse_fn_args(&mut self, named_args: bool, allow_variadic: bool) | ||
6111 | -> PResult<'a, (Vec<Arg> , bool)> { | ||
6112 | self.expect(&token::OpenDelim(token::Paren))?; | ||
6113 | |||
6114 | let sp = self.span; | ||
6115 | let mut variadic = false; | ||
6116 | let (args, recovered): (Vec<Option<Arg>>, bool) = | ||
6117 | self.parse_seq_to_before_end( | ||
6118 | &token::CloseDelim(token::Paren), | ||
6119 | SeqSep::trailing_allowed(token::Comma), | ||
6120 | |p| { | ||
6121 | if p.token == token::DotDotDot { | ||
6122 | p.bump(); | ||
6123 | variadic = true; | ||
6124 | if allow_variadic { | ||
6125 | if p.token != token::CloseDelim(token::Paren) { | ||
6126 | let span = p.span; | ||
6127 | p.span_err(span, | ||
6128 | "`...` must be last in argument list for variadic function"); | ||
6129 | } | ||
6130 | Ok(None) | ||
6131 | } else { | ||
6132 | let span = p.prev_span; | ||
6133 | if p.token == token::CloseDelim(token::Paren) { | ||
6134 | // continue parsing to present any further errors | ||
6135 | p.struct_span_err( | ||
6136 | span, | ||
6137 | "only foreign functions are allowed to be variadic" | ||
6138 | ).emit(); | ||
6139 | Ok(Some(dummy_arg(span))) | ||
6140 | } else { | ||
6141 | // this function definition looks beyond recovery, stop parsing | ||
6142 | p.span_err(span, | ||
6143 | "only foreign functions are allowed to be variadic"); | ||
6144 | Ok(None) | ||
6145 | } | ||
6146 | } | ||
6147 | } else { | ||
6148 | match p.parse_arg_general(named_args, false) { | ||
6149 | Ok(arg) => Ok(Some(arg)), | ||
6150 | Err(mut e) => { | ||
6151 | e.emit(); | ||
6152 | let lo = p.prev_span; | ||
6153 | // Skip every token until next possible arg or end. | ||
6154 | p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); | ||
6155 | // Create a placeholder argument for proper arg count (#34264). | ||
6156 | let span = lo.to(p.prev_span); | ||
6157 | Ok(Some(dummy_arg(span))) | ||
6158 | } | ||
6159 | } | ||
6160 | } | ||
6161 | } | ||
6162 | )?; | ||
6163 | |||
6164 | if !recovered { | ||
6165 | self.eat(&token::CloseDelim(token::Paren)); | ||
6166 | } | ||
6167 | |||
6168 | let args: Vec<_> = args.into_iter().filter_map(|x| x).collect(); | ||
6169 | |||
6170 | if variadic && args.is_empty() { | ||
6171 | self.span_err(sp, | ||
6172 | "variadic function must be declared with at least one named argument"); | ||
6173 | } | ||
6174 | |||
6175 | Ok((args, variadic)) | ||
6176 | } | ||
6177 | |||
6178 | /// Parses the argument list and result type of a function declaration. | ||
6179 | fn parse_fn_decl(&mut self, allow_variadic: bool) -> PResult<'a, P<FnDecl>> { | ||
6180 | |||
6181 | let (args, variadic) = self.parse_fn_args(true, allow_variadic)?; | ||
6182 | let ret_ty = self.parse_ret_ty(true)?; | ||
6183 | |||
6184 | Ok(P(FnDecl { | ||
6185 | inputs: args, | ||
6186 | output: ret_ty, | ||
6187 | variadic, | ||
6188 | })) | ||
6189 | } | ||
6190 | |||
6191 | /// Returns the parsed optional self argument and whether a self shortcut was used. | ||
6192 | fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> { | ||
6193 | let expect_ident = |this: &mut Self| match this.token { | ||
6194 | // Preserve hygienic context. | ||
6195 | token::Ident(ident, _) => | ||
6196 | { let span = this.span; this.bump(); Ident::new(ident.name, span) } | ||
6197 | _ => unreachable!() | ||
6198 | }; | ||
6199 | let isolated_self = |this: &mut Self, n| { | ||
6200 | this.look_ahead(n, |t| t.is_keyword(keywords::SelfLower)) && | ||
6201 | this.look_ahead(n + 1, |t| t != &token::ModSep) | ||
6202 | }; | ||
6203 | |||
6204 | // Parse optional self parameter of a method. | ||
6205 | // Only a limited set of initial token sequences is considered self parameters, anything | ||
6206 | // else is parsed as a normal function parameter list, so some lookahead is required. | ||
6207 | let eself_lo = self.span; | ||
6208 | let (eself, eself_ident, eself_hi) = match self.token { | ||
6209 | token::BinOp(token::And) => { | ||
6210 | // &self | ||
6211 | // &mut self | ||
6212 | // &'lt self | ||
6213 | // &'lt mut self | ||
6214 | // ¬_self | ||
6215 | (if isolated_self(self, 1) { | ||
6216 | self.bump(); | ||
6217 | SelfKind::Region(None, Mutability::Immutable) | ||
6218 | } else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && | ||
6219 | isolated_self(self, 2) { | ||
6220 | self.bump(); | ||
6221 | self.bump(); | ||
6222 | SelfKind::Region(None, Mutability::Mutable) | ||
6223 | } else if self.look_ahead(1, |t| t.is_lifetime()) && | ||
6224 | isolated_self(self, 2) { | ||
6225 | self.bump(); | ||
6226 | let lt = self.expect_lifetime(); | ||
6227 | SelfKind::Region(Some(lt), Mutability::Immutable) | ||
6228 | } else if self.look_ahead(1, |t| t.is_lifetime()) && | ||
6229 | self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) && | ||
6230 | isolated_self(self, 3) { | ||
6231 | self.bump(); | ||
6232 | let lt = self.expect_lifetime(); | ||
6233 | self.bump(); | ||
6234 | SelfKind::Region(Some(lt), Mutability::Mutable) | ||
6235 | } else { | ||
6236 | return Ok(None); | ||
6237 | }, expect_ident(self), self.prev_span) | ||
6238 | } | ||
6239 | token::BinOp(token::Star) => { | ||
6240 | // *self | ||
6241 | // *const self | ||
6242 | // *mut self | ||
6243 | // *not_self | ||
6244 | // Emit special error for `self` cases. | ||
6245 | let msg = "cannot pass `self` by raw pointer"; | ||
6246 | (if isolated_self(self, 1) { | ||
6247 | self.bump(); | ||
6248 | self.struct_span_err(self.span, msg) | ||
6249 | .span_label(self.span, msg) | ||
6250 | .emit(); | ||
6251 | SelfKind::Value(Mutability::Immutable) | ||
6252 | } else if self.look_ahead(1, |t| t.is_mutability()) && | ||
6253 | isolated_self(self, 2) { | ||
6254 | self.bump(); | ||
6255 | self.bump(); | ||
6256 | self.struct_span_err(self.span, msg) | ||
6257 | .span_label(self.span, msg) | ||
6258 | .emit(); | ||
6259 | SelfKind::Value(Mutability::Immutable) | ||
6260 | } else { | ||
6261 | return Ok(None); | ||
6262 | }, expect_ident(self), self.prev_span) | ||
6263 | } | ||
6264 | token::Ident(..) => { | ||
6265 | if isolated_self(self, 0) { | ||
6266 | // self | ||
6267 | // self: TYPE | ||
6268 | let eself_ident = expect_ident(self); | ||
6269 | let eself_hi = self.prev_span; | ||
6270 | (if self.eat(&token::Colon) { | ||
6271 | let ty = self.parse_ty()?; | ||
6272 | SelfKind::Explicit(ty, Mutability::Immutable) | ||
6273 | } else { | ||
6274 | SelfKind::Value(Mutability::Immutable) | ||
6275 | }, eself_ident, eself_hi) | ||
6276 | } else if self.token.is_keyword(keywords::Mut) && | ||
6277 | isolated_self(self, 1) { | ||
6278 | // mut self | ||
6279 | // mut self: TYPE | ||
6280 | self.bump(); | ||
6281 | let eself_ident = expect_ident(self); | ||
6282 | let eself_hi = self.prev_span; | ||
6283 | (if self.eat(&token::Colon) { | ||
6284 | let ty = self.parse_ty()?; | ||
6285 | SelfKind::Explicit(ty, Mutability::Mutable) | ||
6286 | } else { | ||
6287 | SelfKind::Value(Mutability::Mutable) | ||
6288 | }, eself_ident, eself_hi) | ||
6289 | } else { | ||
6290 | return Ok(None); | ||
6291 | } | ||
6292 | } | ||
6293 | _ => return Ok(None), | ||
6294 | }; | ||
6295 | |||
6296 | let eself = source_map::respan(eself_lo.to(eself_hi), eself); | ||
6297 | Ok(Some(Arg::from_self(eself, eself_ident))) | ||
6298 | } | ||
6299 | |||
6300 | /// Parses the parameter list and result type of a function that may have a `self` parameter. | ||
6301 | fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDecl>> | ||
6302 | where F: FnMut(&mut Parser<'a>) -> PResult<'a, Arg>, | ||
6303 | { | ||
6304 | self.expect(&token::OpenDelim(token::Paren))?; | ||
6305 | |||
6306 | // Parse optional self argument | ||
6307 | let self_arg = self.parse_self_arg()?; | ||
6308 | |||
6309 | // Parse the rest of the function parameter list. | ||
6310 | let sep = SeqSep::trailing_allowed(token::Comma); | ||
6311 | let (fn_inputs, recovered) = if let Some(self_arg) = self_arg { | ||
6312 | if self.check(&token::CloseDelim(token::Paren)) { | ||
6313 | (vec![self_arg], false) | ||
6314 | } else if self.eat(&token::Comma) { | ||
6315 | let mut fn_inputs = vec![self_arg]; | ||
6316 | let (mut input, recovered) = self.parse_seq_to_before_end( | ||
6317 | &token::CloseDelim(token::Paren), sep, parse_arg_fn)?; | ||
6318 | fn_inputs.append(&mut input); | ||
6319 | (fn_inputs, recovered) | ||
6320 | } else { | ||
6321 | return self.unexpected(); | ||
6322 | } | ||
6323 | } else { | ||
6324 | self.parse_seq_to_before_end(&token::CloseDelim(token::Paren), sep, parse_arg_fn)? | ||
6325 | }; | ||
6326 | |||
6327 | if !recovered { | ||
6328 | // Parse closing paren and return type. | ||
6329 | self.expect(&token::CloseDelim(token::Paren))?; | ||
6330 | } | ||
6331 | Ok(P(FnDecl { | ||
6332 | inputs: fn_inputs, | ||
6333 | output: self.parse_ret_ty(true)?, | ||
6334 | variadic: false | ||
6335 | })) | ||
6336 | } | ||
6337 | |||
6338 | /// Parses the `|arg, arg|` header of a closure. | ||
6339 | fn parse_fn_block_decl(&mut self) -> PResult<'a, P<FnDecl>> { | ||
6340 | let inputs_captures = { | ||
6341 | if self.eat(&token::OrOr) { | ||
6342 | Vec::new() | ||
6343 | } else { | ||
6344 | self.expect(&token::BinOp(token::Or))?; | ||
6345 | let args = self.parse_seq_to_before_tokens( | ||
6346 | &[&token::BinOp(token::Or), &token::OrOr], | ||
6347 | SeqSep::trailing_allowed(token::Comma), | ||
6348 | TokenExpectType::NoExpect, | ||
6349 | |p| p.parse_fn_block_arg() | ||
6350 | )?.0; | ||
6351 | self.expect_or()?; | ||
6352 | args | ||
6353 | } | ||
6354 | }; | ||
6355 | let output = self.parse_ret_ty(true)?; | ||
6356 | |||
6357 | Ok(P(FnDecl { | ||
6358 | inputs: inputs_captures, | ||
6359 | output, | ||
6360 | variadic: false | ||
6361 | })) | ||
6362 | } | ||
6363 | |||
6364 | /// Parses the name and optional generic types of a function header. | ||
6365 | fn parse_fn_header(&mut self) -> PResult<'a, (Ident, ast::Generics)> { | ||
6366 | let id = self.parse_ident()?; | ||
6367 | let generics = self.parse_generics()?; | ||
6368 | Ok((id, generics)) | ||
6369 | } | ||
6370 | |||
6371 | fn mk_item(&mut self, span: Span, ident: Ident, node: ItemKind, vis: Visibility, | ||
6372 | attrs: Vec<Attribute>) -> P<Item> { | ||
6373 | P(Item { | ||
6374 | ident, | ||
6375 | attrs, | ||
6376 | id: ast::DUMMY_NODE_ID, | ||
6377 | node, | ||
6378 | vis, | ||
6379 | span, | ||
6380 | tokens: None, | ||
6381 | }) | ||
6382 | } | ||
6383 | |||
6384 | /// Parses an item-position function declaration. | ||
6385 | fn parse_item_fn(&mut self, | ||
6386 | unsafety: Unsafety, | ||
6387 | asyncness: IsAsync, | ||
6388 | constness: Spanned<Constness>, | ||
6389 | abi: Abi) | ||
6390 | -> PResult<'a, ItemInfo> { | ||
6391 | let (ident, mut generics) = self.parse_fn_header()?; | ||
6392 | let decl = self.parse_fn_decl(false)?; | ||
6393 | generics.where_clause = self.parse_where_clause()?; | ||
6394 | let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; | ||
6395 | let header = FnHeader { unsafety, asyncness, constness, abi }; | ||
6396 | Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs))) | ||
6397 | } | ||
6398 | |||
6399 | /// Returns `true` if we are looking at `const ID` | ||
6400 | /// (returns `false` for things like `const fn`, etc.). | ||
6401 | fn is_const_item(&mut self) -> bool { | ||
6402 | self.token.is_keyword(keywords::Const) && | ||
6403 | !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) && | ||
6404 | !self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) | ||
6405 | } | ||
6406 | |||
6407 | /// Parses all the "front matter" for a `fn` declaration, up to | ||
6408 | /// and including the `fn` keyword: | ||
6409 | /// | ||
6410 | /// - `const fn` | ||
6411 | /// - `unsafe fn` | ||
6412 | /// - `const unsafe fn` | ||
6413 | /// - `extern fn` | ||
6414 | /// - etc. | ||
6415 | fn parse_fn_front_matter(&mut self) | ||
6416 | -> PResult<'a, ( | ||
6417 | Spanned<Constness>, | ||
6418 | Unsafety, | ||
6419 | IsAsync, | ||
6420 | Abi | ||
6421 | )> | ||
6422 | { | ||
6423 | let is_const_fn = self.eat_keyword(keywords::Const); | ||
6424 | let const_span = self.prev_span; | ||
6425 | let unsafety = self.parse_unsafety(); | ||
6426 | let asyncness = self.parse_asyncness(); | ||
6427 | let (constness, unsafety, abi) = if is_const_fn { | ||
6428 | (respan(const_span, Constness::Const), unsafety, Abi::Rust) | ||
6429 | } else { | ||
6430 | let abi = if self.eat_keyword(keywords::Extern) { | ||
6431 | self.parse_opt_abi()?.unwrap_or(Abi::C) | ||
6432 | } else { | ||
6433 | Abi::Rust | ||
6434 | }; | ||
6435 | (respan(self.prev_span, Constness::NotConst), unsafety, abi) | ||
6436 | }; | ||
6437 | self.expect_keyword(keywords::Fn)?; | ||
6438 | Ok((constness, unsafety, asyncness, abi)) | ||
6439 | } | ||
6440 | |||
6441 | /// Parses an impl item. | ||
6442 | pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { | ||
6443 | maybe_whole!(self, NtImplItem, |x| x); | ||
6444 | let attrs = self.parse_outer_attributes()?; | ||
6445 | let (mut item, tokens) = self.collect_tokens(|this| { | ||
6446 | this.parse_impl_item_(at_end, attrs) | ||
6447 | })?; | ||
6448 | |||
6449 | // See `parse_item` for why this clause is here. | ||
6450 | if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { | ||
6451 | item.tokens = Some(tokens); | ||
6452 | } | ||
6453 | Ok(item) | ||
6454 | } | ||
6455 | |||
6456 | fn parse_impl_item_(&mut self, | ||
6457 | at_end: &mut bool, | ||
6458 | mut attrs: Vec<Attribute>) -> PResult<'a, ImplItem> { | ||
6459 | let lo = self.span; | ||
6460 | let vis = self.parse_visibility(false)?; | ||
6461 | let defaultness = self.parse_defaultness(); | ||
6462 | let (name, node, generics) = if let Some(type_) = self.eat_type() { | ||
6463 | let (name, alias, generics) = type_?; | ||
6464 | let kind = match alias { | ||
6465 | AliasKind::Weak(typ) => ast::ImplItemKind::Type(typ), | ||
6466 | AliasKind::Existential(bounds) => ast::ImplItemKind::Existential(bounds), | ||
6467 | }; | ||
6468 | (name, kind, generics) | ||
6469 | } else if self.is_const_item() { | ||
6470 | // This parses the grammar: | ||
6471 | // ImplItemConst = "const" Ident ":" Ty "=" Expr ";" | ||
6472 | self.expect_keyword(keywords::Const)?; | ||
6473 | let name = self.parse_ident()?; | ||
6474 | self.expect(&token::Colon)?; | ||
6475 | let typ = self.parse_ty()?; | ||
6476 | self.expect(&token::Eq)?; | ||
6477 | let expr = self.parse_expr()?; | ||
6478 | self.expect(&token::Semi)?; | ||
6479 | (name, ast::ImplItemKind::Const(typ, expr), ast::Generics::default()) | ||
6480 | } else { | ||
6481 | let (name, inner_attrs, generics, node) = self.parse_impl_method(&vis, at_end)?; | ||
6482 | attrs.extend(inner_attrs); | ||
6483 | (name, node, generics) | ||
6484 | }; | ||
6485 | |||
6486 | Ok(ImplItem { | ||
6487 | id: ast::DUMMY_NODE_ID, | ||
6488 | span: lo.to(self.prev_span), | ||
6489 | ident: name, | ||
6490 | vis, | ||
6491 | defaultness, | ||
6492 | attrs, | ||
6493 | generics, | ||
6494 | node, | ||
6495 | tokens: None, | ||
6496 | }) | ||
6497 | } | ||
6498 | |||
6499 | fn complain_if_pub_macro(&mut self, vis: &VisibilityKind, sp: Span) { | ||
6500 | match *vis { | ||
6501 | VisibilityKind::Inherited => {} | ||
6502 | _ => { | ||
6503 | let is_macro_rules: bool = match self.token { | ||
6504 | token::Ident(sid, _) => sid.name == Symbol::intern("macro_rules"), | ||
6505 | _ => false, | ||
6506 | }; | ||
6507 | let mut err = if is_macro_rules { | ||
6508 | let mut err = self.diagnostic() | ||
6509 | .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); | ||
6510 | err.span_suggestion( | ||
6511 | sp, | ||
6512 | "try exporting the macro", | ||
6513 | "#[macro_export]".to_owned(), | ||
6514 | Applicability::MaybeIncorrect // speculative | ||
6515 | ); | ||
6516 | err | ||
6517 | } else { | ||
6518 | let mut err = self.diagnostic() | ||
6519 | .struct_span_err(sp, "can't qualify macro invocation with `pub`"); | ||
6520 | err.help("try adjusting the macro to put `pub` inside the invocation"); | ||
6521 | err | ||
6522 | }; | ||
6523 | err.emit(); | ||
6524 | } | ||
6525 | } | ||
6526 | } | ||
6527 | |||
6528 | fn missing_assoc_item_kind_err(&mut self, item_type: &str, prev_span: Span) | ||
6529 | -> DiagnosticBuilder<'a> | ||
6530 | { | ||
6531 | let expected_kinds = if item_type == "extern" { | ||
6532 | "missing `fn`, `type`, or `static`" | ||
6533 | } else { | ||
6534 | "missing `fn`, `type`, or `const`" | ||
6535 | }; | ||
6536 | |||
6537 | // Given this code `path(`, it seems like this is not | ||
6538 | // setting the visibility of a macro invocation, but rather | ||
6539 | // a mistyped method declaration. | ||
6540 | // Create a diagnostic pointing out that `fn` is missing. | ||
6541 | // | ||
6542 | // x | pub path(&self) { | ||
6543 | // | ^ missing `fn`, `type`, or `const` | ||
6544 | // pub path( | ||
6545 | // ^^ `sp` below will point to this | ||
6546 | let sp = prev_span.between(self.prev_span); | ||
6547 | let mut err = self.diagnostic().struct_span_err( | ||
6548 | sp, | ||
6549 | &format!("{} for {}-item declaration", | ||
6550 | expected_kinds, item_type)); | ||
6551 | err.span_label(sp, expected_kinds); | ||
6552 | err | ||
6553 | } | ||
6554 | |||
6555 | /// Parse a method or a macro invocation in a trait impl. | ||
6556 | fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool) | ||
6557 | -> PResult<'a, (Ident, Vec<Attribute>, ast::Generics, | ||
6558 | ast::ImplItemKind)> { | ||
6559 | // code copied from parse_macro_use_or_failure... abstraction! | ||
6560 | if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? { | ||
6561 | // method macro | ||
6562 | Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(), | ||
6563 | ast::ImplItemKind::Macro(mac))) | ||
6564 | } else { | ||
6565 | let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?; | ||
6566 | let ident = self.parse_ident()?; | ||
6567 | let mut generics = self.parse_generics()?; | ||
6568 | let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?; | ||
6569 | generics.where_clause = self.parse_where_clause()?; | ||
6570 | *at_end = true; | ||
6571 | let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; | ||
6572 | let header = ast::FnHeader { abi, unsafety, constness, asyncness }; | ||
6573 | Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method( | ||
6574 | ast::MethodSig { header, decl }, | ||
6575 | body | ||
6576 | ))) | ||
6577 | } | ||
6578 | } | ||
6579 | |||
6580 | /// Parses `trait Foo { ... }` or `trait Foo = Bar;`. | ||
6581 | fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> { | ||
6582 | let ident = self.parse_ident()?; | ||
6583 | let mut tps = self.parse_generics()?; | ||
6584 | |||
6585 | // Parse optional colon and supertrait bounds. | ||
6586 | let bounds = if self.eat(&token::Colon) { | ||
6587 | self.parse_generic_bounds(Some(self.prev_span))? | ||
6588 | } else { | ||
6589 | Vec::new() | ||
6590 | }; | ||
6591 | |||
6592 | if self.eat(&token::Eq) { | ||
6593 | // it's a trait alias | ||
6594 | let bounds = self.parse_generic_bounds(None)?; | ||
6595 | tps.where_clause = self.parse_where_clause()?; | ||
6596 | self.expect(&token::Semi)?; | ||
6597 | if is_auto == IsAuto::Yes { | ||
6598 | let msg = "trait aliases cannot be `auto`"; | ||
6599 | self.struct_span_err(self.prev_span, msg) | ||
6600 | .span_label(self.prev_span, msg) | ||
6601 | .emit(); | ||
6602 | } | ||
6603 | if unsafety != Unsafety::Normal { | ||
6604 | let msg = "trait aliases cannot be `unsafe`"; | ||
6605 | self.struct_span_err(self.prev_span, msg) | ||
6606 | .span_label(self.prev_span, msg) | ||
6607 | .emit(); | ||
6608 | } | ||
6609 | Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) | ||
6610 | } else { | ||
6611 | // it's a normal trait | ||
6612 | tps.where_clause = self.parse_where_clause()?; | ||
6613 | self.expect(&token::OpenDelim(token::Brace))?; | ||
6614 | let mut trait_items = vec![]; | ||
6615 | while !self.eat(&token::CloseDelim(token::Brace)) { | ||
6616 | let mut at_end = false; | ||
6617 | match self.parse_trait_item(&mut at_end) { | ||
6618 | Ok(item) => trait_items.push(item), | ||
6619 | Err(mut e) => { | ||
6620 | e.emit(); | ||
6621 | if !at_end { | ||
6622 | self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); | ||
6623 | } | ||
6624 | } | ||
6625 | } | ||
6626 | } | ||
6627 | Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None)) | ||
6628 | } | ||
6629 | } | ||
6630 | |||
6631 | fn choose_generics_over_qpath(&self) -> bool { | ||
6632 | // There's an ambiguity between generic parameters and qualified paths in impls. | ||
6633 | // If we see `<` it may start both, so we have to inspect some following tokens. | ||
6634 | // The following combinations can only start generics, | ||
6635 | // but not qualified paths (with one exception): | ||
6636 | // `<` `>` - empty generic parameters | ||
6637 | // `<` `#` - generic parameters with attributes | ||
6638 | // `<` (LIFETIME|IDENT) `>` - single generic parameter | ||
6639 | // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list | ||
6640 | // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds | ||
6641 | // `<` (LIFETIME|IDENT) `=` - generic parameter with a default | ||
6642 | // `<` const - generic const parameter | ||
6643 | // The only truly ambiguous case is | ||
6644 | // `<` IDENT `>` `::` IDENT ... | ||
6645 | // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`) | ||
6646 | // because this is what almost always expected in practice, qualified paths in impls | ||
6647 | // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment. | ||
6648 | self.token == token::Lt && | ||
6649 | (self.look_ahead(1, |t| t == &token::Pound || t == &token::Gt) || | ||
6650 | self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) && | ||
6651 | self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma || | ||
6652 | t == &token::Colon || t == &token::Eq) || | ||
6653 | self.look_ahead(1, |t| t.is_keyword(keywords::Const))) | ||
6654 | } | ||
6655 | |||
6656 | fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> { | ||
6657 | self.expect(&token::OpenDelim(token::Brace))?; | ||
6658 | let attrs = self.parse_inner_attributes()?; | ||
6659 | |||
6660 | let mut impl_items = Vec::new(); | ||
6661 | while !self.eat(&token::CloseDelim(token::Brace)) { | ||
6662 | let mut at_end = false; | ||
6663 | match self.parse_impl_item(&mut at_end) { | ||
6664 | Ok(impl_item) => impl_items.push(impl_item), | ||
6665 | Err(mut err) => { | ||
6666 | err.emit(); | ||
6667 | if !at_end { | ||
6668 | self.recover_stmt_(SemiColonMode::Break, BlockMode::Break); | ||
6669 | } | ||
6670 | } | ||
6671 | } | ||
6672 | } | ||
6673 | Ok((impl_items, attrs)) | ||
6674 | } | ||
6675 | |||
6676 | /// Parses an implementation item, `impl` keyword is already parsed. | ||
6677 | /// | ||
6678 | /// impl<'a, T> TYPE { /* impl items */ } | ||
6679 | /// impl<'a, T> TRAIT for TYPE { /* impl items */ } | ||
6680 | /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } | ||
6681 | /// | ||
6682 | /// We actually parse slightly more relaxed grammar for better error reporting and recovery. | ||
6683 | /// `impl` GENERICS `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}` | ||
6684 | /// `impl` GENERICS `!`? TYPE (`where` PREDICATES)? `{` BODY `}` | ||
6685 | fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness) | ||
6686 | -> PResult<'a, ItemInfo> { | ||
6687 | // First, parse generic parameters if necessary. | ||
6688 | let mut generics = if self.choose_generics_over_qpath() { | ||
6689 | self.parse_generics()? | ||
6690 | } else { | ||
6691 | ast::Generics::default() | ||
6692 | }; | ||
6693 | |||
6694 | // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. | ||
6695 | let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) { | ||
6696 | self.bump(); // `!` | ||
6697 | ast::ImplPolarity::Negative | ||
6698 | } else { | ||
6699 | ast::ImplPolarity::Positive | ||
6700 | }; | ||
6701 | |||
6702 | // Parse both types and traits as a type, then reinterpret if necessary. | ||
6703 | let ty_first = self.parse_ty()?; | ||
6704 | |||
6705 | // If `for` is missing we try to recover. | ||
6706 | let has_for = self.eat_keyword(keywords::For); | ||
6707 | let missing_for_span = self.prev_span.between(self.span); | ||
6708 | |||
6709 | let ty_second = if self.token == token::DotDot { | ||
6710 | // We need to report this error after `cfg` expansion for compatibility reasons | ||
6711 | self.bump(); // `..`, do not add it to expected tokens | ||
6712 | Some(P(Ty { node: TyKind::Err, span: self.prev_span, id: ast::DUMMY_NODE_ID })) | ||
6713 | } else if has_for || self.token.can_begin_type() { | ||
6714 | Some(self.parse_ty()?) | ||
6715 | } else { | ||
6716 | None | ||
6717 | }; | ||
6718 | |||
6719 | generics.where_clause = self.parse_where_clause()?; | ||
6720 | |||
6721 | let (impl_items, attrs) = self.parse_impl_body()?; | ||
6722 | |||
6723 | let item_kind = match ty_second { | ||
6724 | Some(ty_second) => { | ||
6725 | // impl Trait for Type | ||
6726 | if !has_for { | ||
6727 | self.struct_span_err(missing_for_span, "missing `for` in a trait impl") | ||
6728 | .span_suggestion_short( | ||
6729 | missing_for_span, | ||
6730 | "add `for` here", | ||
6731 | " for ".to_string(), | ||
6732 | Applicability::MachineApplicable, | ||
6733 | ).emit(); | ||
6734 | } | ||
6735 | |||
6736 | let ty_first = ty_first.into_inner(); | ||
6737 | let path = match ty_first.node { | ||
6738 | // This notably includes paths passed through `ty` macro fragments (#46438). | ||
6739 | TyKind::Path(None, path) => path, | ||
6740 | _ => { | ||
6741 | self.span_err(ty_first.span, "expected a trait, found type"); | ||
6742 | ast::Path::from_ident(Ident::new(keywords::Invalid.name(), ty_first.span)) | ||
6743 | } | ||
6744 | }; | ||
6745 | let trait_ref = TraitRef { path, ref_id: ty_first.id }; | ||
6746 | |||
6747 | ItemKind::Impl(unsafety, polarity, defaultness, | ||
6748 | generics, Some(trait_ref), ty_second, impl_items) | ||
6749 | } | ||
6750 | None => { | ||
6751 | // impl Type | ||
6752 | ItemKind::Impl(unsafety, polarity, defaultness, | ||
6753 | generics, None, ty_first, impl_items) | ||
6754 | } | ||
6755 | }; | ||
6756 | |||
6757 | Ok((keywords::Invalid.ident(), item_kind, Some(attrs))) | ||
6758 | } | ||
6759 | |||
6760 | fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> { | ||
6761 | if self.eat_keyword(keywords::For) { | ||
6762 | self.expect_lt()?; | ||
6763 | let params = self.parse_generic_params()?; | ||
6764 | self.expect_gt()?; | ||
6765 | // We rely on AST validation to rule out invalid cases: There must not be type | ||
6766 | // parameters, and the lifetime parameters must not have bounds. | ||
6767 | Ok(params) | ||
6768 | } else { | ||
6769 | Ok(Vec::new()) | ||
6770 | } | ||
6771 | } | ||
6772 | |||
6773 | /// Parses `struct Foo { ... }`. | ||
6774 | fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> { | ||
6775 | let class_name = self.parse_ident()?; | ||
6776 | |||
6777 | let mut generics = self.parse_generics()?; | ||
6778 | |||
6779 | // There is a special case worth noting here, as reported in issue #17904. | ||
6780 | // If we are parsing a tuple struct it is the case that the where clause | ||
6781 | // should follow the field list. Like so: | ||
6782 | // | ||
6783 | // struct Foo<T>(T) where T: Copy; | ||
6784 | // | ||
6785 | // If we are parsing a normal record-style struct it is the case | ||
6786 | // that the where clause comes before the body, and after the generics. | ||
6787 | // So if we look ahead and see a brace or a where-clause we begin | ||
6788 | // parsing a record style struct. | ||
6789 | // | ||
6790 | // Otherwise if we look ahead and see a paren we parse a tuple-style | ||
6791 | // struct. | ||
6792 | |||
6793 | let vdata = if self.token.is_keyword(keywords::Where) { | ||
6794 | generics.where_clause = self.parse_where_clause()?; | ||
6795 | if self.eat(&token::Semi) { | ||
6796 | // If we see a: `struct Foo<T> where T: Copy;` style decl. | ||
6797 | VariantData::Unit(ast::DUMMY_NODE_ID) | ||
6798 | } else { | ||
6799 | // If we see: `struct Foo<T> where T: Copy { ... }` | ||
6800 | VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) | ||
6801 | } | ||
6802 | // No `where` so: `struct Foo<T>;` | ||
6803 | } else if self.eat(&token::Semi) { | ||
6804 | VariantData::Unit(ast::DUMMY_NODE_ID) | ||
6805 | // Record-style struct definition | ||
6806 | } else if self.token == token::OpenDelim(token::Brace) { | ||
6807 | VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) | ||
6808 | // Tuple-style struct definition with optional where-clause. | ||
6809 | } else if self.token == token::OpenDelim(token::Paren) { | ||
6810 | let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID); | ||
6811 | generics.where_clause = self.parse_where_clause()?; | ||
6812 | self.expect(&token::Semi)?; | ||
6813 | body | ||
6814 | } else { | ||
6815 | let token_str = self.this_token_descr(); | ||
6816 | let mut err = self.fatal(&format!( | ||
6817 | "expected `where`, `{{`, `(`, or `;` after struct name, found {}", | ||
6818 | token_str | ||
6819 | )); | ||
6820 | err.span_label(self.span, "expected `where`, `{`, `(`, or `;` after struct name"); | ||
6821 | return Err(err); | ||
6822 | }; | ||
6823 | |||
6824 | Ok((class_name, ItemKind::Struct(vdata, generics), None)) | ||
6825 | } | ||
6826 | |||
6827 | /// Parses `union Foo { ... }`. | ||
6828 | fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> { | ||
6829 | let class_name = self.parse_ident()?; | ||
6830 | |||
6831 | let mut generics = self.parse_generics()?; | ||
6832 | |||
6833 | let vdata = if self.token.is_keyword(keywords::Where) { | ||
6834 | generics.where_clause = self.parse_where_clause()?; | ||
6835 | VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) | ||
6836 | } else if self.token == token::OpenDelim(token::Brace) { | ||
6837 | VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID) | ||
6838 | } else { | ||
6839 | let token_str = self.this_token_descr(); | ||
6840 | let mut err = self.fatal(&format!( | ||
6841 | "expected `where` or `{{` after union name, found {}", token_str)); | ||
6842 | err.span_label(self.span, "expected `where` or `{` after union name"); | ||
6843 | return Err(err); | ||
6844 | }; | ||
6845 | |||
6846 | Ok((class_name, ItemKind::Union(vdata, generics), None)) | ||
6847 | } | ||
6848 | |||
6849 | fn consume_block(&mut self, delim: token::DelimToken) { | ||
6850 | let mut brace_depth = 0; | ||
6851 | loop { | ||
6852 | if self.eat(&token::OpenDelim(delim)) { | ||
6853 | brace_depth += 1; | ||
6854 | } else if self.eat(&token::CloseDelim(delim)) { | ||
6855 | if brace_depth == 0 { | ||
6856 | return; | ||
6857 | } else { | ||
6858 | brace_depth -= 1; | ||
6859 | continue; | ||
6860 | } | ||
6861 | } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) { | ||
6862 | return; | ||
6863 | } else { | ||
6864 | self.bump(); | ||
6865 | } | ||
6866 | } | ||
6867 | } | ||
6868 | |||
6869 | fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> { | ||
6870 | let mut fields = Vec::new(); | ||
6871 | if self.eat(&token::OpenDelim(token::Brace)) { | ||
6872 | while self.token != token::CloseDelim(token::Brace) { | ||
6873 | let field = self.parse_struct_decl_field().map_err(|e| { | ||
6874 | self.recover_stmt(); | ||
6875 | e | ||
6876 | }); | ||
6877 | match field { | ||
6878 | Ok(field) => fields.push(field), | ||
6879 | Err(mut err) => { | ||
6880 | err.emit(); | ||
6881 | } | ||
6882 | } | ||
6883 | } | ||
6884 | self.eat(&token::CloseDelim(token::Brace)); | ||
6885 | } else { | ||
6886 | let token_str = self.this_token_descr(); | ||
6887 | let mut err = self.fatal(&format!( | ||
6888 | "expected `where`, or `{{` after struct name, found {}", token_str)); | ||
6889 | err.span_label(self.span, "expected `where`, or `{` after struct name"); | ||
6890 | return Err(err); | ||
6891 | } | ||
6892 | |||
6893 | Ok(fields) | ||
6894 | } | ||
6895 | |||
6896 | fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> { | ||
6897 | // This is the case where we find `struct Foo<T>(T) where T: Copy;` | ||
6898 | // Unit like structs are handled in parse_item_struct function | ||
6899 | let fields = self.parse_unspanned_seq( | ||
6900 | &token::OpenDelim(token::Paren), | ||
6901 | &token::CloseDelim(token::Paren), | ||
6902 | SeqSep::trailing_allowed(token::Comma), | ||
6903 | |p| { | ||
6904 | let attrs = p.parse_outer_attributes()?; | ||
6905 | let lo = p.span; | ||
6906 | let vis = p.parse_visibility(true)?; | ||
6907 | let ty = p.parse_ty()?; | ||
6908 | Ok(StructField { | ||
6909 | span: lo.to(ty.span), | ||
6910 | vis, | ||
6911 | ident: None, | ||
6912 | id: ast::DUMMY_NODE_ID, | ||
6913 | ty, | ||
6914 | attrs, | ||
6915 | }) | ||
6916 | })?; | ||
6917 | |||
6918 | Ok(fields) | ||
6919 | } | ||
6920 | |||
6921 | /// Parses a structure field declaration. | ||
6922 | fn parse_single_struct_field(&mut self, | ||
6923 | lo: Span, | ||
6924 | vis: Visibility, | ||
6925 | attrs: Vec<Attribute> ) | ||
6926 | -> PResult<'a, StructField> { | ||
6927 | let mut seen_comma: bool = false; | ||
6928 | let a_var = self.parse_name_and_ty(lo, vis, attrs)?; | ||
6929 | if self.token == token::Comma { | ||
6930 | seen_comma = true; | ||
6931 | } | ||
6932 | match self.token { | ||
6933 | token::Comma => { | ||
6934 | self.bump(); | ||
6935 | } | ||
6936 | token::CloseDelim(token::Brace) => {} | ||
6937 | token::DocComment(_) => { | ||
6938 | let previous_span = self.prev_span; | ||
6939 | let mut err = self.span_fatal_err(self.span, Error::UselessDocComment); | ||
6940 | self.bump(); // consume the doc comment | ||
6941 | let comma_after_doc_seen = self.eat(&token::Comma); | ||
6942 | // `seen_comma` is always false, because we are inside doc block | ||
6943 | // condition is here to make code more readable | ||
6944 | if seen_comma == false && comma_after_doc_seen == true { | ||
6945 | seen_comma = true; | ||
6946 | } | ||
6947 | if comma_after_doc_seen || self.token == token::CloseDelim(token::Brace) { | ||
6948 | err.emit(); | ||
6949 | } else { | ||
6950 | if seen_comma == false { | ||
6951 | let sp = self.sess.source_map().next_point(previous_span); | ||
6952 | err.span_suggestion( | ||
6953 | sp, | ||
6954 | "missing comma here", | ||
6955 | ",".into(), | ||
6956 | Applicability::MachineApplicable | ||
6957 | ); | ||
6958 | } | ||
6959 | return Err(err); | ||
6960 | } | ||
6961 | } | ||
6962 | _ => { | ||
6963 | let sp = self.sess.source_map().next_point(self.prev_span); | ||
6964 | let mut err = self.struct_span_err(sp, &format!("expected `,`, or `}}`, found {}", | ||
6965 | self.this_token_descr())); | ||
6966 | if self.token.is_ident() { | ||
6967 | // This is likely another field; emit the diagnostic and keep going | ||
6968 | err.span_suggestion( | ||
6969 | sp, | ||
6970 | "try adding a comma", | ||
6971 | ",".into(), | ||
6972 | Applicability::MachineApplicable, | ||
6973 | ); | ||
6974 | err.emit(); | ||
6975 | } else { | ||
6976 | return Err(err) | ||
6977 | } | ||
6978 | } | ||
6979 | } | ||
6980 | Ok(a_var) | ||
6981 | } | ||
6982 | |||
6983 | /// Parses an element of a struct declaration. | ||
6984 | fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> { | ||
6985 | let attrs = self.parse_outer_attributes()?; | ||
6986 | let lo = self.span; | ||
6987 | let vis = self.parse_visibility(false)?; | ||
6988 | self.parse_single_struct_field(lo, vis, attrs) | ||
6989 | } | ||
6990 | |||
6991 | /// Parses `pub`, `pub(crate)` and `pub(in path)` plus shortcuts `crate` for `pub(crate)`, | ||
6992 | /// `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`. | ||
6993 | /// If the following element can't be a tuple (i.e., it's a function definition), then | ||
6994 | /// it's not a tuple struct field), and the contents within the parentheses isn't valid, | ||
6995 | /// so emit a proper diagnostic. | ||
6996 | pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { | ||
6997 | maybe_whole!(self, NtVis, |x| x); | ||
6998 | |||
6999 | self.expected_tokens.push(TokenType::Keyword(keywords::Crate)); | ||
7000 | if self.is_crate_vis() { | ||
7001 | self.bump(); // `crate` | ||
7002 | return Ok(respan(self.prev_span, VisibilityKind::Crate(CrateSugar::JustCrate))); | ||
7003 | } | ||
7004 | |||
7005 | if !self.eat_keyword(keywords::Pub) { | ||
7006 | // We need a span for our `Spanned<VisibilityKind>`, but there's inherently no | ||
7007 | // keyword to grab a span from for inherited visibility; an empty span at the | ||
7008 | // beginning of the current token would seem to be the "Schelling span". | ||
7009 | return Ok(respan(self.span.shrink_to_lo(), VisibilityKind::Inherited)) | ||
7010 | } | ||
7011 | let lo = self.prev_span; | ||
7012 | |||
7013 | if self.check(&token::OpenDelim(token::Paren)) { | ||
7014 | // We don't `self.bump()` the `(` yet because this might be a struct definition where | ||
7015 | // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`. | ||
7016 | // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so | ||
7017 | // by the following tokens. | ||
7018 | if self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) { | ||
7019 | // `pub(crate)` | ||
7020 | self.bump(); // `(` | ||
7021 | self.bump(); // `crate` | ||
7022 | self.expect(&token::CloseDelim(token::Paren))?; // `)` | ||
7023 | let vis = respan( | ||
7024 | lo.to(self.prev_span), | ||
7025 | VisibilityKind::Crate(CrateSugar::PubCrate), | ||
7026 | ); | ||
7027 | return Ok(vis) | ||
7028 | } else if self.look_ahead(1, |t| t.is_keyword(keywords::In)) { | ||
7029 | // `pub(in path)` | ||
7030 | self.bump(); // `(` | ||
7031 | self.bump(); // `in` | ||
7032 | let path = self.parse_path(PathStyle::Mod)?; // `path` | ||
7033 | self.expect(&token::CloseDelim(token::Paren))?; // `)` | ||
7034 | let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { | ||
7035 | path: P(path), | ||
7036 | id: ast::DUMMY_NODE_ID, | ||
7037 | }); | ||
7038 | return Ok(vis) | ||
7039 | } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) && | ||
7040 | self.look_ahead(1, |t| t.is_keyword(keywords::Super) || | ||
7041 | t.is_keyword(keywords::SelfLower)) | ||
7042 | { | ||
7043 | // `pub(self)` or `pub(super)` | ||
7044 | self.bump(); // `(` | ||
7045 | let path = self.parse_path(PathStyle::Mod)?; // `super`/`self` | ||
7046 | self.expect(&token::CloseDelim(token::Paren))?; // `)` | ||
7047 | let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { | ||
7048 | path: P(path), | ||
7049 | id: ast::DUMMY_NODE_ID, | ||
7050 | }); | ||
7051 | return Ok(vis) | ||
7052 | } else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct | ||
7053 | // `pub(something) fn ...` or `struct X { pub(something) y: Z }` | ||
7054 | self.bump(); // `(` | ||
7055 | let msg = "incorrect visibility restriction"; | ||
7056 | let suggestion = r##"some possible visibility restrictions are: | ||
7057 | `pub(crate)`: visible only on the current crate | ||
7058 | `pub(super)`: visible only in the current module's parent | ||
7059 | `pub(in path::to::module)`: visible only on the specified path"##; | ||
7060 | let path = self.parse_path(PathStyle::Mod)?; | ||
7061 | let sp = self.prev_span; | ||
7062 | let help_msg = format!("make this visible only to module `{}` with `in`", path); | ||
7063 | self.expect(&token::CloseDelim(token::Paren))?; // `)` | ||
7064 | let mut err = struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg); | ||
7065 | err.help(suggestion); | ||
7066 | err.span_suggestion( | ||
7067 | sp, &help_msg, format!("in {}", path), Applicability::MachineApplicable | ||
7068 | ); | ||
7069 | err.emit(); // emit diagnostic, but continue with public visibility | ||
7070 | } | ||
7071 | } | ||
7072 | |||
7073 | Ok(respan(lo, VisibilityKind::Public)) | ||
7074 | } | ||
7075 | |||
7076 | /// Parses defaultness (i.e., `default` or nothing). | ||
7077 | fn parse_defaultness(&mut self) -> Defaultness { | ||
7078 | // `pub` is included for better error messages | ||
7079 | if self.check_keyword(keywords::Default) && | ||
7080 | self.look_ahead(1, |t| t.is_keyword(keywords::Impl) || | ||
7081 | t.is_keyword(keywords::Const) || | ||
7082 | t.is_keyword(keywords::Fn) || | ||
7083 | t.is_keyword(keywords::Unsafe) || | ||
7084 | t.is_keyword(keywords::Extern) || | ||
7085 | t.is_keyword(keywords::Type) || | ||
7086 | t.is_keyword(keywords::Pub)) { | ||
7087 | self.bump(); // `default` | ||
7088 | Defaultness::Default | ||
7089 | } else { | ||
7090 | Defaultness::Final | ||
7091 | } | ||
7092 | } | ||
7093 | |||
7094 | fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool { | ||
7095 | if self.eat(&token::Semi) { | ||
7096 | let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`"); | ||
7097 | err.span_suggestion_short( | ||
7098 | self.prev_span, | ||
7099 | "remove this semicolon", | ||
7100 | String::new(), | ||
7101 | Applicability::MachineApplicable, | ||
7102 | ); | ||
7103 | if !items.is_empty() { | ||
7104 | let previous_item = &items[items.len()-1]; | ||
7105 | let previous_item_kind_name = match previous_item.node { | ||
7106 | // say "braced struct" because tuple-structs and | ||
7107 | // braceless-empty-struct declarations do take a semicolon | ||
7108 | ItemKind::Struct(..) => Some("braced struct"), | ||
7109 | ItemKind::Enum(..) => Some("enum"), | ||
7110 | ItemKind::Trait(..) => Some("trait"), | ||
7111 | ItemKind::Union(..) => Some("union"), | ||
7112 | _ => None, | ||
7113 | }; | ||
7114 | if let Some(name) = previous_item_kind_name { | ||
7115 | err.help(&format!("{} declarations are not followed by a semicolon", name)); | ||
7116 | } | ||
7117 | } | ||
7118 | err.emit(); | ||
7119 | true | ||
7120 | } else { | ||
7121 | false | ||
7122 | } | ||
7123 | } | ||
7124 | |||
7125 | /// Given a termination token, parses all of the items in a module. | ||
7126 | fn parse_mod_items(&mut self, term: &token::Token, inner_lo: Span) -> PResult<'a, Mod> { | ||
7127 | let mut items = vec![]; | ||
7128 | while let Some(item) = self.parse_item()? { | ||
7129 | items.push(item); | ||
7130 | self.maybe_consume_incorrect_semicolon(&items); | ||
7131 | } | ||
7132 | |||
7133 | if !self.eat(term) { | ||
7134 | let token_str = self.this_token_descr(); | ||
7135 | if !self.maybe_consume_incorrect_semicolon(&items) { | ||
7136 | let mut err = self.fatal(&format!("expected item, found {}", token_str)); | ||
7137 | err.span_label(self.span, "expected item"); | ||
7138 | return Err(err); | ||
7139 | } | ||
7140 | } | ||
7141 | |||
7142 | let hi = if self.span.is_dummy() { | ||
7143 | inner_lo | ||
7144 | } else { | ||
7145 | self.prev_span | ||
7146 | }; | ||
7147 | |||
7148 | Ok(ast::Mod { | ||
7149 | inner: inner_lo.to(hi), | ||
7150 | items, | ||
7151 | inline: true | ||
7152 | }) | ||
7153 | } | ||
7154 | |||
7155 | fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> { | ||
7156 | let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; | ||
7157 | self.expect(&token::Colon)?; | ||
7158 | let ty = self.parse_ty()?; | ||
7159 | self.expect(&token::Eq)?; | ||
7160 | let e = self.parse_expr()?; | ||
7161 | self.expect(&token::Semi)?; | ||
7162 | let item = match m { | ||
7163 | Some(m) => ItemKind::Static(ty, m, e), | ||
7164 | None => ItemKind::Const(ty, e), | ||
7165 | }; | ||
7166 | Ok((id, item, None)) | ||
7167 | } | ||
7168 | |||
7169 | /// Parse a `mod <foo> { ... }` or `mod <foo>;` item | ||
7170 | fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { | ||
7171 | let (in_cfg, outer_attrs) = { | ||
7172 | let mut strip_unconfigured = crate::config::StripUnconfigured { | ||
7173 | sess: self.sess, | ||
7174 | features: None, // don't perform gated feature checking | ||
7175 | }; | ||
7176 | let mut outer_attrs = outer_attrs.to_owned(); | ||
7177 | strip_unconfigured.process_cfg_attrs(&mut outer_attrs); | ||
7178 | (!self.cfg_mods || strip_unconfigured.in_cfg(&outer_attrs), outer_attrs) | ||
7179 | }; | ||
7180 | |||
7181 | let id_span = self.span; | ||
7182 | let id = self.parse_ident()?; | ||
7183 | if self.eat(&token::Semi) { | ||
7184 | if in_cfg && self.recurse_into_file_modules { | ||
7185 | // This mod is in an external file. Let's go get it! | ||
7186 | let ModulePathSuccess { path, directory_ownership, warn } = | ||
7187 | self.submod_path(id, &outer_attrs, id_span)?; | ||
7188 | let (module, mut attrs) = | ||
7189 | self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?; | ||
7190 | // Record that we fetched the mod from an external file | ||
7191 | if warn { | ||
7192 | let attr = Attribute { | ||
7193 | id: attr::mk_attr_id(), | ||
7194 | style: ast::AttrStyle::Outer, | ||
7195 | path: ast::Path::from_ident(Ident::from_str("warn_directory_ownership")), | ||
7196 | tokens: TokenStream::empty(), | ||
7197 | is_sugared_doc: false, | ||
7198 | span: syntax_pos::DUMMY_SP, | ||
7199 | }; | ||
7200 | attr::mark_known(&attr); | ||
7201 | attrs.push(attr); | ||
7202 | } | ||
7203 | Ok((id, ItemKind::Mod(module), Some(attrs))) | ||
7204 | } else { | ||
7205 | let placeholder = ast::Mod { | ||
7206 | inner: syntax_pos::DUMMY_SP, | ||
7207 | items: Vec::new(), | ||
7208 | inline: false | ||
7209 | }; | ||
7210 | Ok((id, ItemKind::Mod(placeholder), None)) | ||
7211 | } | ||
7212 | } else { | ||
7213 | let old_directory = self.directory.clone(); | ||
7214 | self.push_directory(id, &outer_attrs); | ||
7215 | |||
7216 | self.expect(&token::OpenDelim(token::Brace))?; | ||
7217 | let mod_inner_lo = self.span; | ||
7218 | let attrs = self.parse_inner_attributes()?; | ||
7219 | let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; | ||
7220 | |||
7221 | self.directory = old_directory; | ||
7222 | Ok((id, ItemKind::Mod(module), Some(attrs))) | ||
7223 | } | ||
7224 | } | ||
7225 | |||
7226 | fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { | ||
7227 | if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") { | ||
7228 | self.directory.path.to_mut().push(&path.as_str()); | ||
7229 | self.directory.ownership = DirectoryOwnership::Owned { relative: None }; | ||
7230 | } else { | ||
7231 | // We have to push on the current module name in the case of relative | ||
7232 | // paths in order to ensure that any additional module paths from inline | ||
7233 | // `mod x { ... }` come after the relative extension. | ||
7234 | // | ||
7235 | // For example, a `mod z { ... }` inside `x/y.rs` should set the current | ||
7236 | // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. | ||
7237 | if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership { | ||
7238 | if let Some(ident) = relative.take() { // remove the relative offset | ||
7239 | self.directory.path.to_mut().push(ident.as_str()); | ||
7240 | } | ||
7241 | } | ||
7242 | self.directory.path.to_mut().push(&id.as_str()); | ||
7243 | } | ||
7244 | } | ||
7245 | |||
7246 | pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> { | ||
7247 | if let Some(s) = attr::first_attr_value_str_by_name(attrs, "path") { | ||
7248 | let s = s.as_str(); | ||
7249 | |||
7250 | // On windows, the base path might have the form | ||
7251 | // `\\?\foo\bar` in which case it does not tolerate | ||
7252 | // mixed `/` and `\` separators, so canonicalize | ||
7253 | // `/` to `\`. | ||
7254 | #[cfg(windows)] | ||
7255 | let s = s.replace("/", "\\"); | ||
7256 | Some(dir_path.join(s)) | ||
7257 | } else { | ||
7258 | None | ||
7259 | } | ||
7260 | } | ||
7261 | |||
7262 | /// Returns a path to a module. | ||
7263 | pub fn default_submod_path( | ||
7264 | id: ast::Ident, | ||
7265 | relative: Option<ast::Ident>, | ||
7266 | dir_path: &Path, | ||
7267 | source_map: &SourceMap) -> ModulePath | ||
7268 | { | ||
7269 | // If we're in a foo.rs file instead of a mod.rs file, | ||
7270 | // we need to look for submodules in | ||
7271 | // `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than | ||
7272 | // `./<id>.rs` and `./<id>/mod.rs`. | ||
7273 | let relative_prefix_string; | ||
7274 | let relative_prefix = if let Some(ident) = relative { | ||
7275 | relative_prefix_string = format!("{}{}", ident.as_str(), path::MAIN_SEPARATOR); | ||
7276 | &relative_prefix_string | ||
7277 | } else { | ||
7278 | "" | ||
7279 | }; | ||
7280 | |||
7281 | let mod_name = id.to_string(); | ||
7282 | let default_path_str = format!("{}{}.rs", relative_prefix, mod_name); | ||
7283 | let secondary_path_str = format!("{}{}{}mod.rs", | ||
7284 | relative_prefix, mod_name, path::MAIN_SEPARATOR); | ||
7285 | let default_path = dir_path.join(&default_path_str); | ||
7286 | let secondary_path = dir_path.join(&secondary_path_str); | ||
7287 | let default_exists = source_map.file_exists(&default_path); | ||
7288 | let secondary_exists = source_map.file_exists(&secondary_path); | ||
7289 | |||
7290 | let result = match (default_exists, secondary_exists) { | ||
7291 | (true, false) => Ok(ModulePathSuccess { | ||
7292 | path: default_path, | ||
7293 | directory_ownership: DirectoryOwnership::Owned { | ||
7294 | relative: Some(id), | ||
7295 | }, | ||
7296 | warn: false, | ||
7297 | }), | ||
7298 | (false, true) => Ok(ModulePathSuccess { | ||
7299 | path: secondary_path, | ||
7300 | directory_ownership: DirectoryOwnership::Owned { | ||
7301 | relative: None, | ||
7302 | }, | ||
7303 | warn: false, | ||
7304 | }), | ||
7305 | (false, false) => Err(Error::FileNotFoundForModule { | ||
7306 | mod_name: mod_name.clone(), | ||
7307 | default_path: default_path_str, | ||
7308 | secondary_path: secondary_path_str, | ||
7309 | dir_path: dir_path.display().to_string(), | ||
7310 | }), | ||
7311 | (true, true) => Err(Error::DuplicatePaths { | ||
7312 | mod_name: mod_name.clone(), | ||
7313 | default_path: default_path_str, | ||
7314 | secondary_path: secondary_path_str, | ||
7315 | }), | ||
7316 | }; | ||
7317 | |||
7318 | ModulePath { | ||
7319 | name: mod_name, | ||
7320 | path_exists: default_exists || secondary_exists, | ||
7321 | result, | ||
7322 | } | ||
7323 | } | ||
7324 | |||
7325 | fn submod_path(&mut self, | ||
7326 | id: ast::Ident, | ||
7327 | outer_attrs: &[Attribute], | ||
7328 | id_sp: Span) | ||
7329 | -> PResult<'a, ModulePathSuccess> { | ||
7330 | if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { | ||
7331 | return Ok(ModulePathSuccess { | ||
7332 | directory_ownership: match path.file_name().and_then(|s| s.to_str()) { | ||
7333 | // All `#[path]` files are treated as though they are a `mod.rs` file. | ||
7334 | // This means that `mod foo;` declarations inside `#[path]`-included | ||
7335 | // files are siblings, | ||
7336 | // | ||
7337 | // Note that this will produce weirdness when a file named `foo.rs` is | ||
7338 | // `#[path]` included and contains a `mod foo;` declaration. | ||
7339 | // If you encounter this, it's your own darn fault :P | ||
7340 | Some(_) => DirectoryOwnership::Owned { relative: None }, | ||
7341 | _ => DirectoryOwnership::UnownedViaMod(true), | ||
7342 | }, | ||
7343 | path, | ||
7344 | warn: false, | ||
7345 | }); | ||
7346 | } | ||
7347 | |||
7348 | let relative = match self.directory.ownership { | ||
7349 | DirectoryOwnership::Owned { relative } => relative, | ||
7350 | DirectoryOwnership::UnownedViaBlock | | ||
7351 | DirectoryOwnership::UnownedViaMod(_) => None, | ||
7352 | }; | ||
7353 | let paths = Parser::default_submod_path( | ||
7354 | id, relative, &self.directory.path, self.sess.source_map()); | ||
7355 | |||
7356 | match self.directory.ownership { | ||
7357 | DirectoryOwnership::Owned { .. } => { | ||
7358 | paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) | ||
7359 | }, | ||
7360 | DirectoryOwnership::UnownedViaBlock => { | ||
7361 | let msg = | ||
7362 | "Cannot declare a non-inline module inside a block \ | ||
7363 | unless it has a path attribute"; | ||
7364 | let mut err = self.diagnostic().struct_span_err(id_sp, msg); | ||
7365 | if paths.path_exists { | ||
7366 | let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", | ||
7367 | paths.name); | ||
7368 | err.span_note(id_sp, &msg); | ||
7369 | } | ||
7370 | Err(err) | ||
7371 | } | ||
7372 | DirectoryOwnership::UnownedViaMod(warn) => { | ||
7373 | if warn { | ||
7374 | if let Ok(result) = paths.result { | ||
7375 | return Ok(ModulePathSuccess { warn: true, ..result }); | ||
7376 | } | ||
7377 | } | ||
7378 | let mut err = self.diagnostic().struct_span_err(id_sp, | ||
7379 | "cannot declare a new module at this location"); | ||
7380 | if !id_sp.is_dummy() { | ||
7381 | let src_path = self.sess.source_map().span_to_filename(id_sp); | ||
7382 | if let FileName::Real(src_path) = src_path { | ||
7383 | if let Some(stem) = src_path.file_stem() { | ||
7384 | let mut dest_path = src_path.clone(); | ||
7385 | dest_path.set_file_name(stem); | ||
7386 | dest_path.push("mod.rs"); | ||
7387 | err.span_note(id_sp, | ||
7388 | &format!("maybe move this module `{}` to its own \ | ||
7389 | directory via `{}`", src_path.display(), | ||
7390 | dest_path.display())); | ||
7391 | } | ||
7392 | } | ||
7393 | } | ||
7394 | if paths.path_exists { | ||
7395 | err.span_note(id_sp, | ||
7396 | &format!("... or maybe `use` the module `{}` instead \ | ||
7397 | of possibly redeclaring it", | ||
7398 | paths.name)); | ||
7399 | } | ||
7400 | Err(err) | ||
7401 | } | ||
7402 | } | ||
7403 | } | ||
7404 | |||
7405 | /// Reads a module from a source file. | ||
7406 | fn eval_src_mod(&mut self, | ||
7407 | path: PathBuf, | ||
7408 | directory_ownership: DirectoryOwnership, | ||
7409 | name: String, | ||
7410 | id_sp: Span) | ||
7411 | -> PResult<'a, (ast::Mod, Vec<Attribute> )> { | ||
7412 | let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); | ||
7413 | if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { | ||
7414 | let mut err = String::from("circular modules: "); | ||
7415 | let len = included_mod_stack.len(); | ||
7416 | for p in &included_mod_stack[i.. len] { | ||
7417 | err.push_str(&p.to_string_lossy()); | ||
7418 | err.push_str(" -> "); | ||
7419 | } | ||
7420 | err.push_str(&path.to_string_lossy()); | ||
7421 | return Err(self.span_fatal(id_sp, &err[..])); | ||
7422 | } | ||
7423 | included_mod_stack.push(path.clone()); | ||
7424 | drop(included_mod_stack); | ||
7425 | |||
7426 | let mut p0 = | ||
7427 | new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp); | ||
7428 | p0.cfg_mods = self.cfg_mods; | ||
7429 | let mod_inner_lo = p0.span; | ||
7430 | let mod_attrs = p0.parse_inner_attributes()?; | ||
7431 | let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; | ||
7432 | m0.inline = false; | ||
7433 | self.sess.included_mod_stack.borrow_mut().pop(); | ||
7434 | Ok((m0, mod_attrs)) | ||
7435 | } | ||
7436 | |||
7437 | /// Parses a function declaration from a foreign module. | ||
7438 | fn parse_item_foreign_fn(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>) | ||
7439 | -> PResult<'a, ForeignItem> { | ||
7440 | self.expect_keyword(keywords::Fn)?; | ||
7441 | |||
7442 | let (ident, mut generics) = self.parse_fn_header()?; | ||
7443 | let decl = self.parse_fn_decl(true)?; | ||
7444 | generics.where_clause = self.parse_where_clause()?; | ||
7445 | let hi = self.span; | ||
7446 | self.expect(&token::Semi)?; | ||
7447 | Ok(ast::ForeignItem { | ||
7448 | ident, | ||
7449 | attrs, | ||
7450 | node: ForeignItemKind::Fn(decl, generics), | ||
7451 | id: ast::DUMMY_NODE_ID, | ||
7452 | span: lo.to(hi), | ||
7453 | vis, | ||
7454 | }) | ||
7455 | } | ||
7456 | |||
7457 | /// Parses a static item from a foreign module. | ||
7458 | /// Assumes that the `static` keyword is already parsed. | ||
7459 | fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>) | ||
7460 | -> PResult<'a, ForeignItem> { | ||
7461 | let mutbl = self.eat_keyword(keywords::Mut); | ||
7462 | let ident = self.parse_ident()?; | ||
7463 | self.expect(&token::Colon)?; | ||
7464 | let ty = self.parse_ty()?; | ||
7465 | let hi = self.span; | ||
7466 | self.expect(&token::Semi)?; | ||
7467 | Ok(ForeignItem { | ||
7468 | ident, | ||
7469 | attrs, | ||
7470 | node: ForeignItemKind::Static(ty, mutbl), | ||
7471 | id: ast::DUMMY_NODE_ID, | ||
7472 | span: lo.to(hi), | ||
7473 | vis, | ||
7474 | }) | ||
7475 | } | ||
7476 | |||
7477 | /// Parses a type from a foreign module. | ||
7478 | fn parse_item_foreign_type(&mut self, vis: ast::Visibility, lo: Span, attrs: Vec<Attribute>) | ||
7479 | -> PResult<'a, ForeignItem> { | ||
7480 | self.expect_keyword(keywords::Type)?; | ||
7481 | |||
7482 | let ident = self.parse_ident()?; | ||
7483 | let hi = self.span; | ||
7484 | self.expect(&token::Semi)?; | ||
7485 | Ok(ast::ForeignItem { | ||
7486 | ident: ident, | ||
7487 | attrs: attrs, | ||
7488 | node: ForeignItemKind::Ty, | ||
7489 | id: ast::DUMMY_NODE_ID, | ||
7490 | span: lo.to(hi), | ||
7491 | vis: vis | ||
7492 | }) | ||
7493 | } | ||
7494 | |||
7495 | fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { | ||
7496 | let error_msg = "crate name using dashes are not valid in `extern crate` statements"; | ||
7497 | let suggestion_msg = "if the original crate name uses dashes you need to use underscores \ | ||
7498 | in the code"; | ||
7499 | let mut ident = if self.token.is_keyword(keywords::SelfLower) { | ||
7500 | self.parse_path_segment_ident() | ||
7501 | } else { | ||
7502 | self.parse_ident() | ||
7503 | }?; | ||
7504 | let mut idents = vec![]; | ||
7505 | let mut replacement = vec![]; | ||
7506 | let mut fixed_crate_name = false; | ||
7507 | // Accept `extern crate name-like-this` for better diagnostics | ||
7508 | let dash = token::Token::BinOp(token::BinOpToken::Minus); | ||
7509 | if self.token == dash { // Do not include `-` as part of the expected tokens list | ||
7510 | while self.eat(&dash) { | ||
7511 | fixed_crate_name = true; | ||
7512 | replacement.push((self.prev_span, "_".to_string())); | ||
7513 | idents.push(self.parse_ident()?); | ||
7514 | } | ||
7515 | } | ||
7516 | if fixed_crate_name { | ||
7517 | let fixed_name_sp = ident.span.to(idents.last().unwrap().span); | ||
7518 | let mut fixed_name = format!("{}", ident.name); | ||
7519 | for part in idents { | ||
7520 | fixed_name.push_str(&format!("_{}", part.name)); | ||
7521 | } | ||
7522 | ident = Ident::from_str(&fixed_name).with_span_pos(fixed_name_sp); | ||
7523 | |||
7524 | let mut err = self.struct_span_err(fixed_name_sp, error_msg); | ||
7525 | err.span_label(fixed_name_sp, "dash-separated idents are not valid"); | ||
7526 | err.multipart_suggestion( | ||
7527 | suggestion_msg, | ||
7528 | replacement, | ||
7529 | Applicability::MachineApplicable, | ||
7530 | ); | ||
7531 | err.emit(); | ||
7532 | } | ||
7533 | Ok(ident) | ||
7534 | } | ||
7535 | |||
7536 | /// Parses `extern crate` links. | ||
7537 | /// | ||
7538 | /// # Examples | ||
7539 | /// | ||
7540 | /// ``` | ||
7541 | /// extern crate foo; | ||
7542 | /// extern crate bar as foo; | ||
7543 | /// ``` | ||
7544 | fn parse_item_extern_crate(&mut self, | ||
7545 | lo: Span, | ||
7546 | visibility: Visibility, | ||
7547 | attrs: Vec<Attribute>) | ||
7548 | -> PResult<'a, P<Item>> { | ||
7549 | // Accept `extern crate name-like-this` for better diagnostics | ||
7550 | let orig_name = self.parse_crate_name_with_dashes()?; | ||
7551 | let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { | ||
7552 | (rename, Some(orig_name.name)) | ||
7553 | } else { | ||
7554 | (orig_name, None) | ||
7555 | }; | ||
7556 | self.expect(&token::Semi)?; | ||
7557 | |||
7558 | let span = lo.to(self.prev_span); | ||
7559 | Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs)) | ||
7560 | } | ||
7561 | |||
7562 | /// Parses `extern` for foreign ABIs modules. | ||
7563 | /// | ||
7564 | /// `extern` is expected to have been | ||
7565 | /// consumed before calling this method. | ||
7566 | /// | ||
7567 | /// # Examples | ||
7568 | /// | ||
7569 | /// ```ignore (only-for-syntax-highlight) | ||
7570 | /// extern "C" {} | ||
7571 | /// extern {} | ||
7572 | /// ``` | ||
7573 | fn parse_item_foreign_mod(&mut self, | ||
7574 | lo: Span, | ||
7575 | opt_abi: Option<Abi>, | ||
7576 | visibility: Visibility, | ||
7577 | mut attrs: Vec<Attribute>) | ||
7578 | -> PResult<'a, P<Item>> { | ||
7579 | self.expect(&token::OpenDelim(token::Brace))?; | ||
7580 | |||
7581 | let abi = opt_abi.unwrap_or(Abi::C); | ||
7582 | |||
7583 | attrs.extend(self.parse_inner_attributes()?); | ||
7584 | |||
7585 | let mut foreign_items = vec![]; | ||
7586 | while !self.eat(&token::CloseDelim(token::Brace)) { | ||
7587 | foreign_items.push(self.parse_foreign_item()?); | ||
7588 | } | ||
7589 | |||
7590 | let prev_span = self.prev_span; | ||
7591 | let m = ast::ForeignMod { | ||
7592 | abi, | ||
7593 | items: foreign_items | ||
7594 | }; | ||
7595 | let invalid = keywords::Invalid.ident(); | ||
7596 | Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) | ||
7597 | } | ||
7598 | |||
7599 | /// Parses `type Foo = Bar;` | ||
7600 | /// or | ||
7601 | /// `existential type Foo: Bar;` | ||
7602 | /// or | ||
7603 | /// `return `None`` | ||
7604 | /// without modifying the parser state. | ||
7605 | fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> { | ||
7606 | // This parses the grammar: | ||
7607 | // Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";" | ||
7608 | if self.check_keyword(keywords::Type) || | ||
7609 | self.check_keyword(keywords::Existential) && | ||
7610 | self.look_ahead(1, |t| t.is_keyword(keywords::Type)) { | ||
7611 | let existential = self.eat_keyword(keywords::Existential); | ||
7612 | assert!(self.eat_keyword(keywords::Type)); | ||
7613 | Some(self.parse_existential_or_alias(existential)) | ||
7614 | } else { | ||
7615 | None | ||
7616 | } | ||
7617 | } | ||
7618 | |||
7619 | /// Parses a type alias or existential type. | ||
7620 | fn parse_existential_or_alias( | ||
7621 | &mut self, | ||
7622 | existential: bool, | ||
7623 | ) -> PResult<'a, (Ident, AliasKind, ast::Generics)> { | ||
7624 | let ident = self.parse_ident()?; | ||
7625 | let mut tps = self.parse_generics()?; | ||
7626 | tps.where_clause = self.parse_where_clause()?; | ||
7627 | let alias = if existential { | ||
7628 | self.expect(&token::Colon)?; | ||
7629 | let bounds = self.parse_generic_bounds(None)?; | ||
7630 | AliasKind::Existential(bounds) | ||
7631 | } else { | ||
7632 | self.expect(&token::Eq)?; | ||
7633 | let ty = self.parse_ty()?; | ||
7634 | AliasKind::Weak(ty) | ||
7635 | }; | ||
7636 | self.expect(&token::Semi)?; | ||
7637 | Ok((ident, alias, tps)) | ||
7638 | } | ||
7639 | |||
7640 | /// Parses the part of an enum declaration following the `{`. | ||
7641 | fn parse_enum_def(&mut self, _generics: &ast::Generics) -> PResult<'a, EnumDef> { | ||
7642 | let mut variants = Vec::new(); | ||
7643 | let mut all_nullary = true; | ||
7644 | let mut any_disr = vec![]; | ||
7645 | while self.token != token::CloseDelim(token::Brace) { | ||
7646 | let variant_attrs = self.parse_outer_attributes()?; | ||
7647 | let vlo = self.span; | ||
7648 | |||
7649 | let struct_def; | ||
7650 | let mut disr_expr = None; | ||
7651 | let ident = self.parse_ident()?; | ||
7652 | if self.check(&token::OpenDelim(token::Brace)) { | ||
7653 | // Parse a struct variant. | ||
7654 | all_nullary = false; | ||
7655 | struct_def = VariantData::Struct(self.parse_record_struct_body()?, | ||
7656 | ast::DUMMY_NODE_ID); | ||
7657 | } else if self.check(&token::OpenDelim(token::Paren)) { | ||
7658 | all_nullary = false; | ||
7659 | struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?, | ||
7660 | ast::DUMMY_NODE_ID); | ||
7661 | } else if self.eat(&token::Eq) { | ||
7662 | disr_expr = Some(AnonConst { | ||
7663 | id: ast::DUMMY_NODE_ID, | ||
7664 | value: self.parse_expr()?, | ||
7665 | }); | ||
7666 | if let Some(sp) = disr_expr.as_ref().map(|c| c.value.span) { | ||
7667 | any_disr.push(sp); | ||
7668 | } | ||
7669 | struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); | ||
7670 | } else { | ||
7671 | struct_def = VariantData::Unit(ast::DUMMY_NODE_ID); | ||
7672 | } | ||
7673 | |||
7674 | let vr = ast::Variant_ { | ||
7675 | ident, | ||
7676 | attrs: variant_attrs, | ||
7677 | data: struct_def, | ||
7678 | disr_expr, | ||
7679 | }; | ||
7680 | variants.push(respan(vlo.to(self.prev_span), vr)); | ||
7681 | |||
7682 | if !self.eat(&token::Comma) { break; } | ||
7683 | } | ||
7684 | self.expect(&token::CloseDelim(token::Brace))?; | ||
7685 | if !any_disr.is_empty() && !all_nullary { | ||
7686 | let mut err =self.struct_span_err( | ||
7687 | any_disr.clone(), | ||
7688 | "discriminator values can only be used with a field-less enum", | ||
7689 | ); | ||
7690 | for sp in any_disr { | ||
7691 | err.span_label(sp, "only valid in field-less enums"); | ||
7692 | } | ||
7693 | err.emit(); | ||
7694 | } | ||
7695 | |||
7696 | Ok(ast::EnumDef { variants }) | ||
7697 | } | ||
7698 | |||
7699 | /// Parses an enum declaration. | ||
7700 | fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { | ||
7701 | let id = self.parse_ident()?; | ||
7702 | let mut generics = self.parse_generics()?; | ||
7703 | generics.where_clause = self.parse_where_clause()?; | ||
7704 | self.expect(&token::OpenDelim(token::Brace))?; | ||
7705 | |||
7706 | let enum_definition = self.parse_enum_def(&generics).map_err(|e| { | ||
7707 | self.recover_stmt(); | ||
7708 | self.eat(&token::CloseDelim(token::Brace)); | ||
7709 | e | ||
7710 | })?; | ||
7711 | Ok((id, ItemKind::Enum(enum_definition, generics), None)) | ||
7712 | } | ||
7713 | |||
7714 | /// Parses a string as an ABI spec on an extern type or module. Consumes | ||
7715 | /// the `extern` keyword, if one is found. | ||
7716 | fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> { | ||
7717 | match self.token { | ||
7718 | token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => { | ||
7719 | let sp = self.span; | ||
7720 | self.expect_no_suffix(sp, "ABI spec", suf); | ||
7721 | self.bump(); | ||
7722 | match abi::lookup(&s.as_str()) { | ||
7723 | Some(abi) => Ok(Some(abi)), | ||
7724 | None => { | ||
7725 | let prev_span = self.prev_span; | ||
7726 | let mut err = struct_span_err!( | ||
7727 | self.sess.span_diagnostic, | ||
7728 | prev_span, | ||
7729 | E0703, | ||
7730 | "invalid ABI: found `{}`", | ||
7731 | s); | ||
7732 | err.span_label(prev_span, "invalid ABI"); | ||
7733 | err.help(&format!("valid ABIs: {}", abi::all_names().join(", "))); | ||
7734 | err.emit(); | ||
7735 | Ok(None) | ||
7736 | } | ||
7737 | } | ||
7738 | } | ||
7739 | |||
7740 | _ => Ok(None), | ||
7741 | } | ||
7742 | } | ||
7743 | |||
7744 | fn is_static_global(&mut self) -> bool { | ||
7745 | if self.check_keyword(keywords::Static) { | ||
7746 | // Check if this could be a closure | ||
7747 | !self.look_ahead(1, |token| { | ||
7748 | if token.is_keyword(keywords::Move) { | ||
7749 | return true; | ||
7750 | } | ||
7751 | match *token { | ||
7752 | token::BinOp(token::Or) | token::OrOr => true, | ||
7753 | _ => false, | ||
7754 | } | ||
7755 | }) | ||
7756 | } else { | ||
7757 | false | ||
7758 | } | ||
7759 | } | ||
7760 | |||
7761 | fn parse_item_( | ||
7762 | &mut self, | ||
7763 | attrs: Vec<Attribute>, | ||
7764 | macros_allowed: bool, | ||
7765 | attributes_allowed: bool, | ||
7766 | ) -> PResult<'a, Option<P<Item>>> { | ||
7767 | let (ret, tokens) = self.collect_tokens(|this| { | ||
7768 | this.parse_item_implementation(attrs, macros_allowed, attributes_allowed) | ||
7769 | })?; | ||
7770 | |||
7771 | // Once we've parsed an item and recorded the tokens we got while | ||
7772 | // parsing we may want to store `tokens` into the item we're about to | ||
7773 | // return. Note, though, that we specifically didn't capture tokens | ||
7774 | // related to outer attributes. The `tokens` field here may later be | ||
7775 | // used with procedural macros to convert this item back into a token | ||
7776 | // stream, but during expansion we may be removing attributes as we go | ||
7777 | // along. | ||
7778 | // | ||
7779 | // If we've got inner attributes then the `tokens` we've got above holds | ||
7780 | // these inner attributes. If an inner attribute is expanded we won't | ||
7781 | // actually remove it from the token stream, so we'll just keep yielding | ||
7782 | // it (bad!). To work around this case for now we just avoid recording | ||
7783 | // `tokens` if we detect any inner attributes. This should help keep | ||
7784 | // expansion correct, but we should fix this bug one day! | ||
7785 | Ok(ret.map(|item| { | ||
7786 | item.map(|mut i| { | ||
7787 | if !i.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { | ||
7788 | i.tokens = Some(tokens); | ||
7789 | } | ||
7790 | i | ||
7791 | }) | ||
7792 | })) | ||
7793 | } | ||
7794 | |||
7795 | /// Parses one of the items allowed by the flags. | ||
7796 | fn parse_item_implementation( | ||
7797 | &mut self, | ||
7798 | attrs: Vec<Attribute>, | ||
7799 | macros_allowed: bool, | ||
7800 | attributes_allowed: bool, | ||
7801 | ) -> PResult<'a, Option<P<Item>>> { | ||
7802 | maybe_whole!(self, NtItem, |item| { | ||
7803 | let mut item = item.into_inner(); | ||
7804 | let mut attrs = attrs; | ||
7805 | mem::swap(&mut item.attrs, &mut attrs); | ||
7806 | item.attrs.extend(attrs); | ||
7807 | Some(P(item)) | ||
7808 | }); | ||
7809 | |||
7810 | let lo = self.span; | ||
7811 | |||
7812 | let visibility = self.parse_visibility(false)?; | ||
7813 | |||
7814 | if self.eat_keyword(keywords::Use) { | ||
7815 | // USE ITEM | ||
7816 | let item_ = ItemKind::Use(P(self.parse_use_tree()?)); | ||
7817 | self.expect(&token::Semi)?; | ||
7818 | |||
7819 | let span = lo.to(self.prev_span); | ||
7820 | let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs); | ||
7821 | return Ok(Some(item)); | ||
7822 | } | ||
7823 | |||
7824 | if self.eat_keyword(keywords::Extern) { | ||
7825 | if self.eat_keyword(keywords::Crate) { | ||
7826 | return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?)); | ||
7827 | } | ||
7828 | |||
7829 | let opt_abi = self.parse_opt_abi()?; | ||
7830 | |||
7831 | if self.eat_keyword(keywords::Fn) { | ||
7832 | // EXTERN FUNCTION ITEM | ||
7833 | let fn_span = self.prev_span; | ||
7834 | let abi = opt_abi.unwrap_or(Abi::C); | ||
7835 | let (ident, item_, extra_attrs) = | ||
7836 | self.parse_item_fn(Unsafety::Normal, | ||
7837 | IsAsync::NotAsync, | ||
7838 | respan(fn_span, Constness::NotConst), | ||
7839 | abi)?; | ||
7840 | let prev_span = self.prev_span; | ||
7841 | let item = self.mk_item(lo.to(prev_span), | ||
7842 | ident, | ||
7843 | item_, | ||
7844 | visibility, | ||
7845 | maybe_append(attrs, extra_attrs)); | ||
7846 | return Ok(Some(item)); | ||
7847 | } else if self.check(&token::OpenDelim(token::Brace)) { | ||
7848 | return Ok(Some(self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs)?)); | ||
7849 | } | ||
7850 | |||
7851 | self.unexpected()?; | ||
7852 | } | ||
7853 | |||
7854 | if self.is_static_global() { | ||
7855 | self.bump(); | ||
7856 | // STATIC ITEM | ||
7857 | let m = if self.eat_keyword(keywords::Mut) { | ||
7858 | Mutability::Mutable | ||
7859 | } else { | ||
7860 | Mutability::Immutable | ||
7861 | }; | ||
7862 | let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?; | ||
7863 | let prev_span = self.prev_span; | ||
7864 | let item = self.mk_item(lo.to(prev_span), | ||
7865 | ident, | ||
7866 | item_, | ||
7867 | visibility, | ||
7868 | maybe_append(attrs, extra_attrs)); | ||
7869 | return Ok(Some(item)); | ||
7870 | } | ||
7871 | if self.eat_keyword(keywords::Const) { | ||
7872 | let const_span = self.prev_span; | ||
7873 | if self.check_keyword(keywords::Fn) | ||
7874 | || (self.check_keyword(keywords::Unsafe) | ||
7875 | && self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) { | ||
7876 | // CONST FUNCTION ITEM | ||
7877 | let unsafety = self.parse_unsafety(); | ||
7878 | self.bump(); | ||
7879 | let (ident, item_, extra_attrs) = | ||
7880 | self.parse_item_fn(unsafety, | ||
7881 | IsAsync::NotAsync, | ||
7882 | respan(const_span, Constness::Const), | ||
7883 | Abi::Rust)?; | ||
7884 | let prev_span = self.prev_span; | ||
7885 | let item = self.mk_item(lo.to(prev_span), | ||
7886 | ident, | ||
7887 | item_, | ||
7888 | visibility, | ||
7889 | maybe_append(attrs, extra_attrs)); | ||
7890 | return Ok(Some(item)); | ||
7891 | } | ||
7892 | |||
7893 | // CONST ITEM | ||
7894 | if self.eat_keyword(keywords::Mut) { | ||
7895 | let prev_span = self.prev_span; | ||
7896 | let mut err = self.diagnostic() | ||
7897 | .struct_span_err(prev_span, "const globals cannot be mutable"); | ||
7898 | err.span_label(prev_span, "cannot be mutable"); | ||
7899 | err.span_suggestion( | ||
7900 | const_span, | ||
7901 | "you might want to declare a static instead", | ||
7902 | "static".to_owned(), | ||
7903 | Applicability::MaybeIncorrect, | ||
7904 | ); | ||
7905 | err.emit(); | ||
7906 | } | ||
7907 | let (ident, item_, extra_attrs) = self.parse_item_const(None)?; | ||
7908 | let prev_span = self.prev_span; | ||
7909 | let item = self.mk_item(lo.to(prev_span), | ||
7910 | ident, | ||
7911 | item_, | ||
7912 | visibility, | ||
7913 | maybe_append(attrs, extra_attrs)); | ||
7914 | return Ok(Some(item)); | ||
7915 | } | ||
7916 | |||
7917 | // `unsafe async fn` or `async fn` | ||
7918 | if ( | ||
7919 | self.check_keyword(keywords::Unsafe) && | ||
7920 | self.look_ahead(1, |t| t.is_keyword(keywords::Async)) | ||
7921 | ) || ( | ||
7922 | self.check_keyword(keywords::Async) && | ||
7923 | self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) | ||
7924 | ) | ||
7925 | { | ||
7926 | // ASYNC FUNCTION ITEM | ||
7927 | let unsafety = self.parse_unsafety(); | ||
7928 | self.expect_keyword(keywords::Async)?; | ||
7929 | self.expect_keyword(keywords::Fn)?; | ||
7930 | let fn_span = self.prev_span; | ||
7931 | let (ident, item_, extra_attrs) = | ||
7932 | self.parse_item_fn(unsafety, | ||
7933 | IsAsync::Async { | ||
7934 | closure_id: ast::DUMMY_NODE_ID, | ||
7935 | return_impl_trait_id: ast::DUMMY_NODE_ID, | ||
7936 | }, | ||
7937 | respan(fn_span, Constness::NotConst), | ||
7938 | Abi::Rust)?; | ||
7939 | let prev_span = self.prev_span; | ||
7940 | let item = self.mk_item(lo.to(prev_span), | ||
7941 | ident, | ||
7942 | item_, | ||
7943 | visibility, | ||
7944 | maybe_append(attrs, extra_attrs)); | ||
7945 | return Ok(Some(item)); | ||
7946 | } | ||
7947 | if self.check_keyword(keywords::Unsafe) && | ||
7948 | (self.look_ahead(1, |t| t.is_keyword(keywords::Trait)) || | ||
7949 | self.look_ahead(1, |t| t.is_keyword(keywords::Auto))) | ||
7950 | { | ||
7951 | // UNSAFE TRAIT ITEM | ||
7952 | self.bump(); // `unsafe` | ||
7953 | let is_auto = if self.eat_keyword(keywords::Trait) { | ||
7954 | IsAuto::No | ||
7955 | } else { | ||
7956 | self.expect_keyword(keywords::Auto)?; | ||
7957 | self.expect_keyword(keywords::Trait)?; | ||
7958 | IsAuto::Yes | ||
7959 | }; | ||
7960 | let (ident, item_, extra_attrs) = | ||
7961 | self.parse_item_trait(is_auto, Unsafety::Unsafe)?; | ||
7962 | let prev_span = self.prev_span; | ||
7963 | let item = self.mk_item(lo.to(prev_span), | ||
7964 | ident, | ||
7965 | item_, | ||
7966 | visibility, | ||
7967 | maybe_append(attrs, extra_attrs)); | ||
7968 | return Ok(Some(item)); | ||
7969 | } | ||
7970 | if self.check_keyword(keywords::Impl) || | ||
7971 | self.check_keyword(keywords::Unsafe) && | ||
7972 | self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) || | ||
7973 | self.check_keyword(keywords::Default) && | ||
7974 | self.look_ahead(1, |t| t.is_keyword(keywords::Impl)) || | ||
7975 | self.check_keyword(keywords::Default) && | ||
7976 | self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe)) { | ||
7977 | // IMPL ITEM | ||
7978 | let defaultness = self.parse_defaultness(); | ||
7979 | let unsafety = self.parse_unsafety(); | ||
7980 | self.expect_keyword(keywords::Impl)?; | ||
7981 | let (ident, item, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?; | ||
7982 | let span = lo.to(self.prev_span); | ||
7983 | return Ok(Some(self.mk_item(span, ident, item, visibility, | ||
7984 | maybe_append(attrs, extra_attrs)))); | ||
7985 | } | ||
7986 | if self.check_keyword(keywords::Fn) { | ||
7987 | // FUNCTION ITEM | ||
7988 | self.bump(); | ||
7989 | let fn_span = self.prev_span; | ||
7990 | let (ident, item_, extra_attrs) = | ||
7991 | self.parse_item_fn(Unsafety::Normal, | ||
7992 | IsAsync::NotAsync, | ||
7993 | respan(fn_span, Constness::NotConst), | ||
7994 | Abi::Rust)?; | ||
7995 | let prev_span = self.prev_span; | ||
7996 | let item = self.mk_item(lo.to(prev_span), | ||
7997 | ident, | ||
7998 | item_, | ||
7999 | visibility, | ||
8000 | maybe_append(attrs, extra_attrs)); | ||
8001 | return Ok(Some(item)); | ||
8002 | } | ||
8003 | if self.check_keyword(keywords::Unsafe) | ||
8004 | && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { | ||
8005 | // UNSAFE FUNCTION ITEM | ||
8006 | self.bump(); // `unsafe` | ||
8007 | // `{` is also expected after `unsafe`, in case of error, include it in the diagnostic | ||
8008 | self.check(&token::OpenDelim(token::Brace)); | ||
8009 | let abi = if self.eat_keyword(keywords::Extern) { | ||
8010 | self.parse_opt_abi()?.unwrap_or(Abi::C) | ||
8011 | } else { | ||
8012 | Abi::Rust | ||
8013 | }; | ||
8014 | self.expect_keyword(keywords::Fn)?; | ||
8015 | let fn_span = self.prev_span; | ||
8016 | let (ident, item_, extra_attrs) = | ||
8017 | self.parse_item_fn(Unsafety::Unsafe, | ||
8018 | IsAsync::NotAsync, | ||
8019 | respan(fn_span, Constness::NotConst), | ||
8020 | abi)?; | ||
8021 | let prev_span = self.prev_span; | ||
8022 | let item = self.mk_item(lo.to(prev_span), | ||
8023 | ident, | ||
8024 | item_, | ||
8025 | visibility, | ||
8026 | maybe_append(attrs, extra_attrs)); | ||
8027 | return Ok(Some(item)); | ||
8028 | } | ||
8029 | if self.eat_keyword(keywords::Mod) { | ||
8030 | // MODULE ITEM | ||
8031 | let (ident, item_, extra_attrs) = | ||
8032 | self.parse_item_mod(&attrs[..])?; | ||
8033 | let prev_span = self.prev_span; | ||
8034 | let item = self.mk_item(lo.to(prev_span), | ||
8035 | ident, | ||
8036 | item_, | ||
8037 | visibility, | ||
8038 | maybe_append(attrs, extra_attrs)); | ||
8039 | return Ok(Some(item)); | ||
8040 | } | ||
8041 | if let Some(type_) = self.eat_type() { | ||
8042 | let (ident, alias, generics) = type_?; | ||
8043 | // TYPE ITEM | ||
8044 | let item_ = match alias { | ||
8045 | AliasKind::Weak(ty) => ItemKind::Ty(ty, generics), | ||
8046 | AliasKind::Existential(bounds) => ItemKind::Existential(bounds, generics), | ||
8047 | }; | ||
8048 | let prev_span = self.prev_span; | ||
8049 | let item = self.mk_item(lo.to(prev_span), | ||
8050 | ident, | ||
8051 | item_, | ||
8052 | visibility, | ||
8053 | attrs); | ||
8054 | return Ok(Some(item)); | ||
8055 | } | ||
8056 | if self.eat_keyword(keywords::Enum) { | ||
8057 | // ENUM ITEM | ||
8058 | let (ident, item_, extra_attrs) = self.parse_item_enum()?; | ||
8059 | let prev_span = self.prev_span; | ||
8060 | let item = self.mk_item(lo.to(prev_span), | ||
8061 | ident, | ||
8062 | item_, | ||
8063 | visibility, | ||
8064 | maybe_append(attrs, extra_attrs)); | ||
8065 | return Ok(Some(item)); | ||
8066 | } | ||
8067 | if self.check_keyword(keywords::Trait) | ||
8068 | || (self.check_keyword(keywords::Auto) | ||
8069 | && self.look_ahead(1, |t| t.is_keyword(keywords::Trait))) | ||
8070 | { | ||
8071 | let is_auto = if self.eat_keyword(keywords::Trait) { | ||
8072 | IsAuto::No | ||
8073 | } else { | ||
8074 | self.expect_keyword(keywords::Auto)?; | ||
8075 | self.expect_keyword(keywords::Trait)?; | ||
8076 | IsAuto::Yes | ||
8077 | }; | ||
8078 | // TRAIT ITEM | ||
8079 | let (ident, item_, extra_attrs) = | ||
8080 | self.parse_item_trait(is_auto, Unsafety::Normal)?; | ||
8081 | let prev_span = self.prev_span; | ||
8082 | let item = self.mk_item(lo.to(prev_span), | ||
8083 | ident, | ||
8084 | item_, | ||
8085 | visibility, | ||
8086 | maybe_append(attrs, extra_attrs)); | ||
8087 | return Ok(Some(item)); | ||
8088 | } | ||
8089 | if self.eat_keyword(keywords::Struct) { | ||
8090 | // STRUCT ITEM | ||
8091 | let (ident, item_, extra_attrs) = self.parse_item_struct()?; | ||
8092 | let prev_span = self.prev_span; | ||
8093 | let item = self.mk_item(lo.to(prev_span), | ||
8094 | ident, | ||
8095 | item_, | ||
8096 | visibility, | ||
8097 | maybe_append(attrs, extra_attrs)); | ||
8098 | return Ok(Some(item)); | ||
8099 | } | ||
8100 | if self.is_union_item() { | ||
8101 | // UNION ITEM | ||
8102 | self.bump(); | ||
8103 | let (ident, item_, extra_attrs) = self.parse_item_union()?; | ||
8104 | let prev_span = self.prev_span; | ||
8105 | let item = self.mk_item(lo.to(prev_span), | ||
8106 | ident, | ||
8107 | item_, | ||
8108 | visibility, | ||
8109 | maybe_append(attrs, extra_attrs)); | ||
8110 | return Ok(Some(item)); | ||
8111 | } | ||
8112 | if let Some(macro_def) = self.eat_macro_def(&attrs, &visibility, lo)? { | ||
8113 | return Ok(Some(macro_def)); | ||
8114 | } | ||
8115 | |||
8116 | // Verify whether we have encountered a struct or method definition where the user forgot to | ||
8117 | // add the `struct` or `fn` keyword after writing `pub`: `pub S {}` | ||
8118 | if visibility.node.is_pub() && | ||
8119 | self.check_ident() && | ||
8120 | self.look_ahead(1, |t| *t != token::Not) | ||
8121 | { | ||
8122 | // Space between `pub` keyword and the identifier | ||
8123 | // | ||
8124 | // pub S {} | ||
8125 | // ^^^ `sp` points here | ||
8126 | let sp = self.prev_span.between(self.span); | ||
8127 | let full_sp = self.prev_span.to(self.span); | ||
8128 | let ident_sp = self.span; | ||
8129 | if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { | ||
8130 | // possible public struct definition where `struct` was forgotten | ||
8131 | let ident = self.parse_ident().unwrap(); | ||
8132 | let msg = format!("add `struct` here to parse `{}` as a public struct", | ||
8133 | ident); | ||
8134 | let mut err = self.diagnostic() | ||
8135 | .struct_span_err(sp, "missing `struct` for struct definition"); | ||
8136 | err.span_suggestion_short( | ||
8137 | sp, &msg, " struct ".into(), Applicability::MaybeIncorrect // speculative | ||
8138 | ); | ||
8139 | return Err(err); | ||
8140 | } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { | ||
8141 | let ident = self.parse_ident().unwrap(); | ||
8142 | self.bump(); // `(` | ||
8143 | let kw_name = if let Ok(Some(_)) = self.parse_self_arg() { | ||
8144 | "method" | ||
8145 | } else { | ||
8146 | "function" | ||
8147 | }; | ||
8148 | self.consume_block(token::Paren); | ||
8149 | let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { | ||
8150 | self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); | ||
8151 | self.bump(); // `{` | ||
8152 | ("fn", kw_name, false) | ||
8153 | } else if self.check(&token::OpenDelim(token::Brace)) { | ||
8154 | self.bump(); // `{` | ||
8155 | ("fn", kw_name, false) | ||
8156 | } else if self.check(&token::Colon) { | ||
8157 | let kw = "struct"; | ||
8158 | (kw, kw, false) | ||
8159 | } else { | ||
8160 | ("fn` or `struct", "function or struct", true) | ||
8161 | }; | ||
8162 | self.consume_block(token::Brace); | ||
8163 | |||
8164 | let msg = format!("missing `{}` for {} definition", kw, kw_name); | ||
8165 | let mut err = self.diagnostic().struct_span_err(sp, &msg); | ||
8166 | if !ambiguous { | ||
8167 | let suggestion = format!("add `{}` here to parse `{}` as a public {}", | ||
8168 | kw, | ||
8169 | ident, | ||
8170 | kw_name); | ||
8171 | err.span_suggestion_short( | ||
8172 | sp, &suggestion, format!(" {} ", kw), Applicability::MachineApplicable | ||
8173 | ); | ||
8174 | } else { | ||
8175 | if let Ok(snippet) = self.sess.source_map().span_to_snippet(ident_sp) { | ||
8176 | err.span_suggestion( | ||
8177 | full_sp, | ||
8178 | "if you meant to call a macro, try", | ||
8179 | format!("{}!", snippet), | ||
8180 | // this is the `ambiguous` conditional branch | ||
8181 | Applicability::MaybeIncorrect | ||
8182 | ); | ||
8183 | } else { | ||
8184 | err.help("if you meant to call a macro, remove the `pub` \ | ||
8185 | and add a trailing `!` after the identifier"); | ||
8186 | } | ||
8187 | } | ||
8188 | return Err(err); | ||
8189 | } else if self.look_ahead(1, |t| *t == token::Lt) { | ||
8190 | let ident = self.parse_ident().unwrap(); | ||
8191 | self.eat_to_tokens(&[&token::Gt]); | ||
8192 | self.bump(); // `>` | ||
8193 | let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { | ||
8194 | if let Ok(Some(_)) = self.parse_self_arg() { | ||
8195 | ("fn", "method", false) | ||
8196 | } else { | ||
8197 | ("fn", "function", false) | ||
8198 | } | ||
8199 | } else if self.check(&token::OpenDelim(token::Brace)) { | ||
8200 | ("struct", "struct", false) | ||
8201 | } else { | ||
8202 | ("fn` or `struct", "function or struct", true) | ||
8203 | }; | ||
8204 | let msg = format!("missing `{}` for {} definition", kw, kw_name); | ||
8205 | let mut err = self.diagnostic().struct_span_err(sp, &msg); | ||
8206 | if !ambiguous { | ||
8207 | err.span_suggestion_short( | ||
8208 | sp, | ||
8209 | &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), | ||
8210 | format!(" {} ", kw), | ||
8211 | Applicability::MachineApplicable, | ||
8212 | ); | ||
8213 | } | ||
8214 | return Err(err); | ||
8215 | } | ||
8216 | } | ||
8217 | self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility) | ||
8218 | } | ||
8219 | |||
8220 | /// Parses a foreign item. | ||
8221 | crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> { | ||
8222 | maybe_whole!(self, NtForeignItem, |ni| ni); | ||
8223 | |||
8224 | let attrs = self.parse_outer_attributes()?; | ||
8225 | let lo = self.span; | ||
8226 | let visibility = self.parse_visibility(false)?; | ||
8227 | |||
8228 | // FOREIGN STATIC ITEM | ||
8229 | // Treat `const` as `static` for error recovery, but don't add it to expected tokens. | ||
8230 | if self.check_keyword(keywords::Static) || self.token.is_keyword(keywords::Const) { | ||
8231 | if self.token.is_keyword(keywords::Const) { | ||
8232 | self.diagnostic() | ||
8233 | .struct_span_err(self.span, "extern items cannot be `const`") | ||
8234 | .span_suggestion( | ||
8235 | self.span, | ||
8236 | "try using a static value", | ||
8237 | "static".to_owned(), | ||
8238 | Applicability::MachineApplicable | ||
8239 | ).emit(); | ||
8240 | } | ||
8241 | self.bump(); // `static` or `const` | ||
8242 | return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?); | ||
8243 | } | ||
8244 | // FOREIGN FUNCTION ITEM | ||
8245 | if self.check_keyword(keywords::Fn) { | ||
8246 | return Ok(self.parse_item_foreign_fn(visibility, lo, attrs)?); | ||
8247 | } | ||
8248 | // FOREIGN TYPE ITEM | ||
8249 | if self.check_keyword(keywords::Type) { | ||
8250 | return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?); | ||
8251 | } | ||
8252 | |||
8253 | match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? { | ||
8254 | Some(mac) => { | ||
8255 | Ok( | ||
8256 | ForeignItem { | ||
8257 | ident: keywords::Invalid.ident(), | ||
8258 | span: lo.to(self.prev_span), | ||
8259 | id: ast::DUMMY_NODE_ID, | ||
8260 | attrs, | ||
8261 | vis: visibility, | ||
8262 | node: ForeignItemKind::Macro(mac), | ||
8263 | } | ||
8264 | ) | ||
8265 | } | ||
8266 | None => { | ||
8267 | if !attrs.is_empty() { | ||
8268 | self.expected_item_err(&attrs)?; | ||
8269 | } | ||
8270 | |||
8271 | self.unexpected() | ||
8272 | } | ||
8273 | } | ||
8274 | } | ||
8275 | |||
8276 | /// This is the fall-through for parsing items. | ||
8277 | fn parse_macro_use_or_failure( | ||
8278 | &mut self, | ||
8279 | attrs: Vec<Attribute> , | ||
8280 | macros_allowed: bool, | ||
8281 | attributes_allowed: bool, | ||
8282 | lo: Span, | ||
8283 | visibility: Visibility | ||
8284 | ) -> PResult<'a, Option<P<Item>>> { | ||
8285 | if macros_allowed && self.token.is_path_start() { | ||
8286 | // MACRO INVOCATION ITEM | ||
8287 | |||
8288 | let prev_span = self.prev_span; | ||
8289 | self.complain_if_pub_macro(&visibility.node, prev_span); | ||
8290 | |||
8291 | let mac_lo = self.span; | ||
8292 | |||
8293 | // item macro. | ||
8294 | let pth = self.parse_path(PathStyle::Mod)?; | ||
8295 | self.expect(&token::Not)?; | ||
8296 | |||
8297 | // a 'special' identifier (like what `macro_rules!` uses) | ||
8298 | // is optional. We should eventually unify invoc syntax | ||
8299 | // and remove this. | ||
8300 | let id = if self.token.is_ident() { | ||
8301 | self.parse_ident()? | ||
8302 | } else { | ||
8303 | keywords::Invalid.ident() // no special identifier | ||
8304 | }; | ||
8305 | // eat a matched-delimiter token tree: | ||
8306 | let (delim, tts) = self.expect_delimited_token_tree()?; | ||
8307 | if delim != MacDelimiter::Brace { | ||
8308 | if !self.eat(&token::Semi) { | ||
8309 | self.span_err(self.prev_span, | ||
8310 | "macros that expand to items must either \ | ||
8311 | be surrounded with braces or followed by \ | ||
8312 | a semicolon"); | ||
8313 | } | ||
8314 | } | ||
8315 | |||
8316 | let hi = self.prev_span; | ||
8317 | let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim }); | ||
8318 | let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs); | ||
8319 | return Ok(Some(item)); | ||
8320 | } | ||
8321 | |||
8322 | // FAILURE TO PARSE ITEM | ||
8323 | match visibility.node { | ||
8324 | VisibilityKind::Inherited => {} | ||
8325 | _ => { | ||
8326 | return Err(self.span_fatal(self.prev_span, "unmatched visibility `pub`")); | ||
8327 | } | ||
8328 | } | ||
8329 | |||
8330 | if !attributes_allowed && !attrs.is_empty() { | ||
8331 | self.expected_item_err(&attrs)?; | ||
8332 | } | ||
8333 | Ok(None) | ||
8334 | } | ||
8335 | |||
8336 | /// Parses a macro invocation inside a `trait`, `impl` or `extern` block. | ||
8337 | fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>, | ||
8338 | at_end: &mut bool) -> PResult<'a, Option<Mac>> | ||
8339 | { | ||
8340 | if self.token.is_path_start() { | ||
8341 | let prev_span = self.prev_span; | ||
8342 | let lo = self.span; | ||
8343 | let pth = self.parse_path(PathStyle::Mod)?; | ||
8344 | |||
8345 | if pth.segments.len() == 1 { | ||
8346 | if !self.eat(&token::Not) { | ||
8347 | return Err(self.missing_assoc_item_kind_err(item_kind, prev_span)); | ||
8348 | } | ||
8349 | } else { | ||
8350 | self.expect(&token::Not)?; | ||
8351 | } | ||
8352 | |||
8353 | if let Some(vis) = vis { | ||
8354 | self.complain_if_pub_macro(&vis.node, prev_span); | ||
8355 | } | ||
8356 | |||
8357 | *at_end = true; | ||
8358 | |||
8359 | // eat a matched-delimiter token tree: | ||
8360 | let (delim, tts) = self.expect_delimited_token_tree()?; | ||
8361 | if delim != MacDelimiter::Brace { | ||
8362 | self.expect(&token::Semi)?; | ||
8363 | } | ||
8364 | |||
8365 | Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts, delim }))) | ||
8366 | } else { | ||
8367 | Ok(None) | ||
8368 | } | ||
8369 | } | ||
8370 | |||
8371 | fn collect_tokens<F, R>(&mut self, f: F) -> PResult<'a, (R, TokenStream)> | ||
8372 | where F: FnOnce(&mut Self) -> PResult<'a, R> | ||
8373 | { | ||
8374 | // Record all tokens we parse when parsing this item. | ||
8375 | let mut tokens = Vec::new(); | ||
8376 | let prev_collecting = match self.token_cursor.frame.last_token { | ||
8377 | LastToken::Collecting(ref mut list) => { | ||
8378 | Some(mem::replace(list, Vec::new())) | ||
8379 | } | ||
8380 | LastToken::Was(ref mut last) => { | ||
8381 | tokens.extend(last.take()); | ||
8382 | None | ||
8383 | } | ||
8384 | }; | ||
8385 | self.token_cursor.frame.last_token = LastToken::Collecting(tokens); | ||
8386 | let prev = self.token_cursor.stack.len(); | ||
8387 | let ret = f(self); | ||
8388 | let last_token = if self.token_cursor.stack.len() == prev { | ||
8389 | &mut self.token_cursor.frame.last_token | ||
8390 | } else { | ||
8391 | &mut self.token_cursor.stack[prev].last_token | ||
8392 | }; | ||
8393 | |||
8394 | // Pull out the tokens that we've collected from the call to `f` above. | ||
8395 | let mut collected_tokens = match *last_token { | ||
8396 | LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()), | ||
8397 | LastToken::Was(_) => panic!("our vector went away?"), | ||
8398 | }; | ||
8399 | |||
8400 | // If we're not at EOF our current token wasn't actually consumed by | ||
8401 | // `f`, but it'll still be in our list that we pulled out. In that case | ||
8402 | // put it back. | ||
8403 | let extra_token = if self.token != token::Eof { | ||
8404 | collected_tokens.pop() | ||
8405 | } else { | ||
8406 | None | ||
8407 | }; | ||
8408 | |||
8409 | // If we were previously collecting tokens, then this was a recursive | ||
8410 | // call. In that case we need to record all the tokens we collected in | ||
8411 | // our parent list as well. To do that we push a clone of our stream | ||
8412 | // onto the previous list. | ||
8413 | match prev_collecting { | ||
8414 | Some(mut list) => { | ||
8415 | list.extend(collected_tokens.iter().cloned()); | ||
8416 | list.extend(extra_token); | ||
8417 | *last_token = LastToken::Collecting(list); | ||
8418 | } | ||
8419 | None => { | ||
8420 | *last_token = LastToken::Was(extra_token); | ||
8421 | } | ||
8422 | } | ||
8423 | |||
8424 | Ok((ret?, TokenStream::new(collected_tokens))) | ||
8425 | } | ||
8426 | |||
8427 | pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> { | ||
8428 | let attrs = self.parse_outer_attributes()?; | ||
8429 | self.parse_item_(attrs, true, false) | ||
8430 | } | ||
8431 | |||
8432 | /// `::{` or `::*` | ||
8433 | fn is_import_coupler(&mut self) -> bool { | ||
8434 | self.check(&token::ModSep) && | ||
8435 | self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) || | ||
8436 | *t == token::BinOp(token::Star)) | ||
8437 | } | ||
8438 | |||
8439 | /// Parses a `UseTree`. | ||
8440 | /// | ||
8441 | /// ``` | ||
8442 | /// USE_TREE = [`::`] `*` | | ||
8443 | /// [`::`] `{` USE_TREE_LIST `}` | | ||
8444 | /// PATH `::` `*` | | ||
8445 | /// PATH `::` `{` USE_TREE_LIST `}` | | ||
8446 | /// PATH [`as` IDENT] | ||
8447 | /// ``` | ||
8448 | fn parse_use_tree(&mut self) -> PResult<'a, UseTree> { | ||
8449 | let lo = self.span; | ||
8450 | |||
8451 | let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() }; | ||
8452 | let kind = if self.check(&token::OpenDelim(token::Brace)) || | ||
8453 | self.check(&token::BinOp(token::Star)) || | ||
8454 | self.is_import_coupler() { | ||
8455 | // `use *;` or `use ::*;` or `use {...};` or `use ::{...};` | ||
8456 | let mod_sep_ctxt = self.span.ctxt(); | ||
8457 | if self.eat(&token::ModSep) { | ||
8458 | prefix.segments.push( | ||
8459 | PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)) | ||
8460 | ); | ||
8461 | } | ||
8462 | |||
8463 | if self.eat(&token::BinOp(token::Star)) { | ||
8464 | UseTreeKind::Glob | ||
8465 | } else { | ||
8466 | UseTreeKind::Nested(self.parse_use_tree_list()?) | ||
8467 | } | ||
8468 | } else { | ||
8469 | // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;` | ||
8470 | prefix = self.parse_path(PathStyle::Mod)?; | ||
8471 | |||
8472 | if self.eat(&token::ModSep) { | ||
8473 | if self.eat(&token::BinOp(token::Star)) { | ||
8474 | UseTreeKind::Glob | ||
8475 | } else { | ||
8476 | UseTreeKind::Nested(self.parse_use_tree_list()?) | ||
8477 | } | ||
8478 | } else { | ||
8479 | UseTreeKind::Simple(self.parse_rename()?, ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID) | ||
8480 | } | ||
8481 | }; | ||
8482 | |||
8483 | Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) }) | ||
8484 | } | ||
8485 | |||
8486 | /// Parses a `UseTreeKind::Nested(list)`. | ||
8487 | /// | ||
8488 | /// ``` | ||
8489 | /// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`] | ||
8490 | /// ``` | ||
8491 | fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> { | ||
8492 | self.parse_unspanned_seq(&token::OpenDelim(token::Brace), | ||
8493 | &token::CloseDelim(token::Brace), | ||
8494 | SeqSep::trailing_allowed(token::Comma), |this| { | ||
8495 | Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID)) | ||
8496 | }) | ||
8497 | } | ||
8498 | |||
8499 | fn parse_rename(&mut self) -> PResult<'a, Option<Ident>> { | ||
8500 | if self.eat_keyword(keywords::As) { | ||
8501 | self.parse_ident_or_underscore().map(Some) | ||
8502 | } else { | ||
8503 | Ok(None) | ||
8504 | } | ||
8505 | } | ||
8506 | |||
8507 | /// Parses a source module as a crate. This is the main entry point for the parser. | ||
8508 | pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { | ||
8509 | let lo = self.span; | ||
8510 | let krate = Ok(ast::Crate { | ||
8511 | attrs: self.parse_inner_attributes()?, | ||
8512 | module: self.parse_mod_items(&token::Eof, lo)?, | ||
8513 | span: lo.to(self.span), | ||
8514 | }); | ||
8515 | emit_unclosed_delims(&self.unclosed_delims, self.diagnostic()); | ||
8516 | self.unclosed_delims.clear(); | ||
8517 | krate | ||
8518 | } | ||
8519 | |||
8520 | pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> { | ||
8521 | let ret = match self.token { | ||
8522 | token::Literal(token::Str_(s), suf) => (s, ast::StrStyle::Cooked, suf), | ||
8523 | token::Literal(token::StrRaw(s, n), suf) => (s, ast::StrStyle::Raw(n), suf), | ||
8524 | _ => return None | ||
8525 | }; | ||
8526 | self.bump(); | ||
8527 | Some(ret) | ||
8528 | } | ||
8529 | |||
8530 | pub fn parse_str(&mut self) -> PResult<'a, (Symbol, StrStyle)> { | ||
8531 | match self.parse_optional_str() { | ||
8532 | Some((s, style, suf)) => { | ||
8533 | let sp = self.prev_span; | ||
8534 | self.expect_no_suffix(sp, "string literal", suf); | ||
8535 | Ok((s, style)) | ||
8536 | } | ||
8537 | _ => { | ||
8538 | let msg = "expected string literal"; | ||
8539 | let mut err = self.fatal(msg); | ||
8540 | err.span_label(self.span, msg); | ||
8541 | Err(err) | ||
8542 | } | ||
8543 | } | ||
8544 | } | ||
8545 | } | ||
8546 | |||
8547 | pub fn emit_unclosed_delims(unclosed_delims: &[UnmatchedBrace], handler: &errors::Handler) { | ||
8548 | for unmatched in unclosed_delims { | ||
8549 | let mut err = handler.struct_span_err(unmatched.found_span, &format!( | ||
8550 | "incorrect close delimiter: `{}`", | ||
8551 | pprust::token_to_string(&token::Token::CloseDelim(unmatched.found_delim)), | ||
8552 | )); | ||
8553 | err.span_label(unmatched.found_span, "incorrect close delimiter"); | ||
8554 | if let Some(sp) = unmatched.candidate_span { | ||
8555 | err.span_label(sp, "close delimiter possibly meant for this"); | ||
8556 | } | ||
8557 | if let Some(sp) = unmatched.unclosed_span { | ||
8558 | err.span_label(sp, "un-closed delimiter"); | ||
8559 | } | ||
8560 | err.emit(); | ||
8561 | } | ||
8562 | } | ||
diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 4a1229a31..9d0cd1af5 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs | |||
@@ -1,7 +1,8 @@ | |||
1 | use expect_test::{expect_file, ExpectFile}; | 1 | use expect_test::{expect_file, ExpectFile}; |
2 | use ide_db::SymbolKind; | ||
2 | use test_utils::{bench, bench_fixture, skip_slow_tests}; | 3 | use test_utils::{bench, bench_fixture, skip_slow_tests}; |
3 | 4 | ||
4 | use crate::{fixture, FileRange, TextRange}; | 5 | use crate::{fixture, FileRange, HlTag, TextRange}; |
5 | 6 | ||
6 | #[test] | 7 | #[test] |
7 | fn test_highlighting() { | 8 | fn test_highlighting() { |
@@ -226,7 +227,7 @@ fn bar() { | |||
226 | } | 227 | } |
227 | 228 | ||
228 | #[test] | 229 | #[test] |
229 | fn benchmark_syntax_highlighting() { | 230 | fn benchmark_syntax_highlighting_long_struct() { |
230 | if skip_slow_tests() { | 231 | if skip_slow_tests() { |
231 | return; | 232 | return; |
232 | } | 233 | } |
@@ -235,10 +236,36 @@ fn benchmark_syntax_highlighting() { | |||
235 | let (analysis, file_id) = fixture::file(&fixture); | 236 | let (analysis, file_id) = fixture::file(&fixture); |
236 | 237 | ||
237 | let hash = { | 238 | let hash = { |
238 | let _pt = bench("syntax highlighting"); | 239 | let _pt = bench("syntax highlighting long struct"); |
239 | analysis.highlight(file_id).unwrap().len() | 240 | analysis |
241 | .highlight(file_id) | ||
242 | .unwrap() | ||
243 | .iter() | ||
244 | .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct)) | ||
245 | .count() | ||
240 | }; | 246 | }; |
241 | assert_eq!(hash, 32009); | 247 | assert_eq!(hash, 2001); |
248 | } | ||
249 | |||
250 | #[test] | ||
251 | fn benchmark_syntax_highlighting_parser() { | ||
252 | if skip_slow_tests() { | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | let fixture = bench_fixture::glorious_old_parser(); | ||
257 | let (analysis, file_id) = fixture::file(&fixture); | ||
258 | |||
259 | let hash = { | ||
260 | let _pt = bench("syntax highlighting parser"); | ||
261 | analysis | ||
262 | .highlight(file_id) | ||
263 | .unwrap() | ||
264 | .iter() | ||
265 | .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function)) | ||
266 | .count() | ||
267 | }; | ||
268 | assert_eq!(hash, 1629); | ||
242 | } | 269 | } |
243 | 270 | ||
244 | #[test] | 271 | #[test] |
diff --git a/crates/syntax/src/tests.rs b/crates/syntax/src/tests.rs index 9d3433c9d..b2c06e24f 100644 --- a/crates/syntax/src/tests.rs +++ b/crates/syntax/src/tests.rs | |||
@@ -4,11 +4,12 @@ use std::{ | |||
4 | path::{Path, PathBuf}, | 4 | path::{Path, PathBuf}, |
5 | }; | 5 | }; |
6 | 6 | ||
7 | use ast::NameOwner; | ||
7 | use expect_test::expect_file; | 8 | use expect_test::expect_file; |
8 | use rayon::prelude::*; | 9 | use rayon::prelude::*; |
9 | use test_utils::project_dir; | 10 | use test_utils::{bench, bench_fixture, project_dir, skip_slow_tests}; |
10 | 11 | ||
11 | use crate::{fuzz, tokenize, SourceFile, SyntaxError, TextRange, TextSize, Token}; | 12 | use crate::{ast, fuzz, tokenize, AstNode, SourceFile, SyntaxError, TextRange, TextSize, Token}; |
12 | 13 | ||
13 | #[test] | 14 | #[test] |
14 | fn lexer_tests() { | 15 | fn lexer_tests() { |
@@ -42,6 +43,28 @@ fn main() { | |||
42 | } | 43 | } |
43 | 44 | ||
44 | #[test] | 45 | #[test] |
46 | fn benchmark_parser() { | ||
47 | if skip_slow_tests() { | ||
48 | return; | ||
49 | } | ||
50 | let data = bench_fixture::glorious_old_parser(); | ||
51 | let tree = { | ||
52 | let _b = bench("parsing"); | ||
53 | let p = SourceFile::parse(&data); | ||
54 | assert!(p.errors.is_empty()); | ||
55 | assert_eq!(p.tree().syntax.text_range().len(), 352474.into()); | ||
56 | p.tree() | ||
57 | }; | ||
58 | |||
59 | { | ||
60 | let _b = bench("tree traversal"); | ||
61 | let fn_names = | ||
62 | tree.syntax().descendants().filter_map(ast::Fn::cast).filter_map(|f| f.name()).count(); | ||
63 | assert_eq!(fn_names, 268); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | #[test] | ||
45 | fn parser_tests() { | 68 | fn parser_tests() { |
46 | dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], "rast", |text, path| { | 69 | dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], "rast", |text, path| { |
47 | let parse = SourceFile::parse(text); | 70 | let parse = SourceFile::parse(text); |
@@ -128,7 +151,6 @@ fn reparse_fuzz_tests() { | |||
128 | } | 151 | } |
129 | 152 | ||
130 | /// Test that Rust-analyzer can parse and validate the rust-analyzer | 153 | /// Test that Rust-analyzer can parse and validate the rust-analyzer |
131 | /// FIXME: Use this as a benchmark | ||
132 | #[test] | 154 | #[test] |
133 | fn self_hosting_parsing() { | 155 | fn self_hosting_parsing() { |
134 | let dir = project_dir().join("crates"); | 156 | let dir = project_dir().join("crates"); |
diff --git a/crates/test_utils/src/bench_fixture.rs b/crates/test_utils/src/bench_fixture.rs index 41fcca635..aa1bea9bb 100644 --- a/crates/test_utils/src/bench_fixture.rs +++ b/crates/test_utils/src/bench_fixture.rs | |||
@@ -1,7 +1,11 @@ | |||
1 | //! Generates large snippets of Rust code for usage in the benchmarks. | 1 | //! Generates large snippets of Rust code for usage in the benchmarks. |
2 | 2 | ||
3 | use std::fs; | ||
4 | |||
3 | use stdx::format_to; | 5 | use stdx::format_to; |
4 | 6 | ||
7 | use crate::project_dir; | ||
8 | |||
5 | pub fn big_struct() -> String { | 9 | pub fn big_struct() -> String { |
6 | let n = 1_000; | 10 | let n = 1_000; |
7 | 11 | ||
@@ -26,3 +30,8 @@ struct S{} {{ | |||
26 | 30 | ||
27 | buf | 31 | buf |
28 | } | 32 | } |
33 | |||
34 | pub fn glorious_old_parser() -> String { | ||
35 | let path = project_dir().join("bench_data/glorious_old_parser"); | ||
36 | fs::read_to_string(&path).unwrap() | ||
37 | } | ||