1,
&[
kw::Impl,
+ kw::Static,
kw::Const,
kw::Async,
kw::Fn,
let vis = self.parse_visibility(FollowedByType::No)?;
let defaultness = self.parse_defaultness();
- let (ident, kind, generics) = if self.eat_keyword(kw::Type) {
+ let (ident, kind) = if self.eat_keyword(kw::Type) {
self.parse_assoc_ty()?
} else if self.check_fn_front_matter() {
let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?;
- (ident, AssocItemKind::Fn(sig, body), generics)
- } else if self.check_keyword(kw::Const) {
- self.parse_assoc_const()?
+ (ident, AssocItemKind::Fn(sig, generics, body))
+ } else if self.is_static_global() {
+ self.bump(); // `static`
+ let mutbl = self.parse_mutability();
+ let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?;
+ (ident, AssocItemKind::Static(ty, mutbl, expr))
+ } else if self.eat_keyword(kw::Const) {
+ let (ident, ty, expr) = self.parse_item_const_common(None)?;
+ (ident, AssocItemKind::Const(ty, expr))
} else if self.isnt_macro_invocation() {
return Err(self.missing_assoc_item_kind_err("associated", self.prev_span));
} else if self.token.is_path_start() {
let mac = self.parse_item_macro(&vis)?;
*at_end = true;
- (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default())
+ (Ident::invalid(), AssocItemKind::Macro(mac))
} else {
self.recover_attrs_no_item(&attrs)?;
self.unexpected()?
let span = lo.to(self.prev_span);
let id = DUMMY_NODE_ID;
- Ok(AssocItem { id, span, ident, attrs, vis, defaultness, generics, kind, tokens: None })
- }
-
- /// This parses the grammar:
- ///
- /// AssocConst = "const" Ident ":" Ty "=" Expr ";"
- fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
- self.expect_keyword(kw::Const)?;
- let ident = self.parse_ident()?;
- self.expect(&token::Colon)?;
- let ty = self.parse_ty()?;
- let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
- self.expect_semi()?;
- Ok((ident, AssocItemKind::Const(ty, expr), Generics::default()))
+ Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None })
}
/// Parses the following grammar:
///
/// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]
- fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> {
+ fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind)> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
self.expect_semi()?;
- Ok((ident, AssocItemKind::TyAlias(bounds, default), generics))
+ Ok((ident, AssocItemKind::TyAlias(generics, bounds, default)))
}
/// Parses a `UseTree`.
let lo = self.token.span;
let vis = self.parse_visibility(FollowedByType::No)?;
- let (ident, kind) = if self.check_keyword(kw::Type) {
+ let (ident, kind) = if self.eat_keyword(kw::Type) {
// FOREIGN TYPE ITEM
self.parse_item_foreign_type()?
} else if self.check_fn_front_matter() {
} else if self.is_static_global() {
// FOREIGN STATIC ITEM
self.bump(); // `static`
- self.parse_item_foreign_static()?
- } else if self.token.is_keyword(kw::Const) {
- // Treat `const` as `static` for error recovery, but don't add it to expected tokens.
- self.bump(); // `const`
- self.struct_span_err(self.prev_span, "extern items cannot be `const`")
- .span_suggestion(
- self.prev_span,
- "try using a static value",
- "static".to_owned(),
- Applicability::MachineApplicable,
- )
- .emit();
- self.parse_item_foreign_static()?
+ let mutbl = self.parse_mutability();
+ let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?;
+ (ident, ForeignItemKind::Static(ty, mutbl, expr))
+ } else if self.eat_keyword(kw::Const) {
+ let (ident, ty, expr) = self.parse_item_const_common(None)?;
+ (ident, ForeignItemKind::Const(ty, expr))
} else if self.isnt_macro_invocation() {
return Err(self.missing_assoc_item_kind_err("extern", self.prev_span));
} else if self.token.is_path_start() {
Ok(P(self.mk_item(lo, ident, kind, vis, attrs)))
}
- /// Parses a static item from a foreign module.
- /// Assumes that the `static` keyword is already parsed.
- fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
- let mutbl = self.parse_mutability();
- let ident = self.parse_ident()?;
- self.expect(&token::Colon)?;
- let ty = self.parse_ty()?;
- self.expect_semi()?;
- Ok((ident, ForeignItemKind::Static(ty, mutbl)))
- }
-
/// Parses a type from a foreign module.
fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> {
- self.expect_keyword(kw::Type)?;
- let ident = self.parse_ident()?;
- self.expect_semi()?;
- Ok((ident, ForeignItemKind::Ty))
+ let (ident, kind) = self.parse_assoc_ty()?;
+ let kind = match kind {
+ AssocItemKind::TyAlias(g, b, d) => ForeignItemKind::TyAlias(g, b, d),
+ _ => unreachable!(),
+ };
+ Ok((ident, kind))
}
fn is_static_global(&mut self) -> bool {
}
}
- /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with
+ /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with
/// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
///
/// When `m` is `"const"`, `$ident` may also be `"_"`.
fn parse_item_const(&mut self, m: Option<Mutability>) -> PResult<'a, ItemInfo> {
+ let (id, ty, expr) = self.parse_item_const_common(m)?;
+ let item = match m {
+ Some(m) => ItemKind::Static(ty, m, expr),
+ None => ItemKind::Const(ty, expr),
+ };
+ Ok((id, item))
+ }
+
+ /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with
+ /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
+ ///
+ /// When `m` is `"const"`, `$ident` may also be `"_"`.
+ fn parse_item_const_common(
+ &mut self,
+ m: Option<Mutability>,
+ ) -> PResult<'a, (Ident, P<Ty>, Option<P<ast::Expr>>)> {
let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?;
// Parse the type of a `const` or `static mut?` item.
// That is, the `":" $ty` fragment.
- let ty = if self.token == token::Eq {
- self.recover_missing_const_type(id, m)
- } else {
- // Not `=` so expect `":"" $ty` as usual.
- self.expect(&token::Colon)?;
+ let ty = if self.eat(&token::Colon) {
self.parse_ty()?
+ } else {
+ self.recover_missing_const_type(id, m)
};
- self.expect(&token::Eq)?;
- let e = self.parse_expr()?;
+ let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None };
self.expect_semi()?;
- let item = match m {
- Some(m) => ItemKind::Static(ty, m, e),
- None => ItemKind::Const(ty, e),
- };
- Ok((id, item))
+ Ok((id, ty, expr))
}
- /// We were supposed to parse `:` but instead, we're already at `=`.
+ /// We were supposed to parse `:` but the `:` was missing.
/// This means that the type is missing.
fn recover_missing_const_type(&mut self, id: Ident, m: Option<Mutability>) -> P<Ty> {
// Construct the error and stash it away with the hope