提交 5675d9d2 编写于 作者: J Jeffrey Seyfried

Clean up directory ownership semantics.

上级 7b3eeea2
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
use ext::expand::{self, Expansion}; use ext::expand::{self, Expansion};
use ext::hygiene::Mark; use ext::hygiene::Mark;
use fold::{self, Folder}; use fold::{self, Folder};
use parse::{self, parser}; use parse::{self, parser, DirectoryOwnership};
use parse::token; use parse::token;
use ptr::P; use ptr::P;
use symbol::Symbol; use symbol::Symbol;
...@@ -568,9 +568,7 @@ pub struct ExpansionData { ...@@ -568,9 +568,7 @@ pub struct ExpansionData {
pub depth: usize, pub depth: usize,
pub backtrace: ExpnId, pub backtrace: ExpnId,
pub module: Rc<ModuleData>, pub module: Rc<ModuleData>,
pub directory_ownership: DirectoryOwnership,
// True if non-inline modules without a `#[path]` are forbidden at the root of this expansion.
pub no_noninline_mod: bool,
} }
/// One of these is made during expansion and incrementally updated as we go; /// One of these is made during expansion and incrementally updated as we go;
...@@ -601,7 +599,7 @@ pub fn new(parse_sess: &'a parse::ParseSess, ...@@ -601,7 +599,7 @@ pub fn new(parse_sess: &'a parse::ParseSess,
depth: 0, depth: 0,
backtrace: NO_EXPANSION, backtrace: NO_EXPANSION,
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
no_noninline_mod: false, directory_ownership: DirectoryOwnership::Owned,
}, },
} }
} }
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
use feature_gate::{self, Features}; use feature_gate::{self, Features};
use fold; use fold;
use fold::*; use fold::*;
use parse::{ParseSess, PResult, lexer}; use parse::{ParseSess, DirectoryOwnership, PResult, lexer};
use parse::parser::Parser; use parse::parser::Parser;
use parse::token; use parse::token;
use print::pprust; use print::pprust;
...@@ -727,9 +727,10 @@ fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> { ...@@ -727,9 +727,10 @@ fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
} }
fn fold_block(&mut self, block: P<Block>) -> P<Block> { fn fold_block(&mut self, block: P<Block>) -> P<Block> {
let no_noninline_mod = mem::replace(&mut self.cx.current_expansion.no_noninline_mod, true); let old_directory_ownership = self.cx.current_expansion.directory_ownership;
self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
let result = noop_fold_block(block, self); let result = noop_fold_block(block, self);
self.cx.current_expansion.no_noninline_mod = no_noninline_mod; self.cx.current_expansion.directory_ownership = old_directory_ownership;
result result
} }
...@@ -768,7 +769,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> { ...@@ -768,7 +769,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
return noop_fold_item(item, self); return noop_fold_item(item, self);
} }
let orig_no_noninline_mod = self.cx.current_expansion.no_noninline_mod; let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
let mut module = (*self.cx.current_expansion.module).clone(); let mut module = (*self.cx.current_expansion.module).clone();
module.mod_path.push(item.ident); module.mod_path.push(item.ident);
...@@ -779,23 +780,28 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> { ...@@ -779,23 +780,28 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
if inline_module { if inline_module {
if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") { if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
self.cx.current_expansion.no_noninline_mod = false; self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned;
module.directory.push(&*path.as_str()); module.directory.push(&*path.as_str());
} else { } else {
module.directory.push(&*item.ident.name.as_str()); module.directory.push(&*item.ident.name.as_str());
} }
} else { } else {
self.cx.current_expansion.no_noninline_mod = false; let mut path =
module.directory =
PathBuf::from(self.cx.parse_sess.codemap().span_to_filename(inner)); PathBuf::from(self.cx.parse_sess.codemap().span_to_filename(inner));
module.directory.pop(); let directory_ownership = match path.file_name().unwrap().to_str() {
Some("mod.rs") => DirectoryOwnership::Owned,
_ => DirectoryOwnership::UnownedViaMod,
};
path.pop();
module.directory = path;
self.cx.current_expansion.directory_ownership = directory_ownership;
} }
let orig_module = let orig_module =
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
let result = noop_fold_item(item, self); let result = noop_fold_item(item, self);
self.cx.current_expansion.module = orig_module; self.cx.current_expansion.module = orig_module;
self.cx.current_expansion.no_noninline_mod = orig_no_noninline_mod; self.cx.current_expansion.directory_ownership = orig_directory_ownership;
return result; return result;
} }
// Ensure that test functions are accessible from the test harness. // Ensure that test functions are accessible from the test harness.
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
use ext::base::*; use ext::base::*;
use ext::base; use ext::base;
use ext::build::AstBuilder; use ext::build::AstBuilder;
use parse::token; use parse::{token, DirectoryOwnership};
use parse; use parse;
use print::pprust; use print::pprust;
use ptr::P; use ptr::P;
...@@ -90,7 +90,8 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T ...@@ -90,7 +90,8 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
}; };
// The file will be added to the code map by the parser // The file will be added to the code map by the parser
let path = res_rel_file(cx, sp, Path::new(&file)); let path = res_rel_file(cx, sp, Path::new(&file));
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, true, None, sp); let directory_ownership = DirectoryOwnership::Owned;
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
struct ExpandResult<'a> { struct ExpandResult<'a> {
p: parse::parser::Parser<'a>, p: parse::parser::Parser<'a>,
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
use ext::tt::macro_parser::{parse, parse_failure_msg}; use ext::tt::macro_parser::{parse, parse_failure_msg};
use parse::ParseSess; use parse::ParseSess;
use parse::lexer::new_tt_reader; use parse::lexer::new_tt_reader;
use parse::parser::{Parser, Restrictions}; use parse::parser::Parser;
use parse::token::{self, NtTT, Token}; use parse::token::{self, NtTT, Token};
use parse::token::Token::*; use parse::token::Token::*;
use print; use print;
...@@ -117,11 +117,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, ...@@ -117,11 +117,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
let trncbr = let trncbr =
new_tt_reader(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs); new_tt_reader(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs);
let mut p = Parser::new(cx.parse_sess(), Box::new(trncbr)); let mut p = Parser::new(cx.parse_sess(), Box::new(trncbr));
p.directory = cx.current_expansion.module.directory.clone(); let module = &cx.current_expansion.module;
p.restrictions = match cx.current_expansion.no_noninline_mod { p.directory.path = module.directory.clone();
true => Restrictions::NO_NONINLINE_MOD, p.directory.ownership = cx.current_expansion.directory_ownership;
false => Restrictions::empty(), p.root_module_name =
}; module.mod_path.last().map(|id| (*id.name.as_str()).to_owned());
p.check_unknown_macro_variable(); p.check_unknown_macro_variable();
// Let the context choose how to interpret the result. // Let the context choose how to interpret the result.
// Weird, but useful for X-macros. // Weird, but useful for X-macros.
......
...@@ -76,6 +76,19 @@ pub fn codemap(&self) -> &CodeMap { ...@@ -76,6 +76,19 @@ pub fn codemap(&self) -> &CodeMap {
} }
} }
#[derive(Clone)]
pub struct Directory {
pub path: PathBuf,
pub ownership: DirectoryOwnership,
}
#[derive(Copy, Clone)]
pub enum DirectoryOwnership {
Owned,
UnownedViaBlock,
UnownedViaMod,
}
// a bunch of utility functions of the form parse_<thing>_from_<source> // a bunch of utility functions of the form parse_<thing>_from_<source>
// where <thing> includes crate, expr, item, stmt, tts, and one that // where <thing> includes crate, expr, item, stmt, tts, and one that
// uses a HOF to parse anything, and <source> includes file and // uses a HOF to parse anything, and <source> includes file and
...@@ -152,11 +165,11 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a> ...@@ -152,11 +165,11 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a>
/// On an error, use the given span as the source of the problem. /// On an error, use the given span as the source of the problem.
pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess, pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
path: &Path, path: &Path,
owns_directory: bool, directory_ownership: DirectoryOwnership,
module_name: Option<String>, module_name: Option<String>,
sp: Span) -> Parser<'a> { sp: Span) -> Parser<'a> {
let mut p = filemap_to_parser(sess, file_to_filemap(sess, path, Some(sp))); let mut p = filemap_to_parser(sess, file_to_filemap(sess, path, Some(sp)));
p.owns_directory = owns_directory; p.directory.ownership = directory_ownership;
p.root_module_name = module_name; p.root_module_name = module_name;
p p
} }
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
use parse::lexer::{Reader, TokenAndSpan}; use parse::lexer::{Reader, TokenAndSpan};
use parse::obsolete::ObsoleteSyntax; use parse::obsolete::ObsoleteSyntax;
use parse::token::{self, MatchNt, SubstNt}; use parse::token::{self, MatchNt, SubstNt};
use parse::{new_sub_parser_from_file, ParseSess}; use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership};
use util::parser::{AssocOp, Fixity}; use util::parser::{AssocOp, Fixity};
use print::pprust; use print::pprust;
use ptr::P; use ptr::P;
...@@ -68,7 +68,6 @@ ...@@ -68,7 +68,6 @@
flags Restrictions: u8 { flags Restrictions: u8 {
const RESTRICTION_STMT_EXPR = 1 << 0, const RESTRICTION_STMT_EXPR = 1 << 0,
const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1, const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
const NO_NONINLINE_MOD = 1 << 2,
} }
} }
...@@ -200,12 +199,9 @@ pub struct Parser<'a> { ...@@ -200,12 +199,9 @@ pub struct Parser<'a> {
/// extra detail when the same error is seen twice /// extra detail when the same error is seen twice
pub obsolete_set: HashSet<ObsoleteSyntax>, pub obsolete_set: HashSet<ObsoleteSyntax>,
/// Used to determine the path to externally loaded source files /// Used to determine the path to externally loaded source files
pub directory: PathBuf, pub directory: Directory,
/// Stack of open delimiters and their spans. Used for error message. /// Stack of open delimiters and their spans. Used for error message.
pub open_braces: Vec<(token::DelimToken, Span)>, pub open_braces: Vec<(token::DelimToken, Span)>,
/// Flag if this parser "owns" the directory that it is currently parsing
/// in. This will affect how nested files are looked up.
pub owns_directory: bool,
/// Name of the root module this parser originated from. If `None`, then the /// 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 /// name is not known. This does not change while the parser is descending
/// into modules, and sub-parsers have new values for this name. /// into modules, and sub-parsers have new values for this name.
...@@ -245,8 +241,8 @@ pub struct ModulePath { ...@@ -245,8 +241,8 @@ pub struct ModulePath {
} }
pub struct ModulePathSuccess { pub struct ModulePathSuccess {
pub path: ::std::path::PathBuf, pub path: PathBuf,
pub owns_directory: bool, pub directory_ownership: DirectoryOwnership,
} }
pub struct ModulePathError { pub struct ModulePathError {
...@@ -296,9 +292,8 @@ pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box<Reader+'a>, desugar_doc_c ...@@ -296,9 +292,8 @@ pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box<Reader+'a>, desugar_doc_c
quote_depth: 0, quote_depth: 0,
parsing_token_tree: false, parsing_token_tree: false,
obsolete_set: HashSet::new(), obsolete_set: HashSet::new(),
directory: PathBuf::new(), directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
open_braces: Vec::new(), open_braces: Vec::new(),
owns_directory: true,
root_module_name: None, root_module_name: None,
expected_tokens: Vec::new(), expected_tokens: Vec::new(),
tts: Vec::new(), tts: Vec::new(),
...@@ -310,8 +305,8 @@ pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box<Reader+'a>, desugar_doc_c ...@@ -310,8 +305,8 @@ pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box<Reader+'a>, desugar_doc_c
parser.token = tok.tok; parser.token = tok.tok;
parser.span = tok.sp; parser.span = tok.sp;
if parser.span != syntax_pos::DUMMY_SP { if parser.span != syntax_pos::DUMMY_SP {
parser.directory = PathBuf::from(sess.codemap().span_to_filename(parser.span)); parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
parser.directory.pop(); parser.directory.path.pop();
} }
parser parser
} }
...@@ -3966,9 +3961,11 @@ fn parse_stmt_without_recovery(&mut self, ...@@ -3966,9 +3961,11 @@ fn parse_stmt_without_recovery(&mut self,
} }
} else { } else {
// FIXME: Bad copy of attrs // FIXME: Bad copy of attrs
let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD; let old_directory_ownership =
match self.with_res(restrictions, mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
|this| this.parse_item_(attrs.clone(), false, true))? { let item = self.parse_item_(attrs.clone(), false, true)?;
self.directory.ownership = old_directory_ownership;
match item {
Some(i) => Stmt { Some(i) => Stmt {
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, i.span.hi), span: mk_sp(lo, i.span.hi),
...@@ -5271,33 +5268,33 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> ...@@ -5271,33 +5268,33 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
self.bump(); self.bump();
if in_cfg { if in_cfg {
// This mod is in an external file. Let's go get it! // This mod is in an external file. Let's go get it!
let (m, attrs) = self.eval_src_mod(id, &outer_attrs, id_span)?; let ModulePathSuccess { path, directory_ownership } =
Ok((id, m, Some(attrs))) self.submod_path(id, &outer_attrs, id_span)?;
let (module, attrs) =
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
Ok((id, module, Some(attrs)))
} else { } else {
let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() }; let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() };
Ok((id, ItemKind::Mod(placeholder), None)) Ok((id, ItemKind::Mod(placeholder), None))
} }
} else { } else {
let directory = self.directory.clone(); let old_directory = self.directory.clone();
let restrictions = self.push_directory(id, &outer_attrs); self.push_directory(id, &outer_attrs);
self.expect(&token::OpenDelim(token::Brace))?; self.expect(&token::OpenDelim(token::Brace))?;
let mod_inner_lo = self.span.lo; let mod_inner_lo = self.span.lo;
let attrs = self.parse_inner_attributes()?; let attrs = self.parse_inner_attributes()?;
let m = self.with_res(restrictions, |this| { let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
this.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo) self.directory = old_directory;
})?; Ok((id, ItemKind::Mod(module), Some(attrs)))
self.directory = directory;
Ok((id, ItemKind::Mod(m), Some(attrs)))
} }
} }
fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) -> Restrictions { fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
if let Some(path) = ::attr::first_attr_value_str_by_name(attrs, "path") { if let Some(path) = ::attr::first_attr_value_str_by_name(attrs, "path") {
self.directory.push(&*path.as_str()); self.directory.path.push(&*path.as_str());
self.restrictions - Restrictions::NO_NONINLINE_MOD self.directory.ownership = DirectoryOwnership::Owned;
} else { } else {
self.directory.push(&*id.name.as_str()); self.directory.path.push(&*id.name.as_str());
self.restrictions
} }
} }
...@@ -5317,8 +5314,14 @@ pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) - ...@@ -5317,8 +5314,14 @@ pub fn default_submod_path(id: ast::Ident, dir_path: &Path, codemap: &CodeMap) -
let secondary_exists = codemap.file_exists(&secondary_path); let secondary_exists = codemap.file_exists(&secondary_path);
let result = match (default_exists, secondary_exists) { let result = match (default_exists, secondary_exists) {
(true, false) => Ok(ModulePathSuccess { path: default_path, owns_directory: false }), (true, false) => Ok(ModulePathSuccess {
(false, true) => Ok(ModulePathSuccess { path: secondary_path, owns_directory: true }), path: default_path,
directory_ownership: DirectoryOwnership::UnownedViaMod,
}),
(false, true) => Ok(ModulePathSuccess {
path: secondary_path,
directory_ownership: DirectoryOwnership::Owned,
}),
(false, false) => Err(ModulePathError { (false, false) => Err(ModulePathError {
err_msg: format!("file not found for module `{}`", mod_name), err_msg: format!("file not found for module `{}`", mod_name),
help_msg: format!("name the file either {} or {} inside the directory {:?}", help_msg: format!("name the file either {} or {} inside the directory {:?}",
...@@ -5346,13 +5349,19 @@ fn submod_path(&mut self, ...@@ -5346,13 +5349,19 @@ fn submod_path(&mut self,
id: ast::Ident, id: ast::Ident,
outer_attrs: &[ast::Attribute], outer_attrs: &[ast::Attribute],
id_sp: Span) -> PResult<'a, ModulePathSuccess> { id_sp: Span) -> PResult<'a, ModulePathSuccess> {
if let Some(p) = Parser::submod_path_from_attr(outer_attrs, &self.directory) { if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
return Ok(ModulePathSuccess { path: p, owns_directory: true }); return Ok(ModulePathSuccess {
directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
Some("mod.rs") => DirectoryOwnership::Owned,
_ => DirectoryOwnership::UnownedViaMod,
},
path: path,
});
} }
let paths = Parser::default_submod_path(id, &self.directory, self.sess.codemap()); let paths = Parser::default_submod_path(id, &self.directory.path, self.sess.codemap());
if self.restrictions.contains(Restrictions::NO_NONINLINE_MOD) { if let DirectoryOwnership::UnownedViaBlock = self.directory.ownership {
let msg = let msg =
"Cannot declare a non-inline module inside a block unless it has a path attribute"; "Cannot declare a non-inline module inside a block unless it has a path attribute";
let mut err = self.diagnostic().struct_span_err(id_sp, msg); let mut err = self.diagnostic().struct_span_err(id_sp, msg);
...@@ -5362,10 +5371,10 @@ fn submod_path(&mut self, ...@@ -5362,10 +5371,10 @@ fn submod_path(&mut self,
err.span_note(id_sp, &msg); err.span_note(id_sp, &msg);
} }
return Err(err); return Err(err);
} else if !self.owns_directory { } else if let DirectoryOwnership::UnownedViaMod = self.directory.ownership {
let mut err = self.diagnostic().struct_span_err(id_sp, let mut err = self.diagnostic().struct_span_err(id_sp,
"cannot declare a new module at this location"); "cannot declare a new module at this location");
let this_module = match self.directory.file_name() { let this_module = match self.directory.path.file_name() {
Some(file_name) => file_name.to_str().unwrap().to_owned(), Some(file_name) => file_name.to_str().unwrap().to_owned(),
None => self.root_module_name.as_ref().unwrap().clone(), None => self.root_module_name.as_ref().unwrap().clone(),
}; };
...@@ -5390,25 +5399,11 @@ fn submod_path(&mut self, ...@@ -5390,25 +5399,11 @@ fn submod_path(&mut self,
/// Read a module from a source file. /// Read a module from a source file.
fn eval_src_mod(&mut self, fn eval_src_mod(&mut self,
id: ast::Ident, path: PathBuf,
outer_attrs: &[ast::Attribute], directory_ownership: DirectoryOwnership,
name: String,
id_sp: Span) id_sp: Span)
-> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> { -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
let ModulePathSuccess { path, owns_directory } = self.submod_path(id,
outer_attrs,
id_sp)?;
self.eval_src_mod_from_path(path,
owns_directory,
id.to_string(),
id_sp)
}
fn eval_src_mod_from_path(&mut self,
path: PathBuf,
owns_directory: bool,
name: String,
id_sp: Span) -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
let mut err = String::from("circular modules: "); let mut err = String::from("circular modules: ");
...@@ -5423,7 +5418,8 @@ fn eval_src_mod_from_path(&mut self, ...@@ -5423,7 +5418,8 @@ fn eval_src_mod_from_path(&mut self,
included_mod_stack.push(path.clone()); included_mod_stack.push(path.clone());
drop(included_mod_stack); drop(included_mod_stack);
let mut p0 = new_sub_parser_from_file(self.sess, &path, owns_directory, Some(name), id_sp); let mut p0 =
new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp);
let mod_inner_lo = p0.span.lo; let mod_inner_lo = p0.span.lo;
let mod_attrs = p0.parse_inner_attributes()?; let mod_attrs = p0.parse_inner_attributes()?;
let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册