,
+ lo: Span,
+ vis: Visibility,
+ info: ItemInfo,
+ ) -> PResult<'a, Option>> {
+ let (ident, item, extra_attrs) = info;
+ let span = lo.to(self.prev_span);
+ let attrs = maybe_append(attrs, extra_attrs);
+ Ok(Some(self.mk_item(span, ident, item, vis, attrs)))
}
fn recover_first_param(&mut self) -> &'static str {
@@ -727,16 +721,7 @@ impl<'a> Parser<'a> {
};
(name, kind, generics)
} else if self.is_const_item() {
- // This parses the grammar:
- // ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
- self.expect_keyword(kw::Const)?;
- let name = self.parse_ident()?;
- self.expect(&token::Colon)?;
- let typ = self.parse_ty()?;
- self.expect(&token::Eq)?;
- let expr = self.parse_expr()?;
- self.expect(&token::Semi)?;
- (name, ast::ImplItemKind::Const(typ, expr), Generics::default())
+ self.parse_impl_const()?
} else {
let (name, inner_attrs, generics, kind) = self.parse_impl_method(&vis, at_end)?;
attrs.extend(inner_attrs);
@@ -785,12 +770,25 @@ impl<'a> Parser<'a> {
!self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
}
+ /// This parses the grammar:
+ /// ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
+ fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> {
+ self.expect_keyword(kw::Const)?;
+ let name = self.parse_ident()?;
+ self.expect(&token::Colon)?;
+ let typ = self.parse_ty()?;
+ self.expect(&token::Eq)?;
+ let expr = self.parse_expr()?;
+ self.expect(&token::Semi)?;
+ Ok((name, ImplItemKind::Const(typ, expr), Generics::default()))
+ }
+
/// Parses a method or a macro invocation in a trait impl.
fn parse_impl_method(
&mut self,
vis: &Visibility,
at_end: &mut bool
- ) -> PResult<'a, (Ident, Vec, Generics, ast::ImplItemKind)> {
+ ) -> PResult<'a, (Ident, Vec, Generics, ImplItemKind)> {
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
// method macro
@@ -807,14 +805,15 @@ impl<'a> Parser<'a> {
/// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
fn parse_method_sig(
&mut self,
- is_name_required: impl Copy + Fn(&token::Token) -> bool,
+ is_name_required: fn(&token::Token) -> bool,
) -> PResult<'a, (Ident, MethodSig, Generics)> {
let header = self.parse_fn_front_matter()?;
- let (ident, mut generics) = self.parse_fn_header()?;
- let decl = self.parse_fn_decl_with_self(is_name_required)?;
- let sig = MethodSig { header, decl };
- generics.where_clause = self.parse_where_clause()?;
- Ok((ident, sig, generics))
+ let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
+ is_self_allowed: true,
+ allow_c_variadic: false,
+ is_name_required,
+ })?;
+ Ok((ident, MethodSig { header, decl }, generics))
}
/// Parses all the "front matter" for a `fn` declaration, up to
@@ -849,8 +848,16 @@ impl<'a> Parser<'a> {
Ok(FnHeader { constness, unsafety, asyncness, abi })
}
- /// Parses `trait Foo { ... }` or `trait Foo = Bar;`.
- fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
+ /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`.
+ fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
+ // Parse optional `auto` prefix.
+ let is_auto = if self.eat_keyword(kw::Auto) {
+ IsAuto::Yes
+ } else {
+ IsAuto::No
+ };
+
+ self.expect_keyword(kw::Trait)?;
let ident = self.parse_ident()?;
let mut tps = self.parse_generics()?;
@@ -935,30 +942,20 @@ impl<'a> Parser<'a> {
Ok(item)
}
- fn parse_trait_item_(&mut self,
- at_end: &mut bool,
- mut attrs: Vec) -> PResult<'a, TraitItem> {
+ fn parse_trait_item_(
+ &mut self,
+ at_end: &mut bool,
+ mut attrs: Vec,
+ ) -> PResult<'a, TraitItem> {
let lo = self.token.span;
self.eat_bad_pub();
let (name, kind, generics) = if self.eat_keyword(kw::Type) {
self.parse_trait_item_assoc_ty()?
} else if self.is_const_item() {
- self.expect_keyword(kw::Const)?;
- let ident = self.parse_ident()?;
- self.expect(&token::Colon)?;
- let ty = self.parse_ty()?;
- let default = if self.eat(&token::Eq) {
- let expr = self.parse_expr()?;
- self.expect(&token::Semi)?;
- Some(expr)
- } else {
- self.expect(&token::Semi)?;
- None
- };
- (ident, TraitItemKind::Const(ty, default), Generics::default())
+ self.parse_trait_item_const()?
} else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? {
// trait item macro.
- (Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default())
+ (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default())
} else {
// This is somewhat dubious; We don't want to allow
// argument names to be left off if there is a definition...
@@ -966,7 +963,7 @@ impl<'a> Parser<'a> {
// We don't allow argument names to be left off in edition 2018.
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
let body = self.parse_trait_method_body(at_end, &mut attrs)?;
- (ident, ast::TraitItemKind::Method(sig, body), generics)
+ (ident, TraitItemKind::Method(sig, body), generics)
};
Ok(TraitItem {
@@ -980,6 +977,20 @@ impl<'a> Parser<'a> {
})
}
+ fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
+ self.expect_keyword(kw::Const)?;
+ let ident = self.parse_ident()?;
+ self.expect(&token::Colon)?;
+ let ty = self.parse_ty()?;
+ let default = if self.eat(&token::Eq) {
+ Some(self.parse_expr()?)
+ } else {
+ None
+ };
+ self.expect(&token::Semi)?;
+ Ok((ident, TraitItemKind::Const(ty, default), Generics::default()))
+ }
+
/// Parse the "body" of a method in a trait item definition.
/// This can either be `;` when there's no body,
/// or e.g. a block when the method is a provided one.
@@ -1020,8 +1031,7 @@ impl<'a> Parser<'a> {
/// Parses the following grammar:
///
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
- fn parse_trait_item_assoc_ty(&mut self)
- -> PResult<'a, (Ident, TraitItemKind, Generics)> {
+ fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
@@ -1067,21 +1077,13 @@ impl<'a> Parser<'a> {
);
}
- if self.eat(&token::BinOp(token::Star)) {
- UseTreeKind::Glob
- } else {
- UseTreeKind::Nested(self.parse_use_tree_list()?)
- }
+ self.parse_use_tree_glob_or_nested()?
} else {
// `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
prefix = self.parse_path(PathStyle::Mod)?;
if self.eat(&token::ModSep) {
- if self.eat(&token::BinOp(token::Star)) {
- UseTreeKind::Glob
- } else {
- UseTreeKind::Nested(self.parse_use_tree_list()?)
- }
+ self.parse_use_tree_glob_or_nested()?
} else {
UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID)
}
@@ -1090,6 +1092,15 @@ impl<'a> Parser<'a> {
Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
}
+ /// Parses `*` or `{...}`.
+ fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> {
+ Ok(if self.eat(&token::BinOp(token::Star)) {
+ UseTreeKind::Glob
+ } else {
+ UseTreeKind::Nested(self.parse_use_tree_list()?)
+ })
+ }
+
/// Parses a `UseTreeKind::Nested(list)`.
///
/// ```
@@ -1191,38 +1202,34 @@ impl<'a> Parser<'a> {
attrs: Vec,
header: FnHeader,
) -> PResult<'a, Option>> {
- let allow_c_variadic = header.abi == Abi::C && header.unsafety == Unsafety::Unsafe;
- let (ident, decl, generics) = self.parse_fn_sig(allow_c_variadic)?;
+ let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
+ is_self_allowed: false,
+ allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe,
+ is_name_required: |_| true,
+ })?;
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
- let span = lo.to(self.prev_span);
let kind = ItemKind::Fn(decl, header, generics, body);
- let attrs = maybe_append(attrs, Some(inner_attrs));
- Ok(Some(self.mk_item(span, ident, kind, vis, attrs)))
+ self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs)))
}
/// Parse the "signature", including the identifier, parameters, and generics of a function.
- fn parse_fn_sig(
- &mut self,
- allow_c_variadic: bool,
- ) -> PResult<'a, (Ident, P, Generics)> {
- let (ident, mut generics) = self.parse_fn_header()?;
- let decl = self.parse_fn_decl(allow_c_variadic)?;
+ fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P, Generics)> {
+ let ident = self.parse_ident()?;
+ let mut generics = self.parse_generics()?;
+ let decl = self.parse_fn_decl(cfg, true)?;
generics.where_clause = self.parse_where_clause()?;
Ok((ident, decl, generics))
}
- /// Parses the name and optional generic types of a function header.
- fn parse_fn_header(&mut self) -> PResult<'a, (Ident, Generics)> {
- let id = self.parse_ident()?;
- let generics = self.parse_generics()?;
- Ok((id, generics))
- }
-
/// Parses the parameter list and result type of a function declaration.
- fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P> {
+ pub(super) fn parse_fn_decl(
+ &mut self,
+ cfg: ParamCfg,
+ ret_allow_plus: bool,
+ ) -> PResult<'a, P> {
Ok(P(FnDecl {
- inputs: self.parse_fn_params(true, allow_c_variadic)?,
- output: self.parse_ret_ty(true)?,
+ inputs: self.parse_fn_params(cfg)?,
+ output: self.parse_ret_ty(ret_allow_plus)?,
}))
}
@@ -1346,7 +1353,11 @@ impl<'a> Parser<'a> {
extern_sp: Span,
) -> PResult<'a, ForeignItem> {
self.expect_keyword(kw::Fn)?;
- let (ident, decl, generics) = self.parse_fn_sig(true)?;
+ let (ident, decl, generics) = self.parse_fn_sig(super::ParamCfg {
+ is_self_allowed: false,
+ allow_c_variadic: true,
+ is_name_required: |_| true,
+ })?;
let span = lo.to(self.token.span);
self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?;
Ok(ast::ForeignItem {
diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs
index 41ee2a1599d74..018b5951e6e2e 100644
--- a/src/libsyntax/parse/parser/ty.rs
+++ b/src/libsyntax/parse/parser/ty.rs
@@ -4,13 +4,11 @@ use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
use crate::ptr::P;
use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
use crate::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
-use crate::ast::{Mutability, AnonConst, FnDecl, Mac};
+use crate::ast::{Mutability, AnonConst, Mac};
use crate::parse::token::{self, Token};
use crate::source_map::Span;
use crate::symbol::{kw};
-use rustc_target::spec::abi::Abi;
-
use errors::{Applicability, pluralise};
/// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT`,
@@ -281,19 +279,14 @@ impl<'a> Parser<'a> {
*/
let unsafety = self.parse_unsafety();
- let abi = if self.eat_keyword(kw::Extern) {
- self.parse_opt_abi()?.unwrap_or(Abi::C)
- } else {
- Abi::Rust
- };
-
+ let abi = self.parse_extern_abi()?;
self.expect_keyword(kw::Fn)?;
- let inputs = self.parse_fn_params(false, true)?;
- let ret_ty = self.parse_ret_ty(false)?;
- let decl = P(FnDecl {
- inputs,
- output: ret_ty,
- });
+ let cfg = super::ParamCfg {
+ is_self_allowed: false,
+ allow_c_variadic: true,
+ is_name_required: |_| false,
+ };
+ let decl = self.parse_fn_decl(cfg, false)?;
Ok(TyKind::BareFn(P(BareFnTy {
abi,
unsafety,
diff --git a/src/test/ui/parser/issue-33413.rs b/src/test/ui/parser/issue-33413.rs
index 22f80a8aae866..7291732cebe4a 100644
--- a/src/test/ui/parser/issue-33413.rs
+++ b/src/test/ui/parser/issue-33413.rs
@@ -3,6 +3,7 @@ struct S;
impl S {
fn f(*, a: u8) -> u8 {}
//~^ ERROR expected parameter name, found `*`
+ //~| ERROR mismatched types
}
fn main() {}
diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issue-33413.stderr
index 9e1178e8ac1f3..7e5c348e36cea 100644
--- a/src/test/ui/parser/issue-33413.stderr
+++ b/src/test/ui/parser/issue-33413.stderr
@@ -4,5 +4,17 @@ error: expected parameter name, found `*`
LL | fn f(*, a: u8) -> u8 {}
| ^ expected parameter name
-error: aborting due to previous error
+error[E0308]: mismatched types
+ --> $DIR/issue-33413.rs:4:23
+ |
+LL | fn f(*, a: u8) -> u8 {}
+ | - ^^ expected u8, found ()
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+ = note: expected type `u8`
+ found type `()`
+
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0308`.