diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 386496b071d..3ef4d7034de 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -601,7 +601,8 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, })?; 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 mut addl_plugins = Some(addl_plugins); @@ -729,10 +730,6 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, sess.diagnostic()) }); - krate = time(time_passes, - "prelude injection", - || syntax::std_inject::maybe_inject_prelude(&sess.parse_sess, krate)); - time(time_passes, "checking for inline asm in case the target doesn't support it", || no_asm::check_crate(sess, &krate)); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index c7b113689fd..775c24b6d4a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -27,7 +27,7 @@ use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::ty::{self, VariantKind}; use syntax::ast::Name; -use syntax::attr::AttrMetaMethods; +use syntax::attr; use syntax::parse::token; use syntax::codemap::{Span, DUMMY_SP}; @@ -57,6 +57,9 @@ impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) { impl<'b> Resolver<'b> { /// Constructs the reduced graph for the entire 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 { parent: self.graph_root, resolver: self, @@ -128,7 +131,7 @@ impl<'b> Resolver<'b> { }; // 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 { ViewPathSimple(binding, ref full_path) => { @@ -221,6 +224,10 @@ impl<'b> Resolver<'b> { let parent_link = ModuleParentLink(parent, name); let def = Def::Mod(self.definitions.local_def_id(item.id)); 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.module_map.insert(item.id, module); *parent_ref = module; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 4941f867f06..0fab12c230c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -126,7 +126,7 @@ enum ResolutionError<'a> { /// error E0413: cannot be named the same as an enum variant or unit-like struct in scope DeclarationShadowsEnumVariantOrUnitLikeStruct(Name), /// error E0414: only irrefutable patterns allowed here - ConstantForIrrefutableBinding(Name), + ConstantForIrrefutableBinding(Name, &'a NameBinding<'a>), /// error E0415: identifier is bound more than once in this parameter list IdentifierBoundMoreThanOnceInParameterList(&'a str), /// error E0416: identifier is bound more than once in the same pattern @@ -317,19 +317,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, &format!("has same name as enum variant or unit-like struct")); err } - ResolutionError::ConstantForIrrefutableBinding(name) => { + ResolutionError::ConstantForIrrefutableBinding(name, binding) => { let mut err = struct_span_err!(resolver.session, span, E0414, "let variables cannot be named the same as const variables"); err.span_label(span, &format!("cannot be named the same as a const variable")); - if let Some(binding) = resolver.current_module - .resolve_name_in_lexical_scope(name, ValueNS) { - let participle = if binding.is_import() { "imported" } else { "defined" }; - err.span_label(binding.span, &format!("a constant `{}` is {} here", - name, participle)); - } + let participle = if binding.is_import() { "imported" } else { "defined" }; + err.span_label(binding.span, &format!("a constant `{}` is {} here", name, participle)); err } ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => { @@ -714,9 +710,9 @@ enum AssocItemResolveResult { } #[derive(Copy, Clone)] -enum BareIdentifierPatternResolution { +enum BareIdentifierPatternResolution<'a> { FoundStructOrEnumVariant(Def), - FoundConst(Def, Name), + FoundConst(&'a NameBinding<'a>, Name), BareIdentifierPatternUnresolved, } @@ -792,7 +788,7 @@ pub struct ModuleS<'a> { resolutions: RefCell>>>, unresolved_imports: RefCell>>, - prelude: RefCell>>, + no_implicit_prelude: Cell, glob_importers: RefCell, &'a ImportDirective<'a>)>>, globs: RefCell>>, @@ -821,7 +817,7 @@ impl<'a> ModuleS<'a> { extern_crate_id: None, resolutions: RefCell::new(HashMap::new()), unresolved_imports: RefCell::new(Vec::new()), - prelude: RefCell::new(None), + no_implicit_prelude: Cell::new(false), glob_importers: RefCell::new(Vec::new()), globs: RefCell::new((Vec::new())), traits: RefCell::new(None), @@ -985,6 +981,8 @@ pub struct Resolver<'a> { graph_root: Module<'a>, + prelude: Option>, + trait_item_map: FnvHashMap<(Name, DefId), bool /* is static method? */>, structs: FnvHashMap>, @@ -1174,6 +1172,7 @@ impl<'a> Resolver<'a> { // The outermost module has def ID 0; this is not reflected in the // AST. graph_root: graph_root, + prelude: None, trait_item_map: FnvHashMap(), structs: FnvHashMap(), @@ -1456,7 +1455,15 @@ impl<'a> Resolver<'a> { } // We can only see through anonymous modules - if module.def.is_some() { return None; } + if module.def.is_some() { + return match self.prelude { + Some(prelude) if !module.no_implicit_prelude.get() => { + prelude.resolve_name(name, ns, false).success() + .map(LexicalScopeBinding::Item) + } + _ => None, + }; + } } } @@ -1543,11 +1550,7 @@ impl<'a> Resolver<'a> { debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(module)); self.populate_module_if_necessary(module); - match use_lexical_scope { - true => module.resolve_name_in_lexical_scope(name, namespace) - .map(Success).unwrap_or(Failed(None)), - false => module.resolve_name(name, namespace, false), - }.and_then(|binding| { + module.resolve_name(name, namespace, use_lexical_scope).and_then(|binding| { if record_used { if let NameBindingKind::Import { directive, .. } = binding.kind { self.used_imports.insert((directive.id, namespace)); @@ -2289,21 +2292,21 @@ impl<'a> Resolver<'a> { ); self.record_def(pattern.id, err_path_resolution()); } - FoundConst(def, _) if const_ok => { + FoundConst(binding, _) if const_ok => { debug!("(resolving pattern) resolving `{}` to constant", renamed); self.enforce_default_binding_mode(pattern, binding_mode, "a constant"); self.record_def(pattern.id, PathResolution { - base_def: def, + base_def: binding.def().unwrap(), depth: 0, }); } - FoundConst(_, name) => { + FoundConst(binding, name) => { resolve_error( self, pattern.span, - ResolutionError::ConstantForIrrefutableBinding(name) + ResolutionError::ConstantForIrrefutableBinding(name, binding) ); self.record_def(pattern.id, err_path_resolution()); } @@ -2526,7 +2529,7 @@ impl<'a> Resolver<'a> { } fn resolve_bare_identifier_pattern(&mut self, ident: ast::Ident, span: Span) - -> BareIdentifierPatternResolution { + -> BareIdentifierPatternResolution<'a> { let binding = match self.resolve_ident_in_lexical_scope(ident, ValueNS, true) { Some(LexicalScopeBinding::Item(binding)) => binding, _ => return BareIdentifierPatternUnresolved, @@ -2535,7 +2538,7 @@ impl<'a> Resolver<'a> { match def { Def::Variant(..) | Def::Struct(..) => FoundStructOrEnumVariant(def), - Def::Const(..) | Def::AssociatedConst(..) => FoundConst(def, ident.name), + Def::Const(..) | Def::AssociatedConst(..) => FoundConst(binding, ident.name), Def::Static(..) => { let error = ResolutionError::StaticVariableReference(binding); resolve_error(self, span, error); @@ -3264,7 +3267,7 @@ impl<'a> Resolver<'a> { let mut search_module = self.current_module; loop { // 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(); if traits.is_none() { let mut collected_traits = Vec::new(); @@ -3279,23 +3282,25 @@ impl<'a> Resolver<'a> { for &(trait_name, binding) in traits.as_ref().unwrap().iter() { 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; if let NameBindingKind::Import { directive, .. } = binding.kind { let id = directive.id; - self.maybe_unused_trait_imports.insert(id); + this.maybe_unused_trait_imports.insert(id); import_id = Some(id); } 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 { 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; } BlockParentLink(parent_module, _) => { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9bd16117f9a..629b687d8f7 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -257,15 +257,6 @@ impl<'a> ::ModuleS<'a> { Failed(None) } - // Invariant: this may not be called until import resolution is complete. - pub fn resolve_name_in_lexical_scope(&self, name: Name, ns: Namespace) - -> Option<&'a NameBinding<'a>> { - self.resolution(name, ns).borrow().binding - .or_else(|| self.prelude.borrow().and_then(|prelude| { - prelude.resolve_name(name, ns, false).success() - })) - } - // Define the name or return the existing binding if there is a collision. pub fn try_define_child(&self, name: Name, ns: Namespace, binding: NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> { @@ -633,7 +624,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { self.resolver.populate_module_if_necessary(target_module); if let GlobImport { is_prelude: true } = directive.subclass { - *module_.prelude.borrow_mut() = Some(target_module); + self.resolver.prelude = Some(target_module); return Success(()); } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 34f56c95ecf..dc1ef5d94a4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1820,7 +1820,10 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, } } - write!(w, "") + if curty.is_some() { + write!(w, "")?; + } + Ok(()) } fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 84a7b144848..8834c026067 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -12,12 +12,9 @@ use ast; use attr; use codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute}; use codemap; -use fold::Folder; -use fold; use parse::token::{intern, InternedString, keywords}; use parse::{token, ParseSess}; use ptr::P; -use util::small_vector::SmallVector; /// Craft a span that will be ignored by the stability lint's /// call to codemap's is_internal check. @@ -37,33 +34,6 @@ fn ignored_span(sess: &ParseSess, sp: Span) -> Span { return sp; } -pub fn maybe_inject_crates_ref(krate: ast::Crate, alt_std_name: Option) - -> 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 { 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) } -fn no_prelude(attrs: &[ast::Attribute]) -> bool { - attr::contains_name(attrs, "no_implicit_prelude") -} - -struct CrateInjector { - item_name: ast::Ident, - 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 +pub fn maybe_inject_crates_ref(sess: &ParseSess, + mut krate: ast::Crate, + alt_std_name: Option) + -> ast::Crate { + if no_core(&krate) { + return krate; } - fn fold_item(&mut self, item: P) -> SmallVector> { - if !no_prelude(&item.attrs) { - // 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) - } - } + let name = if no_std(&krate) { "core" } else { "std" }; + let crate_name = token::intern(&alt_std_name.unwrap_or(name.to_string())); - fn fold_mod(&mut self, mut mod_: ast::Mod) -> ast::Mod { - let prelude_path = ast::Path { - span: self.span, + krate.module.items.insert(0, P(ast::Item { + attrs: vec![attr::mk_attr_outer(attr::mk_attr_id(), + 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, - segments: vec![ - ast::PathSegment { - identifier: self.crate_identifier, - parameters: ast::PathParameters::none(), - }, - ast::PathSegment { - identifier: token::str_to_ident("prelude"), - parameters: ast::PathParameters::none(), - }, - ast::PathSegment { - identifier: token::str_to_ident("v1"), - parameters: ast::PathParameters::none(), - }, - ], - }; + segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment { + identifier: token::str_to_ident(name), + parameters: ast::PathParameters::none(), + }).collect(), + span: span, + })))), + id: ast::DUMMY_NODE_ID, + ident: keywords::Invalid.ident(), + span: span, + })); - let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path))); - 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) - } + krate }