1
Fork 0

Refactor away the prelude injection pass

This commit is contained in:
Jeffrey Seyfried 2016-06-05 09:56:05 +00:00
parent 0f37edb758
commit 49de80d7ea
5 changed files with 77 additions and 143 deletions

View file

@ -601,7 +601,8 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session,
})?; })?;
krate = time(time_passes, "crate injection", || { krate = time(time_passes, "crate injection", || {
syntax::std_inject::maybe_inject_crates_ref(krate, sess.opts.alt_std_name.clone()) let alt_std_name = sess.opts.alt_std_name.clone();
syntax::std_inject::maybe_inject_crates_ref(&sess.parse_sess, krate, alt_std_name)
}); });
let macros = time(time_passes, let macros = time(time_passes,
@ -720,10 +721,6 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session,
sess.diagnostic()) sess.diagnostic())
}); });
krate = time(time_passes,
"prelude injection",
|| syntax::std_inject::maybe_inject_prelude(&sess.parse_sess, krate));
time(time_passes, time(time_passes,
"checking for inline asm in case the target doesn't support it", "checking for inline asm in case the target doesn't support it",
|| no_asm::check_crate(sess, &krate)); || no_asm::check_crate(sess, &krate));

View file

@ -27,7 +27,7 @@ use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty::{self, VariantKind}; use rustc::ty::{self, VariantKind};
use syntax::ast::Name; use syntax::ast::Name;
use syntax::attr::AttrMetaMethods; use syntax::attr;
use syntax::parse::token; use syntax::parse::token;
use syntax::codemap::{Span, DUMMY_SP}; use syntax::codemap::{Span, DUMMY_SP};
@ -57,6 +57,9 @@ impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
impl<'b> Resolver<'b> { impl<'b> Resolver<'b> {
/// Constructs the reduced graph for the entire crate. /// Constructs the reduced graph for the entire crate.
pub fn build_reduced_graph(&mut self, krate: &Crate) { pub fn build_reduced_graph(&mut self, krate: &Crate) {
let no_implicit_prelude = attr::contains_name(&krate.attrs, "no_implicit_prelude");
self.graph_root.no_implicit_prelude.set(no_implicit_prelude);
let mut visitor = BuildReducedGraphVisitor { let mut visitor = BuildReducedGraphVisitor {
parent: self.graph_root, parent: self.graph_root,
resolver: self, resolver: self,
@ -128,7 +131,7 @@ impl<'b> Resolver<'b> {
}; };
// Build up the import directives. // Build up the import directives.
let is_prelude = item.attrs.iter().any(|attr| attr.name() == "prelude_import"); let is_prelude = attr::contains_name(&item.attrs, "prelude_import");
match view_path.node { match view_path.node {
ViewPathSimple(binding, ref full_path) => { ViewPathSimple(binding, ref full_path) => {
@ -221,6 +224,10 @@ impl<'b> Resolver<'b> {
let parent_link = ModuleParentLink(parent, name); let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(self.definitions.local_def_id(item.id)); let def = Def::Mod(self.definitions.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false); let module = self.new_module(parent_link, Some(def), false);
module.no_implicit_prelude.set({
parent.no_implicit_prelude.get() ||
attr::contains_name(&item.attrs, "no_implicit_prelude")
});
self.define(parent, name, TypeNS, (module, sp, vis)); self.define(parent, name, TypeNS, (module, sp, vis));
self.module_map.insert(item.id, module); self.module_map.insert(item.id, module);
*parent_ref = module; *parent_ref = module;

View file

@ -788,7 +788,7 @@ pub struct ModuleS<'a> {
resolutions: RefCell<HashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>, resolutions: RefCell<HashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
unresolved_imports: RefCell<Vec<&'a ImportDirective<'a>>>, unresolved_imports: RefCell<Vec<&'a ImportDirective<'a>>>,
prelude: RefCell<Option<Module<'a>>>, no_implicit_prelude: Cell<bool>,
glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective<'a>)>>, glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective<'a>)>>,
globs: RefCell<Vec<&'a ImportDirective<'a>>>, globs: RefCell<Vec<&'a ImportDirective<'a>>>,
@ -817,7 +817,7 @@ impl<'a> ModuleS<'a> {
extern_crate_id: None, extern_crate_id: None,
resolutions: RefCell::new(HashMap::new()), resolutions: RefCell::new(HashMap::new()),
unresolved_imports: RefCell::new(Vec::new()), unresolved_imports: RefCell::new(Vec::new()),
prelude: RefCell::new(None), no_implicit_prelude: Cell::new(false),
glob_importers: RefCell::new(Vec::new()), glob_importers: RefCell::new(Vec::new()),
globs: RefCell::new((Vec::new())), globs: RefCell::new((Vec::new())),
traits: RefCell::new(None), traits: RefCell::new(None),
@ -981,6 +981,8 @@ pub struct Resolver<'a> {
graph_root: Module<'a>, graph_root: Module<'a>,
prelude: Option<Module<'a>>,
trait_item_map: FnvHashMap<(Name, DefId), bool /* is static method? */>, trait_item_map: FnvHashMap<(Name, DefId), bool /* is static method? */>,
structs: FnvHashMap<DefId, Vec<Name>>, structs: FnvHashMap<DefId, Vec<Name>>,
@ -1170,6 +1172,7 @@ impl<'a> Resolver<'a> {
// The outermost module has def ID 0; this is not reflected in the // The outermost module has def ID 0; this is not reflected in the
// AST. // AST.
graph_root: graph_root, graph_root: graph_root,
prelude: None,
trait_item_map: FnvHashMap(), trait_item_map: FnvHashMap(),
structs: FnvHashMap(), structs: FnvHashMap(),
@ -1453,10 +1456,13 @@ impl<'a> Resolver<'a> {
// We can only see through anonymous modules // We can only see through anonymous modules
if module.def.is_some() { if module.def.is_some() {
return module.prelude.borrow().and_then(|module| { return match self.prelude {
module.resolve_name(name, ns, false) Some(prelude) if !module.no_implicit_prelude.get() => {
.success().map(LexicalScopeBinding::Item) prelude.resolve_name(name, ns, false).success()
}); .map(LexicalScopeBinding::Item)
}
_ => None,
};
} }
} }
} }
@ -3261,7 +3267,7 @@ impl<'a> Resolver<'a> {
let mut search_module = self.current_module; let mut search_module = self.current_module;
loop { loop {
// Look for trait children. // Look for trait children.
let mut search_in_module = |module: Module<'a>| { let mut search_in_module = |this: &mut Self, module: Module<'a>| {
let mut traits = module.traits.borrow_mut(); let mut traits = module.traits.borrow_mut();
if traits.is_none() { if traits.is_none() {
let mut collected_traits = Vec::new(); let mut collected_traits = Vec::new();
@ -3276,23 +3282,25 @@ impl<'a> Resolver<'a> {
for &(trait_name, binding) in traits.as_ref().unwrap().iter() { for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
let trait_def_id = binding.def().unwrap().def_id(); let trait_def_id = binding.def().unwrap().def_id();
if self.trait_item_map.contains_key(&(name, trait_def_id)) { if this.trait_item_map.contains_key(&(name, trait_def_id)) {
let mut import_id = None; let mut import_id = None;
if let NameBindingKind::Import { directive, .. } = binding.kind { if let NameBindingKind::Import { directive, .. } = binding.kind {
let id = directive.id; let id = directive.id;
self.maybe_unused_trait_imports.insert(id); this.maybe_unused_trait_imports.insert(id);
import_id = Some(id); import_id = Some(id);
} }
add_trait_info(&mut found_traits, trait_def_id, import_id, name); add_trait_info(&mut found_traits, trait_def_id, import_id, name);
self.record_use(trait_name, binding); this.record_use(trait_name, binding);
} }
} }
}; };
search_in_module(search_module); search_in_module(self, search_module);
match search_module.parent_link { match search_module.parent_link {
NoParentLink | ModuleParentLink(..) => { NoParentLink | ModuleParentLink(..) => {
search_module.prelude.borrow().map(search_in_module); if !search_module.no_implicit_prelude.get() {
self.prelude.map(|prelude| search_in_module(self, prelude));
}
break; break;
} }
BlockParentLink(parent_module, _) => { BlockParentLink(parent_module, _) => {

View file

@ -624,7 +624,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
self.resolver.populate_module_if_necessary(target_module); self.resolver.populate_module_if_necessary(target_module);
if let GlobImport { is_prelude: true } = directive.subclass { if let GlobImport { is_prelude: true } = directive.subclass {
*module_.prelude.borrow_mut() = Some(target_module); self.resolver.prelude = Some(target_module);
return Success(()); return Success(());
} }

View file

@ -12,12 +12,9 @@ use ast;
use attr; use attr;
use codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute}; use codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
use codemap; use codemap;
use fold::Folder;
use fold;
use parse::token::{intern, InternedString, keywords}; use parse::token::{intern, InternedString, keywords};
use parse::{token, ParseSess}; use parse::{token, ParseSess};
use ptr::P; use ptr::P;
use util::small_vector::SmallVector;
/// Craft a span that will be ignored by the stability lint's /// Craft a span that will be ignored by the stability lint's
/// call to codemap's is_internal check. /// call to codemap's is_internal check.
@ -37,33 +34,6 @@ fn ignored_span(sess: &ParseSess, sp: Span) -> Span {
return sp; return sp;
} }
pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option<String>)
-> ast::Crate {
if no_core(&krate) {
krate
} else {
let name = if no_std(&krate) {"core"} else {"std"};
let mut fold = CrateInjector {
item_name: token::str_to_ident(name),
crate_name: token::intern(&alt_std_name.unwrap_or(name.to_string())),
};
fold.fold_crate(krate)
}
}
pub fn maybe_inject_prelude(sess: &ParseSess, krate: ast::Crate) -> ast::Crate {
if no_core(&krate) {
krate
} else {
let name = if no_std(&krate) {"core"} else {"std"};
let mut fold = PreludeInjector {
span: ignored_span(sess, DUMMY_SP),
crate_identifier: token::str_to_ident(name),
};
fold.fold_crate(krate)
}
}
pub fn no_core(krate: &ast::Crate) -> bool { pub fn no_core(krate: &ast::Crate) -> bool {
attr::contains_name(&krate.attrs, "no_core") attr::contains_name(&krate.attrs, "no_core")
} }
@ -72,102 +42,54 @@ pub fn no_std(krate: &ast::Crate) -> bool {
attr::contains_name(&krate.attrs, "no_std") || no_core(krate) attr::contains_name(&krate.attrs, "no_std") || no_core(krate)
} }
fn no_prelude(attrs: &[ast::Attribute]) -> bool { pub fn maybe_inject_crates_ref(sess: &ParseSess,
attr::contains_name(attrs, "no_implicit_prelude") mut krate: ast::Crate,
} alt_std_name: Option<String>)
-> ast::Crate {
struct CrateInjector { if no_core(&krate) {
item_name: ast::Ident, return krate;
crate_name: ast::Name,
}
impl fold::Folder for CrateInjector {
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
krate.module.items.insert(0, P(ast::Item {
id: ast::DUMMY_NODE_ID,
ident: self.item_name,
attrs: vec!(
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item(
InternedString::new("macro_use")))),
node: ast::ItemKind::ExternCrate(Some(self.crate_name)),
vis: ast::Visibility::Inherited,
span: DUMMY_SP
}));
krate
}
}
struct PreludeInjector {
span: Span,
crate_identifier: ast::Ident,
}
impl fold::Folder for PreludeInjector {
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
// only add `use std::prelude::*;` if there wasn't a
// `#![no_implicit_prelude]` at the crate level.
// fold_mod() will insert glob path.
if !no_prelude(&krate.attrs) {
krate.module = self.fold_mod(krate.module);
}
krate
} }
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> { let name = if no_std(&krate) { "core" } else { "std" };
if !no_prelude(&item.attrs) { let crate_name = token::intern(&alt_std_name.unwrap_or(name.to_string()));
// only recur if there wasn't `#![no_implicit_prelude]`
// on this item, i.e. this means that the prelude is not
// implicitly imported though the whole subtree
fold::noop_fold_item(item, self)
} else {
SmallVector::one(item)
}
}
fn fold_mod(&mut self, mut mod_: ast::Mod) -> ast::Mod { krate.module.items.insert(0, P(ast::Item {
let prelude_path = ast::Path { attrs: vec![attr::mk_attr_outer(attr::mk_attr_id(),
span: self.span, attr::mk_word_item(InternedString::new("macro_use")))],
vis: ast::Visibility::Inherited,
node: ast::ItemKind::ExternCrate(Some(crate_name)),
ident: token::str_to_ident(name),
id: ast::DUMMY_NODE_ID,
span: DUMMY_SP,
}));
let span = ignored_span(sess, DUMMY_SP);
krate.module.items.insert(0, P(ast::Item {
attrs: vec![ast::Attribute {
node: ast::Attribute_ {
style: ast::AttrStyle::Outer,
value: P(ast::MetaItem {
node: ast::MetaItemKind::Word(token::intern_and_get_ident("prelude_import")),
span: span,
}),
id: attr::mk_attr_id(),
is_sugared_doc: false,
},
span: span,
}],
vis: ast::Visibility::Inherited,
node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
global: false, global: false,
segments: vec![ segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment {
ast::PathSegment { identifier: token::str_to_ident(name),
identifier: self.crate_identifier, parameters: ast::PathParameters::none(),
parameters: ast::PathParameters::none(), }).collect(),
}, span: span,
ast::PathSegment { })))),
identifier: token::str_to_ident("prelude"), id: ast::DUMMY_NODE_ID,
parameters: ast::PathParameters::none(), ident: keywords::Invalid.ident(),
}, span: span,
ast::PathSegment { }));
identifier: token::str_to_ident("v1"),
parameters: ast::PathParameters::none(),
},
],
};
let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path))); krate
mod_.items.insert(0, P(ast::Item {
id: ast::DUMMY_NODE_ID,
ident: keywords::Invalid.ident(),
node: ast::ItemKind::Use(vp),
attrs: vec![ast::Attribute {
span: self.span,
node: ast::Attribute_ {
id: attr::mk_attr_id(),
style: ast::AttrStyle::Outer,
value: P(ast::MetaItem {
span: self.span,
node: ast::MetaItemKind::Word(
token::intern_and_get_ident("prelude_import")
),
}),
is_sugared_doc: false,
},
}],
vis: ast::Visibility::Inherited,
span: self.span,
}));
fold::noop_fold_mod(mod_, self)
}
} }