diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2020-02-02 14:15:52 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-02 14:15:52 +0100 |
| commit | 5951cd3dda738ee6187ecea040738cbad57e04e4 (patch) | |
| tree | d08a2ad41197c6305fbff803237b6ae90f5d1abb /src/librustc_parse/parser | |
| parent | 2e1790dda1a097c2498960413dd8a89f0a18e05f (diff) | |
| parent | 71a6f58229c00720b35579856bdb64e2a19af521 (diff) | |
| download | rust-5951cd3dda738ee6187ecea040738cbad57e04e4.tar.gz rust-5951cd3dda738ee6187ecea040738cbad57e04e4.zip | |
Rollup merge of #68764 - Centril:self-semantic, r=petrochenkov
parser: syntactically allow `self` in all `fn` contexts Part of https://github.com/rust-lang/rust/pull/68728. `self` parameters are now *syntactically* allowed as the first parameter irrespective of item context (and in function pointers). Instead, semantic validation (`ast_validation`) is used. r? @petrochenkov
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/diagnostics.rs | 25 | ||||
| -rw-r--r-- | src/librustc_parse/parser/item.rs | 64 | ||||
| -rw-r--r-- | src/librustc_parse/parser/ty.rs | 3 |
3 files changed, 30 insertions, 62 deletions
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index e2227f66973..b1cab591fd9 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1336,8 +1336,7 @@ impl<'a> Parser<'a> { err: &mut DiagnosticBuilder<'_>, pat: P<ast::Pat>, require_name: bool, - is_self_allowed: bool, - is_trait_item: bool, + first_param: bool, ) -> Option<Ident> { // If we find a pattern followed by an identifier, it could be an (incorrect) // C-style parameter declaration. @@ -1357,13 +1356,12 @@ impl<'a> Parser<'a> { return Some(ident); } else if let PatKind::Ident(_, ident, _) = pat.kind { if require_name - && (is_trait_item - || self.token == token::Comma + && (self.token == token::Comma || self.token == token::Lt || self.token == token::CloseDelim(token::Paren)) { // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}` - if is_self_allowed { + if first_param { err.span_suggestion( pat.span, "if this is a `self` type, give it a parameter name", @@ -1420,21 +1418,12 @@ impl<'a> Parser<'a> { Ok((pat, ty)) } - pub(super) fn recover_bad_self_param( - &mut self, - mut param: ast::Param, - is_trait_item: bool, - ) -> PResult<'a, ast::Param> { + pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> { let sp = param.pat.span; param.ty.kind = TyKind::Err; - let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function"); - if is_trait_item { - err.span_label(sp, "must be the first associated function parameter"); - } else { - err.span_label(sp, "not valid as function parameter"); - err.note("`self` is only valid as the first parameter of an associated function"); - } - err.emit(); + self.struct_span_err(sp, "unexpected `self` parameter in function") + .span_label(sp, "must be the first parameter of an associated function") + .emit(); Ok(param) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 7f15c403e9a..94b72307dae 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1715,8 +1715,6 @@ impl<'a> Parser<'a> { /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). pub(super) struct ParamCfg { - /// Is `self` is allowed as the first parameter? - pub is_self_allowed: bool, /// `is_name_required` decides if, per-parameter, /// the parameter must have a pattern or just a type. pub is_name_required: fn(&token::Token) -> bool, @@ -1732,8 +1730,8 @@ impl<'a> Parser<'a> { attrs: Vec<Attribute>, header: FnHeader, ) -> PResult<'a, Option<P<Item>>> { - let (ident, decl, generics) = - self.parse_fn_sig(ParamCfg { is_self_allowed: false, is_name_required: |_| true })?; + let cfg = ParamCfg { is_name_required: |_| true }; + let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let kind = ItemKind::Fn(FnSig { decl, header }, generics, body); self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs))) @@ -1747,20 +1745,13 @@ impl<'a> Parser<'a> { attrs: Vec<Attribute>, extern_sp: Span, ) -> PResult<'a, P<ForeignItem>> { + let cfg = ParamCfg { is_name_required: |_| true }; self.expect_keyword(kw::Fn)?; - let (ident, decl, generics) = - self.parse_fn_sig(ParamCfg { is_self_allowed: false, is_name_required: |_| true })?; + let (ident, decl, generics) = self.parse_fn_sig(&cfg)?; let span = lo.to(self.token.span); self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?; - Ok(P(ast::ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Fn(decl, generics), - id: DUMMY_NODE_ID, - span, - vis, - tokens: None, - })) + let kind = ForeignItemKind::Fn(decl, generics); + Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None })) } fn parse_assoc_fn( @@ -1770,8 +1761,7 @@ impl<'a> Parser<'a> { is_name_required: fn(&token::Token) -> bool, ) -> PResult<'a, (Ident, AssocItemKind, Generics)> { let header = self.parse_fn_front_matter()?; - let (ident, decl, generics) = - self.parse_fn_sig(ParamCfg { is_self_allowed: true, is_name_required })?; + let (ident, decl, generics) = self.parse_fn_sig(&ParamCfg { is_name_required })?; let sig = FnSig { header, decl }; let body = self.parse_assoc_fn_body(at_end, attrs)?; Ok((ident, AssocItemKind::Fn(sig, body), generics)) @@ -1847,7 +1837,7 @@ impl<'a> Parser<'a> { } /// Parse the "signature", including the identifier, parameters, and generics of a function. - fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> { + fn parse_fn_sig(&mut self, cfg: &ParamCfg) -> PResult<'a, (Ident, P<FnDecl>, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; let decl = self.parse_fn_decl(cfg, true)?; @@ -1858,7 +1848,7 @@ impl<'a> Parser<'a> { /// Parses the parameter list and result type of a function declaration. pub(super) fn parse_fn_decl( &mut self, - cfg: ParamCfg, + cfg: &ParamCfg, ret_allow_plus: bool, ) -> PResult<'a, P<FnDecl>> { Ok(P(FnDecl { @@ -1868,11 +1858,11 @@ impl<'a> Parser<'a> { } /// Parses the parameter list of a function, including the `(` and `)` delimiters. - fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> { - let is_trait_item = cfg.is_self_allowed; - // Parse the arguments, starting out with `self` being possibly allowed... + fn parse_fn_params(&mut self, cfg: &ParamCfg) -> PResult<'a, Vec<Param>> { + let mut first_param = true; + // Parse the arguments, starting out with `self` being allowed... let (mut params, _) = self.parse_paren_comma_seq(|p| { - let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| { + let param = p.parse_param_general(&cfg, first_param).or_else(|mut e| { e.emit(); let lo = p.prev_span; // Skip every token until next possible arg or end. @@ -1881,7 +1871,7 @@ impl<'a> Parser<'a> { Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span)))) }); // ...now that we've parsed the first argument, `self` is no longer allowed. - cfg.is_self_allowed = false; + first_param = false; param })?; // Replace duplicated recovered params with `_` pattern to avoid unnecessary errors. @@ -1889,21 +1879,17 @@ impl<'a> Parser<'a> { Ok(params) } - /// Skips unexpected attributes and doc comments in this position and emits an appropriate - /// error. - /// This version of parse param doesn't necessarily require identifier names. - fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> { + /// Parses a single function parameter. + /// + /// - `self` is syntactically allowed when `first_param` holds. + fn parse_param_general(&mut self, cfg: &ParamCfg, first_param: bool) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. if let Some(mut param) = self.parse_self_param()? { param.attrs = attrs.into(); - return if cfg.is_self_allowed { - Ok(param) - } else { - self.recover_bad_self_param(param, is_trait_item) - }; + return if first_param { Ok(param) } else { self.recover_bad_self_param(param) }; } let is_name_required = match self.token.kind { @@ -1915,13 +1901,9 @@ impl<'a> Parser<'a> { let pat = self.parse_fn_param_pat()?; if let Err(mut err) = self.expect(&token::Colon) { - return if let Some(ident) = self.parameter_without_type( - &mut err, - pat, - is_name_required, - cfg.is_self_allowed, - is_trait_item, - ) { + return if let Some(ident) = + self.parameter_without_type(&mut err, pat, is_name_required, first_param) + { err.emit(); Ok(dummy_arg(ident)) } else { @@ -1975,8 +1957,6 @@ impl<'a> Parser<'a> { } /// Returns the parsed optional self parameter and whether a self shortcut was used. - /// - /// See `parse_self_param_with_attrs` to collect attributes. fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> { // Extract an identifier *after* having confirmed that the token is one. let expect_self_ident = |this: &mut Self| { diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index a4cc9fa48f2..c9c2cbb98ca 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -288,8 +288,7 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; - let cfg = ParamCfg { is_self_allowed: false, is_name_required: |_| false }; - let decl = self.parse_fn_decl(cfg, false)?; + let decl = self.parse_fn_decl(&ParamCfg { is_name_required: |_| false }, false)?; Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl }))) } |
