solar_parse/parser/
item.rs

1use super::{ExpectedToken, SeqSep};
2use crate::{PResult, Parser};
3use itertools::Itertools;
4use smallvec::SmallVec;
5use solar_ast::{token::*, *};
6use solar_interface::{diagnostics::DiagMsg, error_code, kw, sym, Ident, Span};
7
8impl<'sess, 'ast> Parser<'sess, 'ast> {
9    /// Parses a source unit.
10    #[instrument(level = "debug", skip_all)]
11    pub fn parse_file(&mut self) -> PResult<'sess, SourceUnit<'ast>> {
12        self.parse_items(TokenKind::Eof).map(SourceUnit::new)
13    }
14
15    /// Parses a list of items until the given token is encountered.
16    fn parse_items(&mut self, end: TokenKind) -> PResult<'sess, Box<'ast, [Item<'ast>]>> {
17        let get_msg_note = |this: &mut Self| {
18            let (prefix, list, link);
19            if this.in_contract {
20                prefix = "contract";
21                list = "function, variable, struct, or modifier definition";
22                link = "contractBodyElement";
23            } else {
24                prefix = "global";
25                list = "pragma, import directive, contract, interface, library, struct, enum, constant, function, modifier, or error definition";
26                link = "sourceUnit";
27            }
28            let msg =
29                format!("expected {prefix} item ({list}), found {}", this.token.full_description());
30            let note = format!("for a full list of valid {prefix} items, see <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.{link}>");
31            (msg, note)
32        };
33
34        let mut items = Vec::new();
35        while let Some(item) = self.parse_item()? {
36            if self.in_contract && !item.is_allowed_in_contract() {
37                let msg = format!("{}s are not allowed in contracts", item.description());
38                let (_, note) = get_msg_note(self);
39                self.dcx().err(msg).span(item.span).note(note).emit();
40            } else {
41                items.push(item);
42            }
43        }
44        if !self.eat(end) {
45            let (msg, note) = get_msg_note(self);
46            return Err(self.dcx().err(msg).span(self.token.span).note(note));
47        }
48        Ok(self.alloc_vec(items))
49    }
50
51    /// Parses an item.
52    #[instrument(level = "debug", skip_all)]
53    pub fn parse_item(&mut self) -> PResult<'sess, Option<Item<'ast>>> {
54        let docs = self.parse_doc_comments();
55        self.parse_spanned(Self::parse_item_kind)
56            .map(|(span, kind)| kind.map(|kind| Item { docs, span, kind }))
57    }
58
59    fn parse_item_kind(&mut self) -> PResult<'sess, Option<ItemKind<'ast>>> {
60        let kind = if self.is_function_like() {
61            self.parse_function().map(ItemKind::Function)
62        } else if self.eat_keyword(kw::Struct) {
63            self.parse_struct().map(ItemKind::Struct)
64        } else if self.eat_keyword(kw::Event) {
65            self.parse_event().map(ItemKind::Event)
66        } else if self.is_contract_like() {
67            self.parse_contract().map(ItemKind::Contract)
68        } else if self.eat_keyword(kw::Enum) {
69            self.parse_enum().map(ItemKind::Enum)
70        } else if self.eat_keyword(kw::Type) {
71            self.parse_udvt().map(ItemKind::Udvt)
72        } else if self.eat_keyword(kw::Pragma) {
73            self.parse_pragma().map(ItemKind::Pragma)
74        } else if self.eat_keyword(kw::Import) {
75            self.parse_import().map(ItemKind::Import)
76        } else if self.eat_keyword(kw::Using) {
77            self.parse_using().map(ItemKind::Using)
78        } else if self.check_keyword(sym::error)
79            && self.look_ahead(1).is_ident()
80            && self.look_ahead(2).is_open_delim(Delimiter::Parenthesis)
81        {
82            self.bump(); // `error`
83            self.parse_error().map(ItemKind::Error)
84        } else if self.is_variable_declaration() {
85            let flags = if self.in_contract { VarFlags::STATE_VAR } else { VarFlags::CONSTANT_VAR };
86            self.parse_variable_definition(flags).map(ItemKind::Variable)
87        } else {
88            return Ok(None);
89        };
90        kind.map(Some)
91    }
92
93    /// Returns `true` if the current token is the start of a function definition.
94    fn is_function_like(&self) -> bool {
95        (self.token.is_keyword(kw::Function)
96            && !self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
97            || self.token.is_keyword_any(&[
98                kw::Constructor,
99                kw::Fallback,
100                kw::Receive,
101                kw::Modifier,
102            ])
103    }
104
105    /// Returns `true` if the current token is the start of a contract definition.
106    fn is_contract_like(&self) -> bool {
107        self.token.is_keyword_any(&[kw::Abstract, kw::Contract, kw::Interface, kw::Library])
108    }
109
110    /// Returns `true` if the current token is the start of a variable declaration.
111    pub(super) fn is_variable_declaration(&self) -> bool {
112        // https://github.com/ethereum/solidity/blob/194b114664c7daebc2ff68af3c573272f5d28913/libsolidity/parsing/Parser.cpp#L2451
113        self.token.is_non_reserved_ident(false) || self.is_non_custom_variable_declaration()
114    }
115
116    pub(super) fn is_non_custom_variable_declaration(&self) -> bool {
117        self.token.is_keyword(kw::Mapping)
118            || (self.token.is_keyword(kw::Function)
119                && self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
120            || self.token.is_elementary_type()
121    }
122
123    /* ----------------------------------------- Items ----------------------------------------- */
124    // These functions expect that the keyword has already been eaten unless otherwise noted.
125
126    /// Parses a function definition.
127    ///
128    /// Expects the current token to be a function-like keyword.
129    fn parse_function(&mut self) -> PResult<'sess, ItemFunction<'ast>> {
130        let Token { span: lo, kind: TokenKind::Ident(kw) } = self.token else {
131            unreachable!("parse_function called without function-like keyword");
132        };
133        self.bump(); // kw
134
135        let kind = match kw {
136            kw::Constructor => FunctionKind::Constructor,
137            kw::Function => FunctionKind::Function,
138            kw::Fallback => FunctionKind::Fallback,
139            kw::Receive => FunctionKind::Receive,
140            kw::Modifier => FunctionKind::Modifier,
141            _ => unreachable!("parse_function called without function-like keyword"),
142        };
143        let flags = FunctionFlags::from_kind(kind);
144        let header = self.parse_function_header(flags)?;
145        let (body_span, body) = self.parse_spanned(|this| {
146            Ok(if !flags.contains(FunctionFlags::ONLY_BLOCK) && this.eat(TokenKind::Semi) {
147                None
148            } else {
149                Some(this.parse_block()?)
150            })
151        })?;
152
153        if !self.in_contract && !kind.allowed_in_global() {
154            let msg = format!("{kind}s are not allowed in the global scope");
155            self.dcx().err(msg).span(lo.to(self.prev_token.span)).emit();
156        }
157        // All function kinds are allowed in contracts.
158
159        Ok(ItemFunction { kind, header, body, body_span })
160    }
161
162    /// Parses a function a header.
163    pub(super) fn parse_function_header(
164        &mut self,
165        flags: FunctionFlags,
166    ) -> PResult<'sess, FunctionHeader<'ast>> {
167        let mut header = FunctionHeader::default();
168        let var_flags = if flags.contains(FunctionFlags::PARAM_NAME) {
169            VarFlags::FUNCTION_TY
170        } else {
171            VarFlags::FUNCTION
172        };
173
174        if flags.contains(FunctionFlags::NAME) {
175            // Allow and warn on `function fallback` or `function receive`.
176            let ident;
177            if flags == FunctionFlags::FUNCTION
178                && self.token.is_keyword_any(&[kw::Fallback, kw::Receive])
179            {
180                let kw_span = self.prev_token.span;
181                ident = self.parse_ident_any()?;
182                let msg = format!("function named `{ident}`");
183                let mut warn = self.dcx().warn(msg).span(ident.span).code(error_code!(3445));
184                if self.in_contract {
185                    let help = format!("remove the `function` keyword if you intend this to be a contract's {ident} function");
186                    warn = warn.span_help(kw_span, help);
187                }
188                warn.emit();
189            } else {
190                ident = self.parse_ident()?;
191            }
192            header.name = Some(ident);
193        } else if self.token.is_non_reserved_ident(false) {
194            let msg = "function names are not allowed here";
195            self.dcx().err(msg).span(self.token.span).emit();
196            self.bump();
197        }
198
199        if flags.contains(FunctionFlags::NO_PARENS)
200            && !self.token.is_open_delim(Delimiter::Parenthesis)
201        {
202            // Omitted parens.
203        } else {
204            header.parameters = self.parse_parameter_list(true, var_flags)?;
205        }
206
207        let mut modifiers = Vec::new();
208        loop {
209            // This is needed to skip parsing surrounding variable's visibility in function types.
210            // E.g. in `function(uint) external internal e;` the `internal` is the surrounding
211            // variable's visibility, not the function's.
212            // HACK: Ugly way to add an extra guard to `if let` without the unstable `let-chains`.
213            // Ideally this would be `if let Some(_) = _ && guard { ... }`.
214            let vis_guard = (!(flags == FunctionFlags::FUNCTION_TY && header.visibility.is_some()))
215                .then_some(());
216            if let Some(visibility) = vis_guard.and_then(|()| self.parse_visibility()) {
217                if !flags.contains(FunctionFlags::from_visibility(visibility)) {
218                    let msg = visibility_error(visibility, flags.visibilities());
219                    self.dcx().err(msg).span(self.prev_token.span).emit();
220                } else if header.visibility.is_some() {
221                    let msg = "visibility already specified";
222                    self.dcx().err(msg).span(self.prev_token.span).emit();
223                } else {
224                    header.visibility = Some(visibility);
225                }
226            } else if let Some(state_mutability) = self.parse_state_mutability() {
227                if !flags.contains(FunctionFlags::from_state_mutability(state_mutability)) {
228                    let msg = state_mutability_error(state_mutability, flags.state_mutabilities());
229                    self.dcx().err(msg).span(self.prev_token.span).emit();
230                } else if !header.state_mutability.is_non_payable() {
231                    let msg = "state mutability already specified";
232                    self.dcx().err(msg).span(self.prev_token.span).emit();
233                } else {
234                    header.state_mutability = state_mutability;
235                }
236            } else if self.eat_keyword(kw::Virtual) {
237                if !flags.contains(FunctionFlags::VIRTUAL) {
238                    let msg = "`virtual` is not allowed here";
239                    self.dcx().err(msg).span(self.prev_token.span).emit();
240                } else if header.virtual_ {
241                    let msg = "virtual already specified";
242                    self.dcx().err(msg).span(self.prev_token.span).emit();
243                } else {
244                    header.virtual_ = true;
245                }
246            } else if self.eat_keyword(kw::Override) {
247                let o = self.parse_override()?;
248                if !flags.contains(FunctionFlags::OVERRIDE) {
249                    let msg = "`override` is not allowed here";
250                    self.dcx().err(msg).span(self.prev_token.span).emit();
251                } else if header.override_.is_some() {
252                    let msg = "override already specified";
253                    self.dcx().err(msg).span(self.prev_token.span).emit();
254                } else {
255                    header.override_ = Some(o);
256                }
257            } else if flags.contains(FunctionFlags::MODIFIERS)
258                && self.token.is_non_reserved_ident(false)
259            {
260                modifiers.push(self.parse_modifier()?);
261            } else {
262                break;
263            }
264        }
265
266        header.modifiers = self.alloc_vec(modifiers);
267
268        if flags.contains(FunctionFlags::RETURNS) && self.eat_keyword(kw::Returns) {
269            header.returns = self.parse_parameter_list(false, var_flags)?;
270        }
271
272        Ok(header)
273    }
274
275    /// Parses a struct definition.
276    fn parse_struct(&mut self) -> PResult<'sess, ItemStruct<'ast>> {
277        let name = self.parse_ident()?;
278        let fields = self.parse_delim_seq(
279            Delimiter::Brace,
280            SeqSep::trailing_enforced(TokenKind::Semi),
281            true,
282            |this| this.parse_variable_definition(VarFlags::STRUCT),
283        )?;
284        Ok(ItemStruct { name, fields })
285    }
286
287    /// Parses an event definition.
288    fn parse_event(&mut self) -> PResult<'sess, ItemEvent<'ast>> {
289        let name = self.parse_ident()?;
290        let parameters = self.parse_parameter_list(true, VarFlags::EVENT)?;
291        let anonymous = self.eat_keyword(kw::Anonymous);
292        self.expect_semi()?;
293        Ok(ItemEvent { name, parameters, anonymous })
294    }
295
296    /// Parses an error definition.
297    fn parse_error(&mut self) -> PResult<'sess, ItemError<'ast>> {
298        let name = self.parse_ident()?;
299        let parameters = self.parse_parameter_list(true, VarFlags::ERROR)?;
300        self.expect_semi()?;
301        Ok(ItemError { name, parameters })
302    }
303
304    /// Parses a contract definition.
305    ///
306    /// Expects the current token to be a contract-like keyword.
307    fn parse_contract(&mut self) -> PResult<'sess, ItemContract<'ast>> {
308        let TokenKind::Ident(kw) = self.token.kind else {
309            unreachable!("parse_contract called without contract-like keyword");
310        };
311        self.bump(); // kw
312
313        let kind = match kw {
314            kw::Abstract => {
315                self.expect_keyword(kw::Contract)?;
316                ContractKind::AbstractContract
317            }
318            kw::Contract => ContractKind::Contract,
319            kw::Interface => ContractKind::Interface,
320            kw::Library => ContractKind::Library,
321            _ => unreachable!("parse_contract called without contract-like keyword"),
322        };
323        let name = self.parse_ident()?;
324
325        let mut bases = None::<Box<'_, [Modifier<'_>]>>;
326        let mut layout = None::<StorageLayoutSpecifier<'_>>;
327        loop {
328            if self.eat_keyword(kw::Is) {
329                let new_bases = self.parse_inheritance()?;
330                if let Some(prev) = &bases {
331                    let msg = "base contracts already specified";
332                    let span = |bases: &[Modifier<'_>]| {
333                        Span::join_first_last(bases.iter().map(|m| m.span()))
334                    };
335                    self.dcx()
336                        .err(msg)
337                        .span(span(new_bases))
338                        .span_note(span(prev), "previous definition")
339                        .emit();
340                } else if !new_bases.is_empty() {
341                    bases = Some(new_bases);
342                }
343            } else if self.check_keyword(sym::layout) {
344                let new_layout = self.parse_storage_layout_specifier()?;
345                if let Some(prev) = &layout {
346                    let msg = "storage layout already specified";
347                    self.dcx()
348                        .err(msg)
349                        .span(new_layout.span)
350                        .span_note(prev.span, "previous definition")
351                        .emit();
352                } else {
353                    layout = Some(new_layout);
354                }
355            } else {
356                break;
357            }
358        }
359
360        if let Some(layout) = &layout {
361            if !kind.is_contract() {
362                let msg = "storage layout is only allowed for contracts";
363                self.dcx().err(msg).span(layout.span).emit();
364            }
365        }
366
367        self.expect(TokenKind::OpenDelim(Delimiter::Brace))?;
368        let body =
369            self.in_contract(|this| this.parse_items(TokenKind::CloseDelim(Delimiter::Brace)))?;
370
371        Ok(ItemContract { kind, name, layout, bases: bases.unwrap_or_default(), body })
372    }
373
374    /// Parses an enum definition.
375    fn parse_enum(&mut self) -> PResult<'sess, ItemEnum<'ast>> {
376        let name = self.parse_ident()?;
377        let variants = self.parse_delim_comma_seq(Delimiter::Brace, true, Self::parse_ident)?;
378        Ok(ItemEnum { name, variants })
379    }
380
381    /// Parses a user-defined value type.
382    fn parse_udvt(&mut self) -> PResult<'sess, ItemUdvt<'ast>> {
383        let name = self.parse_ident()?;
384        self.expect_keyword(kw::Is)?;
385        let ty = self.parse_type()?;
386        self.expect_semi()?;
387        Ok(ItemUdvt { name, ty })
388    }
389
390    /// Parses a pragma directive.
391    fn parse_pragma(&mut self) -> PResult<'sess, PragmaDirective<'ast>> {
392        let is_ident_or_strlit = |t: Token| t.is_ident() || t.is_str_lit();
393
394        let tokens = if self.check_keyword(sym::solidity)
395            || (self.token.is_ident()
396                && self.look_ahead_with(1, |t| t.is_op() || t.is_rational_lit()))
397        {
398            // `pragma <ident> <req>;`
399            let ident = self.parse_ident_any()?;
400            let req = self.parse_semver_req()?;
401            PragmaTokens::Version(ident, req)
402        } else if (is_ident_or_strlit(self.token) && self.look_ahead(1).kind == TokenKind::Semi)
403            || (is_ident_or_strlit(self.token)
404                && self.look_ahead_with(1, is_ident_or_strlit)
405                && self.look_ahead(2).kind == TokenKind::Semi)
406        {
407            // `pragma <k>;`
408            // `pragma <k> <v>;`
409            let k = self.parse_ident_or_strlit()?;
410            let v = if self.token.is_ident() || self.token.is_str_lit() {
411                Some(self.parse_ident_or_strlit()?)
412            } else {
413                None
414            };
415            PragmaTokens::Custom(k, v)
416        } else {
417            let mut tokens = Vec::new();
418            while !matches!(self.token.kind, TokenKind::Semi | TokenKind::Eof) {
419                tokens.push(self.token);
420                self.bump();
421            }
422            if !self.token.is_eof() && tokens.is_empty() {
423                let msg = "expected at least one token in pragma directive";
424                self.dcx().err(msg).span(self.prev_token.span).emit();
425            }
426            PragmaTokens::Verbatim(self.alloc_vec(tokens))
427        };
428        self.expect_semi()?;
429        Ok(PragmaDirective { tokens })
430    }
431
432    fn parse_ident_or_strlit(&mut self) -> PResult<'sess, IdentOrStrLit> {
433        if self.check_ident() {
434            self.parse_ident().map(IdentOrStrLit::Ident)
435        } else if self.check_str_lit() {
436            self.parse_str_lit().map(IdentOrStrLit::StrLit)
437        } else {
438            self.unexpected()
439        }
440    }
441
442    /// Parses a SemVer version requirement.
443    ///
444    /// See `crates/ast/src/ast/semver.rs` for more details on the implementation.
445    pub fn parse_semver_req(&mut self) -> PResult<'sess, SemverReq<'ast>> {
446        if self.check_noexpect(TokenKind::Semi) || self.check_noexpect(TokenKind::Eof) {
447            let msg = "empty version requirement";
448            let span = self.prev_token.span.to(self.token.span);
449            return Err(self.dcx().err(msg).span(span));
450        }
451        self.parse_semver_req_components_dis().map(|dis| SemverReq { dis })
452    }
453
454    /// `any(c)`
455    fn parse_semver_req_components_dis(
456        &mut self,
457    ) -> PResult<'sess, Box<'ast, [SemverReqCon<'ast>]>> {
458        // https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L170
459        let mut dis = Vec::new();
460        loop {
461            dis.push(self.parse_semver_req_components_con()?);
462            if self.eat(TokenKind::OrOr) {
463                continue;
464            }
465            if self.check(TokenKind::Semi) || self.check(TokenKind::Eof) {
466                break;
467            }
468            // `parse_semver_req_components_con` parses a single range,
469            // or all the values until `||`.
470            debug_assert!(
471                matches!(
472                    dis.last().map(|x| &x.components),
473                    Some([
474                        ..,
475                        SemverReqComponent { span: _, kind: SemverReqComponentKind::Range(..) }
476                    ])
477                ),
478                "not a range: last={:?}",
479                dis.last()
480            );
481            return Err(self.dcx().err("ranges can only be combined using the || operator"));
482        }
483        Ok(self.alloc_vec(dis))
484    }
485
486    /// `all(c)`
487    fn parse_semver_req_components_con(&mut self) -> PResult<'sess, SemverReqCon<'ast>> {
488        // component - component (range)
489        // or component component* (conjunction)
490
491        let mut components = Vec::new();
492        let lo = self.token.span;
493        let (op, v) = self.parse_semver_component()?;
494        if self.eat(TokenKind::BinOp(BinOpToken::Minus)) {
495            // range
496            // Ops are parsed and overwritten: https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L210
497            let _ = op;
498            let (_second_op, right) = self.parse_semver_component()?;
499            let kind = SemverReqComponentKind::Range(v, right);
500            let span = lo.to(self.prev_token.span);
501            components.push(SemverReqComponent { span, kind });
502        } else {
503            // conjunction; first is already parsed
504            let span = lo.to(self.prev_token.span);
505            let kind = SemverReqComponentKind::Op(op, v);
506            components.push(SemverReqComponent { span, kind });
507            // others
508            while !matches!(self.token.kind, TokenKind::OrOr | TokenKind::Eof | TokenKind::Semi) {
509                let (span, (op, v)) = self.parse_spanned(Self::parse_semver_component)?;
510                let kind = SemverReqComponentKind::Op(op, v);
511                components.push(SemverReqComponent { span, kind });
512            }
513        }
514        let span = lo.to(self.prev_token.span);
515        let components = self.alloc_vec(components);
516        Ok(SemverReqCon { span, components })
517    }
518
519    fn parse_semver_component(&mut self) -> PResult<'sess, (Option<SemverOp>, SemverVersion)> {
520        let op = self.parse_semver_op();
521        let v = self.parse_semver_version()?;
522        Ok((op, v))
523    }
524
525    fn parse_semver_op(&mut self) -> Option<SemverOp> {
526        // https://github.com/ethereum/solidity/blob/e81f2bdbd66e9c8780f74b8a8d67b4dc2c87945e/liblangutil/SemVerHandler.cpp#L227
527        let op = match self.token.kind {
528            TokenKind::Eq => SemverOp::Exact,
529            TokenKind::Gt => SemverOp::Greater,
530            TokenKind::Ge => SemverOp::GreaterEq,
531            TokenKind::Lt => SemverOp::Less,
532            TokenKind::Le => SemverOp::LessEq,
533            TokenKind::Tilde => SemverOp::Tilde,
534            TokenKind::BinOp(BinOpToken::Caret) => SemverOp::Caret,
535            _ => return None,
536        };
537        self.bump();
538        Some(op)
539    }
540
541    fn parse_semver_version(&mut self) -> PResult<'sess, SemverVersion> {
542        Ok(SemverVersionParser::new(self).parse())
543    }
544
545    /// Parses an import directive.
546    fn parse_import(&mut self) -> PResult<'sess, ImportDirective<'ast>> {
547        let path;
548        let items = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
549            // * as alias from ""
550            let alias = self.parse_as_alias()?;
551            self.expect_keyword(sym::from)?;
552            path = self.parse_str_lit()?;
553            ImportItems::Glob(alias)
554        } else if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
555            // { x as y, ... } from ""
556            let list = self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
557                let name = this.parse_ident()?;
558                let alias = this.parse_as_alias_opt()?;
559                Ok((name, alias))
560            })?;
561            self.expect_keyword(sym::from)?;
562            path = self.parse_str_lit()?;
563            ImportItems::Aliases(list)
564        } else {
565            // "" as alias
566            path = self.parse_str_lit()?;
567            let alias = self.parse_as_alias_opt()?;
568            ImportItems::Plain(alias)
569        };
570        if path.value.as_str().is_empty() {
571            let msg = "import path cannot be empty";
572            self.dcx().err(msg).span(path.span).emit();
573        }
574        self.expect_semi()?;
575        Ok(ImportDirective { path, items })
576    }
577
578    /// Parses an optional `as` alias identifier.
579    fn parse_as_alias_opt(&mut self) -> PResult<'sess, Option<Ident>> {
580        if self.eat_keyword(kw::As) {
581            self.parse_ident().map(Some)
582        } else {
583            Ok(None)
584        }
585    }
586
587    /// Parses an `as` alias identifier.
588    fn parse_as_alias(&mut self) -> PResult<'sess, Ident> {
589        self.expect_keyword(kw::As)?;
590        self.parse_ident()
591    }
592
593    /// Parses a using directive.
594    fn parse_using(&mut self) -> PResult<'sess, UsingDirective<'ast>> {
595        let list = self.parse_using_list()?;
596        self.expect_keyword(kw::For)?;
597        let ty = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
598            None
599        } else {
600            Some(self.parse_type()?)
601        };
602        let global = self.eat_keyword(sym::global);
603        self.expect_semi()?;
604        Ok(UsingDirective { list, ty, global })
605    }
606
607    fn parse_using_list(&mut self) -> PResult<'sess, UsingList<'ast>> {
608        if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
609            self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
610                let path = this.parse_path()?;
611                let op = if this.eat_keyword(kw::As) {
612                    Some(this.parse_user_definable_operator()?)
613                } else {
614                    None
615                };
616                Ok((path, op))
617            })
618            .map(UsingList::Multiple)
619        } else {
620            self.parse_path().map(UsingList::Single)
621        }
622    }
623
624    fn parse_user_definable_operator(&mut self) -> PResult<'sess, UserDefinableOperator> {
625        use BinOpToken::*;
626        use TokenKind::*;
627        use UserDefinableOperator as Op;
628        macro_rules! user_op {
629            ($($tok1:tt $(($tok2:tt))? => $op:expr),* $(,)?) => {
630                match self.token.kind {
631                    $($tok1 $(($tok2))? => $op,)*
632                    _ => {
633                        self.expected_tokens.extend_from_slice(&[$(ExpectedToken::Token($tok1 $(($tok2))?)),*]);
634                        return self.unexpected();
635                    }
636                }
637            };
638        }
639        let op = user_op! {
640            BinOp(And) => Op::BitAnd,
641            Tilde => Op::BitNot,
642            BinOp(Or) => Op::BitOr,
643            BinOp(Caret) => Op::BitXor,
644            BinOp(Plus) => Op::Add,
645            BinOp(Slash) => Op::Div,
646            BinOp(Percent) => Op::Rem,
647            BinOp(Star) => Op::Mul,
648            BinOp(Minus) => Op::Sub,
649            EqEq => Op::Eq,
650            Ge => Op::Ge,
651            Gt => Op::Gt,
652            Le => Op::Le,
653            Lt => Op::Lt,
654            Ne => Op::Ne,
655        };
656        self.bump();
657        Ok(op)
658    }
659
660    /* ----------------------------------------- Common ----------------------------------------- */
661
662    /// Parses a variable declaration/definition.
663    ///
664    /// `state-variable-declaration`, `constant-variable-declaration`, `variable-declaration`,
665    /// `variable-declaration-statement`, and more.
666    pub(super) fn parse_variable_definition(
667        &mut self,
668        flags: VarFlags,
669    ) -> PResult<'sess, VariableDefinition<'ast>> {
670        self.parse_variable_definition_with(flags, None)
671    }
672
673    pub(super) fn parse_variable_definition_with(
674        &mut self,
675        flags: VarFlags,
676        ty: Option<Type<'ast>>,
677    ) -> PResult<'sess, VariableDefinition<'ast>> {
678        let mut lo = self.token.span;
679        let ty = match ty {
680            Some(ty) => {
681                lo = lo.with_lo(ty.span.lo());
682                ty
683            }
684            None => self.parse_type()?,
685        };
686
687        if ty.is_function()
688            && flags == VarFlags::STATE_VAR
689            && self.check_noexpect(TokenKind::OpenDelim(Delimiter::Brace))
690        {
691            let msg = "expected a state variable declaration";
692            let note = "this style of fallback function has been removed; use the `fallback` or `receive` keywords instead";
693            self.dcx().err(msg).span(self.token.span).note(note).emit();
694            let _ = self.parse_block()?;
695            return Ok(VariableDefinition {
696                span: lo.to(self.prev_token.span),
697                ty,
698                visibility: None,
699                mutability: None,
700                data_location: None,
701                override_: None,
702                indexed: false,
703                name: None,
704                initializer: None,
705            });
706        }
707
708        let mut data_location = None;
709        let mut visibility = None;
710        let mut mutability = None;
711        let mut override_ = None;
712        let mut indexed = false;
713        loop {
714            if let Some(s) = self.parse_data_location() {
715                if !flags.contains(VarFlags::DATALOC) {
716                    let msg = "data locations are not allowed here";
717                    self.dcx().err(msg).span(self.prev_token.span).emit();
718                } else if data_location.is_some() {
719                    let msg = "data location already specified";
720                    self.dcx().err(msg).span(self.prev_token.span).emit();
721                } else {
722                    data_location = Some(s);
723                }
724            } else if let Some(v) = self.parse_visibility() {
725                if !flags.contains(VarFlags::from_visibility(v)) {
726                    let msg = visibility_error(v, flags.visibilities());
727                    self.dcx().err(msg).span(self.prev_token.span).emit();
728                } else if visibility.is_some() {
729                    let msg = "visibility already specified";
730                    self.dcx().err(msg).span(self.prev_token.span).emit();
731                } else {
732                    visibility = Some(v);
733                }
734            } else if let Some(m) = self.parse_variable_mutability() {
735                // `CONSTANT_VAR` is special cased later.
736                if flags != VarFlags::CONSTANT_VAR && !flags.contains(VarFlags::from_varmut(m)) {
737                    let msg = varmut_error(m, flags.varmuts());
738                    self.dcx().err(msg).span(self.prev_token.span).emit();
739                } else if mutability.is_some() {
740                    let msg = "mutability already specified";
741                    self.dcx().err(msg).span(self.prev_token.span).emit();
742                } else {
743                    mutability = Some(m);
744                }
745            } else if self.eat_keyword(kw::Indexed) {
746                if !flags.contains(VarFlags::INDEXED) {
747                    let msg = "`indexed` is not allowed here";
748                    self.dcx().err(msg).span(self.prev_token.span).emit();
749                } else if indexed {
750                    let msg = "`indexed` already specified";
751                    self.dcx().err(msg).span(self.prev_token.span).emit();
752                } else {
753                    indexed = true;
754                }
755            } else if self.eat_keyword(kw::Virtual) {
756                let msg = "`virtual` is not allowed here";
757                self.dcx().err(msg).span(self.prev_token.span).emit();
758            } else if self.eat_keyword(kw::Override) {
759                let o = self.parse_override()?;
760                if !flags.contains(VarFlags::OVERRIDE) {
761                    let msg = "`override` is not allowed here";
762                    self.dcx().err(msg).span(self.prev_token.span).emit();
763                } else if override_.is_some() {
764                    let msg = "override already specified";
765                    self.dcx().err(msg).span(self.prev_token.span).emit();
766                } else {
767                    override_ = Some(o);
768                }
769            } else {
770                break;
771            }
772        }
773
774        let name = if flags.contains(VarFlags::NAME) {
775            self.parse_ident().map(Some)
776        } else {
777            self.parse_ident_opt()
778        }?;
779        if let Some(name) = &name {
780            if flags.contains(VarFlags::NAME_WARN) {
781                debug_assert!(!flags.contains(VarFlags::NAME));
782                let msg = "named function type parameters are deprecated";
783                self.dcx().warn(msg).code(error_code!(6162)).span(name.span).emit();
784            }
785        }
786
787        let initializer = if flags.contains(VarFlags::INITIALIZER) && self.eat(TokenKind::Eq) {
788            Some(self.parse_expr()?)
789        } else {
790            None
791        };
792
793        if flags.contains(VarFlags::SEMI) {
794            self.expect_semi()?;
795        }
796
797        let span = lo.to(self.prev_token.span);
798
799        if mutability == Some(VarMut::Constant) && initializer.is_none() {
800            let msg = "constant variable must be initialized";
801            self.dcx().err(msg).span(span).emit();
802        }
803        if flags == VarFlags::CONSTANT_VAR && mutability != Some(VarMut::Constant) {
804            let msg = "only constant variables are allowed at file level";
805            self.dcx().err(msg).span(span).emit();
806        }
807
808        Ok(VariableDefinition {
809            span,
810            ty,
811            data_location,
812            visibility,
813            mutability,
814            override_,
815            indexed,
816            name,
817            initializer,
818        })
819    }
820
821    /// Parses mutability of a variable: `constant | immutable`.
822    fn parse_variable_mutability(&mut self) -> Option<VarMut> {
823        if self.eat_keyword(kw::Constant) {
824            Some(VarMut::Constant)
825        } else if self.eat_keyword(kw::Immutable) {
826            Some(VarMut::Immutable)
827        } else {
828            None
829        }
830    }
831
832    /// Parses a parameter list: `($(vardecl),*)`.
833    pub(super) fn parse_parameter_list(
834        &mut self,
835        allow_empty: bool,
836        flags: VarFlags,
837    ) -> PResult<'sess, ParameterList<'ast>> {
838        self.parse_paren_comma_seq(allow_empty, |this| this.parse_variable_definition(flags))
839    }
840
841    /// Parses a list of inheritance specifiers.
842    fn parse_inheritance(&mut self) -> PResult<'sess, Box<'ast, [Modifier<'ast>]>> {
843        let mut list = SmallVec::<[_; 8]>::new();
844        loop {
845            list.push(self.parse_modifier()?);
846            if !self.eat(TokenKind::Comma) {
847                break;
848            }
849        }
850        Ok(self.alloc_smallvec(list))
851    }
852
853    /// Parses a storage layout specifier.
854    fn parse_storage_layout_specifier(&mut self) -> PResult<'sess, StorageLayoutSpecifier<'ast>> {
855        let lo = self.token.span;
856        self.expect_keyword(sym::layout)?;
857        self.expect_keyword(sym::at)?;
858        let slot = self.parse_expr()?;
859        Ok(StorageLayoutSpecifier { span: lo.to(self.prev_token.span), slot })
860    }
861
862    /// Parses a single modifier invocation.
863    fn parse_modifier(&mut self) -> PResult<'sess, Modifier<'ast>> {
864        let name = self.parse_path()?;
865        let arguments = if self.token.kind == TokenKind::OpenDelim(Delimiter::Parenthesis) {
866            self.parse_call_args()?
867        } else {
868            CallArgs::empty(name.span().shrink_to_hi())
869        };
870        Ok(Modifier { name, arguments })
871    }
872
873    /// Parses a single function override.
874    ///
875    /// Expects the `override` to have already been eaten.
876    fn parse_override(&mut self) -> PResult<'sess, Override<'ast>> {
877        debug_assert!(self.prev_token.is_keyword(kw::Override));
878        let lo = self.prev_token.span;
879        let paths = if self.token.is_open_delim(Delimiter::Parenthesis) {
880            self.parse_paren_comma_seq(false, Self::parse_path)?
881        } else {
882            Default::default()
883        };
884        let span = lo.to(self.prev_token.span);
885        Ok(Override { span, paths })
886    }
887
888    /// Parses a single string literal. This is only used in import paths and statements, not
889    /// expressions.
890    pub(super) fn parse_str_lit(&mut self) -> PResult<'sess, StrLit> {
891        match self.parse_str_lit_opt() {
892            Some(lit) => Ok(lit),
893            None => self.unexpected(),
894        }
895    }
896
897    /// Parses a single optional string literal. This is only used in import paths and statements,
898    /// not expressions.
899    pub(super) fn parse_str_lit_opt(&mut self) -> Option<StrLit> {
900        if !self.check_str_lit() {
901            return None;
902        }
903        let Token { kind: TokenKind::Literal(TokenLitKind::Str, symbol), span } = self.token else {
904            unreachable!()
905        };
906        self.bump();
907        Some(StrLit { span, value: symbol })
908    }
909
910    /// Parses a storage location: `storage | memory | calldata | transient`.
911    fn parse_data_location(&mut self) -> Option<DataLocation> {
912        if self.eat_keyword(kw::Storage) {
913            Some(DataLocation::Storage)
914        } else if self.eat_keyword(kw::Memory) {
915            Some(DataLocation::Memory)
916        } else if self.eat_keyword(kw::Calldata) {
917            Some(DataLocation::Calldata)
918        } else if self.check_keyword(sym::transient)
919            && !matches!(
920                self.look_ahead(1).kind,
921                TokenKind::Eq | TokenKind::Semi | TokenKind::CloseDelim(_) | TokenKind::Comma
922            )
923        {
924            self.bump(); // `transient`
925            Some(DataLocation::Transient)
926        } else {
927            None
928        }
929    }
930
931    /// Parses a visibility: `public | private | internal | external`.
932    pub(super) fn parse_visibility(&mut self) -> Option<Visibility> {
933        if self.eat_keyword(kw::Public) {
934            Some(Visibility::Public)
935        } else if self.eat_keyword(kw::Private) {
936            Some(Visibility::Private)
937        } else if self.eat_keyword(kw::Internal) {
938            Some(Visibility::Internal)
939        } else if self.eat_keyword(kw::External) {
940            Some(Visibility::External)
941        } else {
942            None
943        }
944    }
945
946    /// Parses state mutability: `payable | pure | view`.
947    pub(super) fn parse_state_mutability(&mut self) -> Option<StateMutability> {
948        if self.eat_keyword(kw::Payable) {
949            Some(StateMutability::Payable)
950        } else if self.eat_keyword(kw::Pure) {
951            Some(StateMutability::Pure)
952        } else if self.eat_keyword(kw::View) {
953            Some(StateMutability::View)
954        } else {
955            None
956        }
957    }
958}
959
960struct SemverVersionParser<'p, 'sess, 'ast> {
961    p: &'p mut Parser<'sess, 'ast>,
962    bumps: u32,
963    pos_inside: u32,
964}
965
966impl<'p, 'sess, 'ast> SemverVersionParser<'p, 'sess, 'ast> {
967    fn new(p: &'p mut Parser<'sess, 'ast>) -> Self {
968        Self { p, bumps: 0, pos_inside: 0 }
969    }
970
971    fn emit_err(&self, msg: impl Into<DiagMsg>) {
972        self.p.dcx().err(msg).span(self.current_span()).emit();
973    }
974
975    fn parse(mut self) -> SemverVersion {
976        let lo = self.current_span();
977        let major = self.parse_version_part();
978        let mut minor = None;
979        let mut patch = None;
980        if self.eat_dot() {
981            minor = Some(self.parse_version_part());
982            if self.eat_dot() {
983                patch = Some(self.parse_version_part());
984            }
985        }
986        if self.pos_inside > 0 || self.bumps == 0 {
987            self.emit_err("unexpected trailing characters");
988            self.bump_token();
989        }
990        SemverVersion { span: lo.to(self.current_span()), major, minor, patch }
991    }
992
993    fn eat_dot(&mut self) -> bool {
994        let r = self.current_char() == Some('.');
995        if r {
996            self.bump_char();
997        }
998        r
999    }
1000
1001    fn parse_version_part(&mut self) -> SemverVersionNumber {
1002        match self.current_char() {
1003            Some('*' | 'x' | 'X') => {
1004                self.bump_char();
1005                SemverVersionNumber::Wildcard
1006            }
1007            Some('0'..='9') => {
1008                let s = self.current_str().unwrap();
1009                let len = s.bytes().take_while(u8::is_ascii_digit).count();
1010                let result = s[..len].parse();
1011                self.bump_chars(len as u32);
1012                let Ok(n) = result else {
1013                    self.emit_err("version number too large");
1014                    return SemverVersionNumber::Wildcard;
1015                };
1016                SemverVersionNumber::Number(n)
1017            }
1018            _ => {
1019                self.emit_err("expected version number");
1020                self.bump_char();
1021                SemverVersionNumber::Wildcard
1022            }
1023        }
1024    }
1025
1026    fn current_char(&self) -> Option<char> {
1027        self.current_str()?.chars().next()
1028    }
1029
1030    fn current_str(&self) -> Option<&str> {
1031        self.current_token_str()?.get(self.pos_inside as usize..)
1032    }
1033
1034    fn current_token_str(&self) -> Option<&str> {
1035        Some(match &self.current_token().kind {
1036            TokenKind::Dot => ".",
1037            TokenKind::BinOp(BinOpToken::Star) => "*",
1038            TokenKind::Ident(s) | TokenKind::Literal(_, s) => s.as_str(),
1039            _ => return None,
1040        })
1041    }
1042
1043    fn current_token(&self) -> &Token {
1044        &self.p.token
1045    }
1046
1047    fn current_span(&self) -> Span {
1048        let mut s = self.current_token().span;
1049        if self.pos_inside > 0 {
1050            s = s.with_lo(s.lo() + self.pos_inside);
1051        }
1052        s
1053    }
1054
1055    fn bump_char(&mut self) {
1056        self.bump_chars(1);
1057    }
1058
1059    fn bump_chars(&mut self, n: u32) {
1060        if let Some(s) = self.current_token_str() {
1061            if self.pos_inside + n >= s.len() as u32 {
1062                self.bump_token();
1063            } else {
1064                self.pos_inside += n;
1065            }
1066        }
1067    }
1068
1069    fn bump_token(&mut self) {
1070        self.p.bump();
1071        self.bumps += 1;
1072        self.pos_inside = 0;
1073    }
1074}
1075
1076bitflags::bitflags! {
1077    /// Flags for parsing variable declarations.
1078    #[derive(Clone, Copy, PartialEq, Eq)]
1079    pub(super) struct VarFlags: u16 {
1080        // `ty` is always required. `name` is always optional, unless `NAME` is specified.
1081
1082        const DATALOC     = 1 << 1;
1083        const INDEXED     = 1 << 2;
1084
1085        const PRIVATE     = 1 << 3;
1086        const INTERNAL    = 1 << 4;
1087        const PUBLIC      = 1 << 5;
1088        const EXTERNAL    = 1 << 6; // Never accepted, just for error messages.
1089        const VISIBILITY  = Self::PRIVATE.bits()
1090                          | Self::INTERNAL.bits()
1091                          | Self::PUBLIC.bits()
1092                          | Self::EXTERNAL.bits();
1093
1094        const CONSTANT    = 1 << 7;
1095        const IMMUTABLE   = 1 << 8;
1096
1097        const OVERRIDE    = 1 << 9;
1098
1099        const NAME        = 1 << 10;
1100        const NAME_WARN   = 1 << 11;
1101
1102        const INITIALIZER = 1 << 12;
1103        const SEMI        = 1 << 13;
1104
1105        const STRUCT       = Self::NAME.bits();
1106        const ERROR        = 0;
1107        const EVENT        = Self::INDEXED.bits();
1108        const FUNCTION     = Self::DATALOC.bits();
1109        const FUNCTION_TY  = Self::DATALOC.bits() | Self::NAME_WARN.bits();
1110
1111        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.stateVariableDeclaration
1112        const STATE_VAR    = Self::DATALOC.bits()
1113                           | Self::PRIVATE.bits()
1114                           | Self::INTERNAL.bits()
1115                           | Self::PUBLIC.bits()
1116                           | Self::CONSTANT.bits()
1117                           | Self::IMMUTABLE.bits()
1118                           | Self::OVERRIDE.bits()
1119                           | Self::NAME.bits()
1120                           | Self::INITIALIZER.bits()
1121                           | Self::SEMI.bits();
1122
1123        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constantVariableDeclaration
1124        const CONSTANT_VAR = Self::CONSTANT.bits()
1125                           | Self::NAME.bits()
1126                           | Self::INITIALIZER.bits()
1127                           | Self::SEMI.bits();
1128
1129        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.variableDeclarationStatement
1130        const VAR = Self::DATALOC.bits() | Self::INITIALIZER.bits();
1131    }
1132
1133    /// Flags for parsing function headers.
1134    #[derive(Clone, Copy, PartialEq, Eq)]
1135    pub(super) struct FunctionFlags: u16 {
1136        /// Name is required.
1137        const NAME             = 1 << 0;
1138        /// Function type: parameter names are parsed, but issue a warning.
1139        const PARAM_NAME       = 1 << 1;
1140        /// Parens can be omitted.
1141        const NO_PARENS        = 1 << 2;
1142
1143        // Visibility
1144        const PRIVATE          = 1 << 3;
1145        const INTERNAL         = 1 << 4;
1146        const PUBLIC           = 1 << 5;
1147        const EXTERNAL         = 1 << 6;
1148        const VISIBILITY       = Self::PRIVATE.bits()
1149                               | Self::INTERNAL.bits()
1150                               | Self::PUBLIC.bits()
1151                               | Self::EXTERNAL.bits();
1152
1153        // StateMutability
1154        const PURE             = 1 << 7;
1155        const VIEW             = 1 << 8;
1156        const PAYABLE          = 1 << 9;
1157        const STATE_MUTABILITY = Self::PURE.bits()
1158                               | Self::VIEW.bits()
1159                               | Self::PAYABLE.bits();
1160
1161        const MODIFIERS        = 1 << 10;
1162        const VIRTUAL          = 1 << 11;
1163        const OVERRIDE         = 1 << 12;
1164
1165        const RETURNS          = 1 << 13;
1166        /// Must be implemented, meaning it must end in a `{}` implementation block.
1167        const ONLY_BLOCK       = 1 << 14;
1168
1169        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.constructorDefinition
1170        const CONSTRUCTOR = Self::MODIFIERS.bits()
1171                          | Self::PAYABLE.bits()
1172                          | Self::INTERNAL.bits()
1173                          | Self::PUBLIC.bits()
1174                          | Self::ONLY_BLOCK.bits();
1175
1176        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionDefinition
1177        const FUNCTION    = Self::NAME.bits()
1178                          | Self::VISIBILITY.bits()
1179                          | Self::STATE_MUTABILITY.bits()
1180                          | Self::MODIFIERS.bits()
1181                          | Self::VIRTUAL.bits()
1182                          | Self::OVERRIDE.bits()
1183                          | Self::RETURNS.bits();
1184
1185        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.modifierDefinition
1186        const MODIFIER    = Self::NAME.bits()
1187                          | Self::NO_PARENS.bits()
1188                          | Self::VIRTUAL.bits()
1189                          | Self::OVERRIDE.bits();
1190
1191        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.fallbackFunctionDefinition
1192        const FALLBACK    = Self::EXTERNAL.bits()
1193                          | Self::STATE_MUTABILITY.bits()
1194                          | Self::MODIFIERS.bits()
1195                          | Self::VIRTUAL.bits()
1196                          | Self::OVERRIDE.bits()
1197                          | Self::RETURNS.bits();
1198
1199        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.receiveFunctionDefinition
1200        const RECEIVE     = Self::EXTERNAL.bits()
1201                          | Self::PAYABLE.bits()
1202                          | Self::MODIFIERS.bits()
1203                          | Self::VIRTUAL.bits()
1204                          | Self::OVERRIDE.bits();
1205
1206        // https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.functionTypeName
1207        const FUNCTION_TY = Self::PARAM_NAME.bits()
1208                          | Self::VISIBILITY.bits()
1209                          | Self::STATE_MUTABILITY.bits()
1210                          | Self::RETURNS.bits();
1211    }
1212}
1213
1214impl VarFlags {
1215    fn from_visibility(v: Visibility) -> Self {
1216        match v {
1217            Visibility::Private => Self::PRIVATE,
1218            Visibility::Internal => Self::INTERNAL,
1219            Visibility::Public => Self::PUBLIC,
1220            Visibility::External => Self::EXTERNAL,
1221        }
1222    }
1223
1224    fn into_visibility(self) -> Option<Visibility> {
1225        match self {
1226            Self::PRIVATE => Some(Visibility::Private),
1227            Self::INTERNAL => Some(Visibility::Internal),
1228            Self::PUBLIC => Some(Visibility::Public),
1229            Self::EXTERNAL => Some(Visibility::External),
1230            _ => None,
1231        }
1232    }
1233
1234    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1235        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1236    }
1237
1238    fn from_varmut(v: VarMut) -> Self {
1239        match v {
1240            VarMut::Constant => Self::CONSTANT,
1241            VarMut::Immutable => Self::IMMUTABLE,
1242        }
1243    }
1244
1245    fn into_varmut(self) -> Option<VarMut> {
1246        match self {
1247            Self::CONSTANT => Some(VarMut::Constant),
1248            Self::IMMUTABLE => Some(VarMut::Immutable),
1249            _ => None,
1250        }
1251    }
1252
1253    fn varmuts(self) -> Option<impl Iterator<Item = VarMut>> {
1254        self.supported(Self::CONSTANT | Self::IMMUTABLE)
1255            .map(|iter| iter.map(|x| x.into_varmut().unwrap()))
1256    }
1257
1258    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1259        let s = self.intersection(what);
1260        if s.is_empty() {
1261            None
1262        } else {
1263            Some(s.iter())
1264        }
1265    }
1266}
1267
1268impl FunctionFlags {
1269    fn from_kind(kind: FunctionKind) -> Self {
1270        match kind {
1271            FunctionKind::Constructor => Self::CONSTRUCTOR,
1272            FunctionKind::Function => Self::FUNCTION,
1273            FunctionKind::Modifier => Self::MODIFIER,
1274            FunctionKind::Receive => Self::RECEIVE,
1275            FunctionKind::Fallback => Self::FALLBACK,
1276        }
1277    }
1278
1279    fn from_visibility(visibility: Visibility) -> Self {
1280        match visibility {
1281            Visibility::Private => Self::PRIVATE,
1282            Visibility::Internal => Self::INTERNAL,
1283            Visibility::Public => Self::PUBLIC,
1284            Visibility::External => Self::EXTERNAL,
1285        }
1286    }
1287
1288    fn into_visibility(self) -> Option<Visibility> {
1289        match self {
1290            Self::PRIVATE => Some(Visibility::Private),
1291            Self::INTERNAL => Some(Visibility::Internal),
1292            Self::PUBLIC => Some(Visibility::Public),
1293            Self::EXTERNAL => Some(Visibility::External),
1294            _ => None,
1295        }
1296    }
1297
1298    fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1299        self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1300    }
1301
1302    fn from_state_mutability(state_mutability: StateMutability) -> Self {
1303        match state_mutability {
1304            StateMutability::Pure => Self::PURE,
1305            StateMutability::View => Self::VIEW,
1306            StateMutability::Payable => Self::PAYABLE,
1307            StateMutability::NonPayable => unreachable!(),
1308        }
1309    }
1310
1311    fn into_state_mutability(self) -> Option<StateMutability> {
1312        match self {
1313            Self::PURE => Some(StateMutability::Pure),
1314            Self::VIEW => Some(StateMutability::View),
1315            Self::PAYABLE => Some(StateMutability::Payable),
1316            _ => None,
1317        }
1318    }
1319
1320    fn state_mutabilities(self) -> Option<impl Iterator<Item = StateMutability>> {
1321        self.supported(Self::STATE_MUTABILITY)
1322            .map(|iter| iter.map(|x| x.into_state_mutability().unwrap()))
1323    }
1324
1325    fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1326        let s = self.intersection(what);
1327        if s.is_empty() {
1328            None
1329        } else {
1330            Some(s.iter())
1331        }
1332    }
1333}
1334
1335fn visibility_error(v: Visibility, iter: Option<impl Iterator<Item = Visibility>>) -> String {
1336    common_flags_error(v, "visibility", iter)
1337}
1338
1339fn varmut_error(m: VarMut, iter: Option<impl Iterator<Item = VarMut>>) -> String {
1340    common_flags_error(m, "mutability", iter)
1341}
1342
1343fn state_mutability_error(
1344    m: StateMutability,
1345    iter: Option<impl Iterator<Item = StateMutability>>,
1346) -> String {
1347    common_flags_error(m, "state mutability", iter)
1348}
1349
1350fn common_flags_error<T: std::fmt::Display>(
1351    t: T,
1352    desc: &str,
1353    iter: Option<impl Iterator<Item = T>>,
1354) -> String {
1355    match iter {
1356        Some(iter) => format!("`{t}` not allowed here; allowed values: {}", iter.format(", ")),
1357        None => format!("{desc} is not allowed here"),
1358    }
1359}
1360
1361#[cfg(test)]
1362mod tests {
1363    use super::*;
1364    use solar_interface::{source_map::FileName, Result, Session};
1365
1366    fn assert_version_matches(tests: &[(&str, &str, bool)]) {
1367        let sess = Session::builder().with_test_emitter().build();
1368        sess.enter(|| -> Result {
1369            for (i, &(v, req_s, res)) in tests.iter().enumerate() {
1370                let name = i.to_string();
1371                let src = format!("{v} {req_s}");
1372                let arena = Arena::new();
1373                let mut parser =
1374                    Parser::from_source_code(&sess, &arena, FileName::Custom(name), src)?;
1375
1376                let version = parser.parse_semver_version().map_err(|e| e.emit()).unwrap();
1377                assert_eq!(version.to_string(), v);
1378                let req: SemverReq<'_> = parser.parse_semver_req().map_err(|e| e.emit()).unwrap();
1379                sess.dcx.has_errors().unwrap();
1380                assert_eq!(req.matches(&version), res, "v={v:?}, req={req_s:?}");
1381            }
1382            Ok(())
1383        })
1384        .unwrap();
1385    }
1386
1387    #[test]
1388    fn semver_matches() {
1389        assert_version_matches(&[
1390            // none = eq
1391            ("0.8.1", "0", true),
1392            ("0.8.1", "1", false),
1393            ("0.8.1", "1.0", false),
1394            ("0.8.1", "1.0.0", false),
1395            ("0.8.1", "0.7", false),
1396            ("0.8.1", "0.7.0", false),
1397            ("0.8.1", "0.7.1", false),
1398            ("0.8.1", "0.7.2", false),
1399            ("0.8.1", "0.8", true),
1400            ("0.8.1", "0.8.0", false),
1401            ("0.8.1", "0.8.1", true),
1402            ("0.8.1", "0.8.2", false),
1403            ("0.8.1", "0.9", false),
1404            ("0.8.1", "0.9.0", false),
1405            ("0.8.1", "0.9.1", false),
1406            ("0.8.1", "0.9.2", false),
1407            // eq
1408            ("0.8.1", "=0", true),
1409            ("0.8.1", "=1", false),
1410            ("0.8.1", "=1.0", false),
1411            ("0.8.1", "=1.0.0", false),
1412            ("0.8.1", "=0.7", false),
1413            ("0.8.1", "=0.7.0", false),
1414            ("0.8.1", "=0.7.1", false),
1415            ("0.8.1", "=0.7.2", false),
1416            ("0.8.1", "=0.8", true),
1417            ("0.8.1", "=0.8.0", false),
1418            ("0.8.1", "=0.8.1", true),
1419            ("0.8.1", "=0.8.2", false),
1420            ("0.8.1", "=0.9", false),
1421            ("0.8.1", "=0.9.0", false),
1422            ("0.8.1", "=0.9.1", false),
1423            ("0.8.1", "=0.9.2", false),
1424            // gt
1425            ("0.8.1", ">0", false),
1426            ("0.8.1", ">1", false),
1427            ("0.8.1", ">1.0", false),
1428            ("0.8.1", ">1.0.0", false),
1429            ("0.8.1", ">0.7", true),
1430            ("0.8.1", ">0.7.0", true),
1431            ("0.8.1", ">0.7.1", true),
1432            ("0.8.1", ">0.7.2", true),
1433            ("0.8.1", ">0.8", false),
1434            ("0.8.1", ">0.8.0", true),
1435            ("0.8.1", ">0.8.1", false),
1436            ("0.8.1", ">0.8.2", false),
1437            ("0.8.1", ">0.9", false),
1438            ("0.8.1", ">0.9.0", false),
1439            ("0.8.1", ">0.9.1", false),
1440            ("0.8.1", ">0.9.2", false),
1441            // ge
1442            ("0.8.1", ">=0", true),
1443            ("0.8.1", ">=1", false),
1444            ("0.8.1", ">=1.0", false),
1445            ("0.8.1", ">=1.0.0", false),
1446            ("0.8.1", ">=0.7", true),
1447            ("0.8.1", ">=0.7.0", true),
1448            ("0.8.1", ">=0.7.1", true),
1449            ("0.8.1", ">=0.7.2", true),
1450            ("0.8.1", ">=0.8", true),
1451            ("0.8.1", ">=0.8.0", true),
1452            ("0.8.1", ">=0.8.1", true),
1453            ("0.8.1", ">=0.8.2", false),
1454            ("0.8.1", ">=0.9", false),
1455            ("0.8.1", ">=0.9.0", false),
1456            ("0.8.1", ">=0.9.1", false),
1457            ("0.8.1", ">=0.9.2", false),
1458            // lt
1459            ("0.8.1", "<0", false),
1460            ("0.8.1", "<1", true),
1461            ("0.8.1", "<1.0", true),
1462            ("0.8.1", "<1.0.0", true),
1463            ("0.8.1", "<0.7", false),
1464            ("0.8.1", "<0.7.0", false),
1465            ("0.8.1", "<0.7.1", false),
1466            ("0.8.1", "<0.7.2", false),
1467            ("0.8.1", "<0.8", false),
1468            ("0.8.1", "<0.8.0", false),
1469            ("0.8.1", "<0.8.1", false),
1470            ("0.8.1", "<0.8.2", true),
1471            ("0.8.1", "<0.9", true),
1472            ("0.8.1", "<0.9.0", true),
1473            ("0.8.1", "<0.9.1", true),
1474            ("0.8.1", "<0.9.2", true),
1475            // le
1476            ("0.8.1", "<=0", true),
1477            ("0.8.1", "<=1", true),
1478            ("0.8.1", "<=1.0", true),
1479            ("0.8.1", "<=1.0.0", true),
1480            ("0.8.1", "<=0.7", false),
1481            ("0.8.1", "<=0.7.0", false),
1482            ("0.8.1", "<=0.7.1", false),
1483            ("0.8.1", "<=0.7.2", false),
1484            ("0.8.1", "<=0.8", true),
1485            ("0.8.1", "<=0.8.0", false),
1486            ("0.8.1", "<=0.8.1", true),
1487            ("0.8.1", "<=0.8.2", true),
1488            ("0.8.1", "<=0.9.0", true),
1489            ("0.8.1", "<=0.9.1", true),
1490            ("0.8.1", "<=0.9.2", true),
1491            // tilde
1492            ("0.8.1", "~0", true),
1493            ("0.8.1", "~1", false),
1494            ("0.8.1", "~1.0", false),
1495            ("0.8.1", "~1.0.0", false),
1496            ("0.8.1", "~0.7", false),
1497            ("0.8.1", "~0.7.0", false),
1498            ("0.8.1", "~0.7.1", false),
1499            ("0.8.1", "~0.7.2", false),
1500            ("0.8.1", "~0.8", true),
1501            ("0.8.1", "~0.8.0", true),
1502            ("0.8.1", "~0.8.1", true),
1503            ("0.8.1", "~0.8.2", false),
1504            ("0.8.1", "~0.9.0", false),
1505            ("0.8.1", "~0.9.1", false),
1506            ("0.8.1", "~0.9.2", false),
1507            // caret
1508            ("0.8.1", "^0", true),
1509            ("0.8.1", "^1", false),
1510            ("0.8.1", "^1.0", false),
1511            ("0.8.1", "^1.0.0", false),
1512            ("0.8.1", "^0.7", false),
1513            ("0.8.1", "^0.7.0", false),
1514            ("0.8.1", "^0.7.1", false),
1515            ("0.8.1", "^0.7.2", false),
1516            ("0.8.1", "^0.8", true),
1517            ("0.8.1", "^0.8.0", true),
1518            ("0.8.1", "^0.8.1", true),
1519            ("0.8.1", "^0.8.2", false),
1520            ("0.8.1", "^0.9.0", false),
1521            ("0.8.1", "^0.9.1", false),
1522            ("0.8.1", "^0.9.2", false),
1523            // ranges
1524            ("0.8.1", "0 - 1", true),
1525            ("0.8.1", "0.1 - 1.1", true),
1526            ("0.8.1", "0.1.1 - 1.1.1", true),
1527            ("0.8.1", "0 - 0.8.1", true),
1528            ("0.8.1", "0 - 0.8.2", true),
1529            ("0.8.1", "0.7 - 0.8.1", true),
1530            ("0.8.1", "0.7 - 0.8.2", true),
1531            ("0.8.1", "0.8 - 0.8.1", true),
1532            ("0.8.1", "0.8 - 0.8.2", true),
1533            ("0.8.1", "0.8.0 - 0.8.1", true),
1534            ("0.8.1", "0.8.0 - 0.8.2", true),
1535            ("0.8.1", "0.8.0 - 0.9.0", true),
1536            ("0.8.1", "0.8.0 - 1.0.0", true),
1537            ("0.8.1", "0.8.1 - 0.8.1", true),
1538            ("0.8.1", "0.8.1 - 0.8.2", true),
1539            ("0.8.1", "0.8.1 - 0.9.0", true),
1540            ("0.8.1", "0.8.1 - 1.0.0", true),
1541            ("0.8.1", "0.7 - 0.8", true),
1542            ("0.8.1", "0.7.0 - 0.8", true),
1543            ("0.8.1", "0.8 - 0.8", true),
1544            ("0.8.1", "0.8.0 - 0.8", true),
1545            ("0.8.1", "0.8 - 0.8.0", false),
1546            ("0.8.1", "0.8 - 0.8.1", true),
1547            // or
1548            ("0.8.1", "0 || 0", true),
1549            ("0.8.1", "0 || 1", true),
1550            ("0.8.1", "1 || 0", true),
1551            ("0.8.1", "0.0 || 0.0", false),
1552            ("0.8.1", "0.0 || 1.0", false),
1553            ("0.8.1", "1.0 || 0.0", false),
1554            ("0.8.1", "0.7 || 0.8", true),
1555            ("0.8.1", "0.8 || 0.8", true),
1556            ("0.8.1", "0.8 || 0.8.1", true),
1557            ("0.8.1", "0.8 || 0.8.2", true),
1558            ("0.8.1", "0.8 || 0.9", true),
1559        ]);
1560    }
1561}