diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 5ad72a7443dd2..662bbe6a287a3 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -5,7 +5,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; use rustc_expand::panictry; -use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership}; +use rustc_parse::{self, new_sub_parser_from_file, parser::Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::symbol::Symbol; use rustc_span::{self, Pos, Span}; @@ -108,8 +108,7 @@ pub fn expand_include<'cx>( return DummyResult::any(sp); } }; - let directory_ownership = DirectoryOwnership::Owned { relative: None }; - let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp); + let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp); struct ExpandResult<'a> { p: Parser<'a>, diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 38b8ab62212e8..61a34a39d58f1 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -18,10 +18,10 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; -use rustc_parse::parser::module; +use rustc_parse::parser::module::{parse_external_mod, push_directory}; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; -use rustc_parse::DirectoryOwnership; +use rustc_parse::{Directory, DirectoryOwnership}; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; @@ -1428,8 +1428,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_items(); } + let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck. + let ident = item.ident; + match item.kind { ast::ItemKind::MacCall(..) => { + item.attrs = attrs; self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { ItemKind::MacCall(mac) => self @@ -1441,45 +1445,56 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, inline, .. }) - if item.ident != Ident::invalid() => - { - let orig_directory_ownership = self.cx.current_expansion.directory_ownership; + ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => { + let sess = self.cx.parse_sess; + let orig_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); - module.mod_path.push(item.ident); - - if inline { - module::push_directory( - item.ident, - &item.attrs, - &mut self.cx.current_expansion.directory_ownership, - &mut module.directory, - ); + + let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop. + let dir = Directory { ownership: orig_ownership, path: module.directory }; + let Directory { ownership, path } = if old_mod.inline { + // Inline `mod foo { ... }`, but we still need to push directories. + item.attrs = attrs; + push_directory(ident, &item.attrs, dir) } else { - let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner); - let mut path = match path { - FileName::Real(path) => path, - other => PathBuf::from(other.to_string()), - }; - let directory_ownership = match path.file_name().unwrap().to_str() { - Some("mod.rs") => DirectoryOwnership::Owned { relative: None }, - Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) }, - None => DirectoryOwnership::UnownedViaMod, + // We have an outline `mod foo;` so we need to parse the file. + let (new_mod, dir) = parse_external_mod(sess, ident, dir, &mut attrs, pushed); + *old_mod = new_mod; + item.attrs = attrs; + // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. + item = match self.configure(item) { + Some(node) => node, + None => { + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } + return Default::default(); + } }; - path.pop(); - module.directory = path; - self.cx.current_expansion.directory_ownership = directory_ownership; - } + dir + }; + // Set the module info before we flat map. + self.cx.current_expansion.directory_ownership = ownership; + module.directory = path; + module.mod_path.push(ident); let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); + let result = noop_flat_map_item(item, self); + + // Restore the module info. self.cx.current_expansion.module = orig_module; - self.cx.current_expansion.directory_ownership = orig_directory_ownership; + self.cx.current_expansion.directory_ownership = orig_ownership; + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } result } - - _ => noop_flat_map_item(item, self), + _ => { + item.attrs = attrs; + noop_flat_map_item(item, self) + } } } diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 2268c9b385477..1628d8bfdbc0a 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -1,4 +1,4 @@ -use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander}; +use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; @@ -18,7 +18,6 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder, FatalError}; use rustc_feature::Features; use rustc_parse::parser::Parser; -use rustc_parse::Directory; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; @@ -182,6 +181,8 @@ fn generic_extension<'cx>( lhses: &[mbe::TokenTree], rhses: &[mbe::TokenTree], ) -> Box { + let sess = cx.parse_sess; + if cx.trace_macros() { let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); trace_macros_note(&mut cx.expansions, sp, msg); @@ -209,7 +210,7 @@ fn generic_extension<'cx>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); + let parser = parser_from_cx(sess, arg.clone()); for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers @@ -222,14 +223,13 @@ fn generic_extension<'cx>( // This is used so that if a matcher is not `Success(..)`ful, // then the spans which became gated when parsing the unsuccessful matcher // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. - let mut gated_spans_snapshot = - mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); + let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. - cx.parse_sess.gated_spans.merge(gated_spans_snapshot); + sess.gated_spans.merge(gated_spans_snapshot); let rhs = match rhses[i] { // ignore delimiters @@ -258,11 +258,7 @@ fn generic_extension<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let directory = Directory { - path: cx.current_expansion.module.directory.clone(), - ownership: cx.current_expansion.directory_ownership, - }; - let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None); + let mut p = Parser::new(cx.parse_sess(), tts, false, None); p.root_module_name = cx.current_expansion.module.mod_path.last().map(|id| id.to_string()); p.last_type_ascription = cx.current_expansion.prior_type_ascription; @@ -289,7 +285,7 @@ fn generic_extension<'cx>( // The matcher was not `Success(..)`ful. // Restore to the state before snapshotting and maybe try again. - mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); + mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut()); } drop(parser); @@ -309,8 +305,7 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); - match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { + match parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) { Success(_) => { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -392,7 +387,7 @@ pub fn compile_declarative_macro( ), ]; - let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS); + let parser = Parser::new(sess, body, true, rustc_parse::MACRO_ARGUMENTS); let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) { Success(m) => m, Failure(token, msg) => { @@ -1209,16 +1204,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx<'cx>( - current_expansion: &'cx ExpansionData, - sess: &'cx ParseSess, - tts: TokenStream, -) -> Parser<'cx> { - let directory = Directory { - path: current_expansion.module.directory.clone(), - ownership: current_expansion.directory_ownership, - }; - Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS) +fn parser_from_cx<'cx>(sess: &'cx ParseSess, tts: TokenStream) -> Parser<'cx> { + Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS) } /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index d209da866e17c..c611f24942012 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -538,12 +538,3 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { fn is_cfg(attr: &Attribute) -> bool { attr.check_name(sym::cfg) } - -/// Process the potential `cfg` attributes on a module. -/// Also determine if the module should be included in this configuration. -pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec) -> bool { - // Don't perform gated feature checking. - let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - strip_unconfigured.process_cfg_attrs(attrs); - !cfg_mods || strip_unconfigured.in_cfg(&attrs) -} diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 884499ff2dd48..bcaae02942e29 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -3,6 +3,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(bindings_after_at)] +#![feature(try_blocks)] use rustc_ast::ast; use rustc_ast::token::{self, Nonterminal}; @@ -119,10 +120,7 @@ pub fn maybe_new_parser_from_source_str( name: FileName, source: String, ) -> Result, Vec> { - let mut parser = - maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))?; - parser.recurse_into_file_modules = false; - Ok(parser) + maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) } /// Creates a new parser, handling errors as appropriate if the file doesn't exist. @@ -146,12 +144,10 @@ pub fn maybe_new_parser_from_file<'a>( pub fn new_sub_parser_from_file<'a>( sess: &'a ParseSess, path: &Path, - directory_ownership: DirectoryOwnership, module_name: Option, sp: Span, ) -> Parser<'a> { let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp))); - p.directory.ownership = directory_ownership; p.root_module_name = module_name; p } @@ -257,7 +253,7 @@ pub fn stream_to_parser<'a>( stream: TokenStream, subparser_name: Option<&'static str>, ) -> Parser<'a> { - Parser::new(sess, stream, None, true, false, subparser_name) + Parser::new(sess, stream, false, subparser_name) } /// Given a stream, the `ParseSess` and the base directory, produces a parser. @@ -271,12 +267,8 @@ pub fn stream_to_parser<'a>( /// The main usage of this function is outside of rustc, for those who uses /// librustc_ast as a library. Please do not remove this function while refactoring /// just because it is not used in rustc codebase! -pub fn stream_to_parser_with_base_dir( - sess: &ParseSess, - stream: TokenStream, - base_dir: Directory, -) -> Parser<'_> { - Parser::new(sess, stream, Some(base_dir), true, false, None) +pub fn stream_to_parser_with_base_dir(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { + Parser::new(sess, stream, false, None) } /// Runs the given subparser `f` on the tokens of the given `attr`'s item. @@ -286,7 +278,7 @@ pub fn parse_in<'a, T>( name: &'static str, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, T> { - let mut parser = Parser::new(sess, tts, None, false, false, Some(name)); + let mut parser = Parser::new(sess, tts, false, Some(name)); let result = f(&mut parser)?; if parser.token != token::Eof { parser.unexpected()?; diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 40dc9275b32a5..f4862a6c87b73 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -13,7 +13,6 @@ mod stmt; use diagnostics::Error; use crate::lexer::UnmatchedBrace; -use crate::{Directory, DirectoryOwnership}; use log::debug; use rustc_ast::ast::DUMMY_NODE_ID; @@ -28,11 +27,9 @@ use rustc_ast::util::comments::{doc_comment_style, strip_doc_comment_decoration} use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_session::parse::ParseSess; -use rustc_span::source_map::respan; +use rustc_span::source_map::{respan, Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{FileName, Span, DUMMY_SP}; -use std::path::PathBuf; use std::{cmp, mem, slice}; bitflags::bitflags! { @@ -93,11 +90,6 @@ pub struct Parser<'a> { /// The previous token. pub prev_token: Token, restrictions: Restrictions, - /// Used to determine the path to externally loaded source files. - pub(super) directory: Directory, - /// `true` to parse sub-modules in other files. - // Public for rustfmt usage. - pub recurse_into_file_modules: bool, /// Name of the root module this parser originated from. If `None`, then the /// name is not known. This does not change while the parser is descending /// into modules, and sub-parsers have new values for this name. @@ -105,9 +97,6 @@ pub struct Parser<'a> { expected_tokens: Vec, token_cursor: TokenCursor, desugar_doc_comments: bool, - /// `true` we should configure out of line modules as we parse. - // Public for rustfmt usage. - pub cfg_mods: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error /// appropriately. @@ -355,8 +344,6 @@ impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, tokens: TokenStream, - directory: Option, - recurse_into_file_modules: bool, desugar_doc_comments: bool, subparser_name: Option<&'static str>, ) -> Self { @@ -365,11 +352,6 @@ impl<'a> Parser<'a> { token: Token::dummy(), prev_token: Token::dummy(), restrictions: Restrictions::empty(), - recurse_into_file_modules, - directory: Directory { - path: PathBuf::new(), - ownership: DirectoryOwnership::Owned { relative: None }, - }, root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { @@ -377,7 +359,6 @@ impl<'a> Parser<'a> { stack: Vec::new(), }, desugar_doc_comments, - cfg_mods: true, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, unclosed_delims: Vec::new(), @@ -389,18 +370,6 @@ impl<'a> Parser<'a> { // Make parser point to the first token. parser.bump(); - if let Some(directory) = directory { - parser.directory = directory; - } else if !parser.token.span.is_dummy() { - if let Some(FileName::Real(path)) = - &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path - { - if let Some(directory_path) = path.parent() { - parser.directory.path = directory_path.to_path_buf(); - } - } - } - parser } diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 66faf295b7232..695afafdd824c 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,7 +1,7 @@ use super::item::ItemInfo; use super::Parser; -use crate::{new_sub_parser_from_file, DirectoryOwnership}; +use crate::{new_sub_parser_from_file, Directory, DirectoryOwnership}; use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; use rustc_ast::attr; @@ -39,25 +39,12 @@ impl<'a> Parser<'a> { /// Parses a `mod { ... }` or `mod ;` item. pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { - let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); - let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { - if in_cfg && self.recurse_into_file_modules { - let dir = &self.directory; - parse_external_module(self.sess, self.cfg_mods, id, dir.ownership, &dir.path, attrs) - } else { - Default::default() - } + Default::default() } else { - let old_directory = self.directory.clone(); - push_directory(id, &attrs, &mut self.directory.ownership, &mut self.directory.path); - self.expect(&token::OpenDelim(token::Brace))?; - let module = self.parse_mod(&token::CloseDelim(token::Brace))?; - - self.directory = old_directory; - module + self.parse_mod(&token::CloseDelim(token::Brace))? }; attrs.append(&mut inner_attrs); Ok((id, ItemKind::Mod(module))) @@ -95,41 +82,45 @@ impl<'a> Parser<'a> { } } -fn parse_external_module( +pub fn parse_external_mod( sess: &ParseSess, - cfg_mods: bool, - id: ast::Ident, - ownership: DirectoryOwnership, - dir_path: &Path, - attrs: &[Attribute], -) -> (Mod, Vec) { - submod_path(sess, id, &attrs, ownership, dir_path) - .and_then(|r| eval_src_mod(sess, cfg_mods, r.path, r.ownership, id)) - .map_err(|mut err| err.emit()) - .unwrap_or_default() -} - -/// Reads a module from a source file. -fn eval_src_mod<'a>( - sess: &'a ParseSess, - cfg_mods: bool, - path: PathBuf, - dir_ownership: DirectoryOwnership, id: ast::Ident, -) -> PResult<'a, (Mod, Vec)> { - let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); - error_on_circular_module(sess, id.span, &path, &included_mod_stack)?; - included_mod_stack.push(path.clone()); - drop(included_mod_stack); - - let mut p0 = - new_sub_parser_from_file(sess, &path, dir_ownership, Some(id.to_string()), id.span); - p0.cfg_mods = cfg_mods; - let mut module = p0.parse_mod(&token::Eof)?; - module.0.inline = false; + Directory { mut ownership, path }: Directory, + attrs: &mut Vec, + pop_mod_stack: &mut bool, +) -> (Mod, Directory) { + // We bail on the first error, but that error does not cause a fatal error... (1) + let result: PResult<'_, _> = try { + // Extract the file path and the new ownership. + let mp = submod_path(sess, id, &attrs, ownership, &path)?; + ownership = mp.ownership; + + // Ensure file paths are acyclic. + let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); + error_on_circular_module(sess, id.span, &mp.path, &included_mod_stack)?; + included_mod_stack.push(mp.path.clone()); + *pop_mod_stack = true; // We have pushed, so notify caller. + drop(included_mod_stack); + + // Actually parse the external file as amodule. + let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), id.span); + let mut module = p0.parse_mod(&token::Eof)?; + module.0.inline = false; + module + }; + // (1) ...instead, we return a dummy module. + let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_default(); + attrs.append(&mut new_attrs); + + // Extract the directory path for submodules of `module`. + let path = sess.source_map().span_to_unmapped_path(module.inner); + let mut path = match path { + FileName::Real(path) => path, + other => PathBuf::from(other.to_string()), + }; + path.pop(); - sess.included_mod_stack.borrow_mut().pop(); - Ok(module) + (module, Directory { ownership, path }) } fn error_on_circular_module<'a>( @@ -153,12 +144,11 @@ fn error_on_circular_module<'a>( pub fn push_directory( id: Ident, attrs: &[Attribute], - dir_ownership: &mut DirectoryOwnership, - dir_path: &mut PathBuf, -) { - if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { - dir_path.push(&*path.as_str()); - *dir_ownership = DirectoryOwnership::Owned { relative: None }; + Directory { mut ownership, mut path }: Directory, +) -> Directory { + if let Some(filename) = attr::first_attr_value_str_by_name(attrs, sym::path) { + path.push(&*filename.as_str()); + ownership = DirectoryOwnership::Owned { relative: None }; } else { // We have to push on the current module name in the case of relative // paths in order to ensure that any additional module paths from inline @@ -166,14 +156,15 @@ pub fn push_directory( // // For example, a `mod z { ... }` inside `x/y.rs` should set the current // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. - if let DirectoryOwnership::Owned { relative } = dir_ownership { + if let DirectoryOwnership::Owned { relative } = &mut ownership { if let Some(ident) = relative.take() { // Remove the relative offset. - dir_path.push(&*ident.as_str()); + path.push(&*ident.as_str()); } } - dir_path.push(&*id.as_str()); + path.push(&*id.as_str()); } + Directory { ownership, path } } fn submod_path<'a>( diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 4359823be0890..d40597d8fcb0c 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -5,7 +5,6 @@ use super::pat::GateOr; use super::path::PathStyle; use super::{BlockMode, Parser, Restrictions, SemiColonMode}; use crate::maybe_whole; -use crate::DirectoryOwnership; use rustc_ast::ast; use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle}; @@ -54,7 +53,7 @@ impl<'a> Parser<'a> { // that starts like a path (1 token), but it fact not a path. // Also, we avoid stealing syntax from `parse_item_`. self.parse_stmt_path_start(lo, attrs)? - } else if let Some(item) = self.parse_stmt_item(attrs.clone())? { + } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? { // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { @@ -72,13 +71,6 @@ impl<'a> Parser<'a> { Ok(Some(stmt)) } - fn parse_stmt_item(&mut self, attrs: Vec) -> PResult<'a, Option> { - let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); - let item = self.parse_item_common(attrs, false, true, |_| true)?; - self.directory.ownership = old; - Ok(item) - } - fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec) -> PResult<'a, Stmt> { let path = self.parse_path(PathStyle::Expr)?;