diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index a0ea09720b4..685b21a1717 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -38,6 +38,7 @@ use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use std::convert::TryFrom; use std::fmt; use std::iter; @@ -2668,6 +2669,20 @@ impl From for ItemKind { } } +impl TryFrom for AssocItemKind { + type Error = ItemKind; + + fn try_from(item_kind: ItemKind) -> Result { + Ok(match item_kind { + ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), + ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d), + ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d), + ItemKind::Mac(a) => AssocItemKind::Macro(a), + _ => return Err(item_kind), + }) + } +} + /// An item in `extern` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { @@ -2692,4 +2707,18 @@ impl From for ItemKind { } } +impl TryFrom for ForeignItemKind { + type Error = ItemKind; + + fn try_from(item_kind: ItemKind) -> Result { + Ok(match item_kind { + ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), + ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d), + ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d), + ItemKind::Mac(a) => ForeignItemKind::Macro(a), + _ => return Err(item_kind), + }) + } +} + pub type ForeignItem = Item; diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index cf07e452acb..08e74034e86 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -24,6 +24,7 @@ use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use log::debug; +use std::convert::TryFrom; use std::mem; pub(super) type ItemInfo = (Ident, ItemKind); @@ -647,16 +648,16 @@ impl<'a> Parser<'a> { /// Parses associated items. fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { Ok(self.parse_item_(req_name)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { - let kind = match kind { - ItemKind::Mac(a) => AssocItemKind::Macro(a), - ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d), - ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d), - ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), - ItemKind::Static(a, _, b) => { - self.struct_span_err(span, "associated `static` items are not allowed").emit(); - AssocItemKind::Const(Defaultness::Final, a, b) - } - _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), + let kind = match AssocItemKind::try_from(kind) { + Ok(kind) => kind, + Err(kind) => match kind { + ItemKind::Static(a, _, b) => { + self.struct_span_err(span, "associated `static` items are not allowed") + .emit(); + AssocItemKind::Const(Defaultness::Final, a, b) + } + _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), + }, }; Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) })) @@ -833,16 +834,15 @@ impl<'a> Parser<'a> { /// Parses a foreign item (one in an `extern { ... }` block). pub fn parse_foreign_item(&mut self) -> PResult<'a, Option>>> { Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { - let kind = match kind { - ItemKind::Mac(a) => ForeignItemKind::Macro(a), - ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d), - ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d), - ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), - ItemKind::Const(_, a, b) => { - self.error_on_foreign_const(span, ident); - ForeignItemKind::Static(a, Mutability::Not, b) - } - _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), + let kind = match ForeignItemKind::try_from(kind) { + Ok(kind) => kind, + Err(kind) => match kind { + ItemKind::Const(_, a, b) => { + self.error_on_foreign_const(span, ident); + ForeignItemKind::Static(a, Mutability::Not, b) + } + _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), + }, }; Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) }))