diff options
| -rw-r--r-- | src/librustc_resolve/lib.rs | 56 | ||||
| -rw-r--r-- | src/librustc_resolve/resolve_imports.rs | 114 |
2 files changed, 75 insertions, 95 deletions
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 3fcf14bbbcd..b2f60ddb8da 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -92,8 +92,7 @@ use std::cell::{Cell, RefCell}; use std::fmt; use std::mem::replace; -use resolve_imports::{Target, ImportDirective, ImportResolution}; -use resolve_imports::Shadowable; +use resolve_imports::{ImportDirective, ImportResolution}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. @@ -951,6 +950,7 @@ bitflags! { // Variants are considered `PUBLIC`, but some of them live in private enums. // We need to track them to prohibit reexports like `pub use PrivEnum::Variant`. const PRIVATE_VARIANT = 1 << 2, + const PRELUDE = 1 << 3, } } @@ -1291,10 +1291,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { name); return Indeterminate; } - Success((target, used_proxy)) => { + Success((binding, used_proxy)) => { // Check to see whether there are type bindings, and, if // so, whether there is a module within. - if let Some(module_def) = target.binding.module() { + if let Some(module_def) = binding.module() { search_module = module_def; // Keep track of the closest private module used @@ -1390,7 +1390,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving module path for import) indeterminate; bailing"); return Indeterminate; } - Success((target, _)) => match target.binding.module() { + Success((binding, _)) => match binding.module() { Some(containing_module) => { search_module = containing_module; start_index = 1; @@ -1424,7 +1424,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { name: Name, namespace: Namespace, record_used: bool) - -> ResolveResult<(Target<'a>, bool)> { + -> ResolveResult<(NameBinding<'a>, bool)> { debug!("(resolving item in lexical scope) resolving `{}` in namespace {:?} in `{}`", name, namespace, @@ -1446,10 +1446,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving item in lexical scope) indeterminate higher scope; bailing"); return Indeterminate; } - Success((target, used_reexport)) => { + Success((binding, used_reexport)) => { // We found the module. debug!("(resolving item in lexical scope) found name in module, done"); - return Success((target, used_reexport)); + return Success((binding, used_reexport)); } } @@ -1543,7 +1543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } /// Attempts to resolve the supplied name in the given module for the - /// given namespace. If successful, returns the target corresponding to + /// given namespace. If successful, returns the binding corresponding to /// the name. /// /// The boolean returned on success is an indicator of whether this lookup @@ -1554,7 +1554,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { namespace: Namespace, allow_private_imports: bool, record_used: bool) - -> ResolveResult<(Target<'a>, bool)> { + -> ResolveResult<(NameBinding<'a>, bool)> { debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(&*module_)); @@ -1570,7 +1570,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.used_crates.insert(krate); } } - return Success((Target::new(module_, binding, Shadowable::Never), false)); + return Success((binding, false)); } // Check the list of resolved imports. @@ -1580,12 +1580,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving name in module) import unresolved; bailing out"); return Indeterminate; } - if let Some(target) = import_resolution.target.clone() { + if let Some(binding) = import_resolution.binding.clone() { debug!("(resolving name in module) resolved to import"); if record_used { self.record_import_use(name, namespace, &import_resolution); } - return Success((target, true)); + return Success((binding, true)); } } Some(..) | None => {} // Continue. @@ -2616,11 +2616,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { -> BareIdentifierPatternResolution { let module = self.current_module; match self.resolve_item_in_lexical_scope(module, name, ValueNS, true) { - Success((target, _)) => { + Success((binding, _)) => { debug!("(resolve bare identifier pattern) succeeded in finding {} at {:?}", name, - &target.binding); - match target.binding.def() { + &binding); + match binding.def() { None => { panic!("resolved name in the value namespace to a set of name bindings \ with no def?!"); @@ -2776,7 +2776,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let module = self.current_module; let name = identifier.unhygienic_name; match self.resolve_item_in_lexical_scope(module, name, namespace, record_used) { - Success((target, _)) => target.binding.def().map(LocalDef::from_def), + Success((binding, _)) => binding.def().map(LocalDef::from_def), Failed(Some((span, msg))) => { resolve_error(self, span, ResolutionError::FailedToResolve(&*msg)); None @@ -2914,7 +2914,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let name = segments.last().unwrap().identifier.name; let result = self.resolve_name_in_module(containing_module, name, namespace, false, true); let def = match result { - Success((Target { binding, .. }, _)) => { + Success((binding, _)) => { let (def, lp) = binding.def_and_lp(); (def, last_private.or(lp)) } @@ -2970,7 +2970,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let name = segments.last().unwrap().identifier.name; match self.resolve_name_in_module(containing_module, name, namespace, false, true) { - Success((Target { binding, .. }, _)) => { + Success((binding, _)) => { let (def, lp) = binding.def_and_lp(); Some((def, last_private.or(lp))) } @@ -3008,12 +3008,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let AnonymousModuleRibKind(module) = self.get_ribs(namespace)[i].kind { - if let Success((target, _)) = self.resolve_name_in_module(module, - ident.unhygienic_name, - namespace, - true, - true) { - if let Some(def) = target.binding.def() { + if let Success((binding, _)) = self.resolve_name_in_module(module, + ident.unhygienic_name, + namespace, + true, + true) { + if let Some(def) = binding.def() { return Some(LocalDef::from_def(def)); } } @@ -3455,11 +3455,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Look for imports. for (&(_, ns), import) in search_module.import_resolutions.borrow().iter() { if ns != TypeNS { continue } - let target = match import.target { - Some(ref target) => target, + let binding = match import.binding { + Some(ref binding) => binding, None => continue, }; - let did = match target.binding.def() { + let did = match binding.def() { Some(Def::Trait(trait_def_id)) => trait_def_id, Some(..) | None => continue, }; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 3d2300e44c4..882531efbb7 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -78,24 +78,14 @@ impl ImportDirective { shadowable: shadowable, } } -} - -/// The item that an import resolves to. -#[derive(Clone,Debug)] -pub struct Target<'a> { - pub target_module: Module<'a>, - pub binding: NameBinding<'a>, - pub shadowable: Shadowable, -} -impl<'a> Target<'a> { - pub fn new(target_module: Module<'a>, binding: NameBinding<'a>, shadowable: Shadowable) - -> Self { - Target { - target_module: target_module, - binding: binding, - shadowable: shadowable, + // Given the binding to which this directive resolves in a particular namespace, + // this returns the binding for the name this directive defines in that namespace. + fn import<'a>(&self, mut binding: NameBinding<'a>) -> NameBinding<'a> { + if self.shadowable == Shadowable::Always { + binding.modifiers = binding.modifiers | DefModifiers::PRELUDE; } + binding } } @@ -117,7 +107,7 @@ pub struct ImportResolution<'a> { pub is_public: bool, /// Resolution of the name in the namespace - pub target: Option<Target<'a>>, + pub binding: Option<NameBinding<'a>>, /// The source node of the `use` directive pub id: NodeId, @@ -128,14 +118,16 @@ impl<'a> ImportResolution<'a> { ImportResolution { outstanding_references: 0, id: id, - target: None, + binding: None, is_public: is_public, } } pub fn shadowable(&self) -> Shadowable { - match self.target { - Some(ref target) => target.shadowable, + match self.binding { + Some(ref binding) if binding.defined_with(DefModifiers::PRELUDE) => + Shadowable::Always, + Some(_) => Shadowable::Never, None => Shadowable::Always, } } @@ -217,23 +209,17 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { e.import_directive.is_public) }); - if resolution.target.is_none() { + if resolution.binding.is_none() { debug!("(resolving import error) adding fake target to import resolution of `{}`", target); - let name_binding = NameBinding { + let dummy_binding = NameBinding { modifiers: DefModifiers::IMPORTABLE, def_or_module: DefOrModule::Def(Def::Err), span: None, }; - // Create a fake target pointing to a fake name binding in our - // own module - let target = Target::new(e.source_module, - name_binding, - Shadowable::Always); - - resolution.target = Some(target); + resolution.binding = Some(dummy_binding); } } @@ -374,14 +360,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { } /// Resolves the name in the namespace of the module because it is being imported by - /// importing_module. Returns the module in which the name was defined (as opposed to imported), - /// the name bindings defining the name, and whether or not the name was imported into `module`. + /// importing_module. Returns the name bindings defining the name + /// and whether or not the name was imported. fn resolve_name_in_module(&mut self, module: Module<'b>, // Module containing the name name: Name, ns: Namespace, importing_module: Module<'b>) // Module importing the name - -> (ResolveResult<(Module<'b>, NameBinding<'b>)>, bool) { + -> (ResolveResult<NameBinding<'b>>, bool) { build_reduced_graph::populate_module_if_necessary(self.resolver, module); if let Some(name_binding) = module.get_child(name, ns) { if name_binding.is_extern_crate() { @@ -390,7 +376,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { self.resolver.used_crates.insert(krate); } } - return (Success((module, name_binding)), false) + return (Success(name_binding), false) } // If there is an unresolved glob at this point in the containing module, bail out. @@ -411,10 +397,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { return (Failed(None), false); } - let target = resolution.target.clone(); - if let Some(Target { target_module, binding, shadowable: _ }) = target { + if let Some(binding) = resolution.binding.clone() { self.resolver.record_import_use(name, ns, &resolution); - (Success((target_module, binding)), true) + (Success(binding), true) } else { (Failed(None), false) } @@ -470,9 +455,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { self.resolve_name_in_module(target_module, source, TypeNS, module_); match (&value_result, &type_result) { - (&Success((_, ref name_binding)), _) if !value_used_reexport && - directive.is_public && - !name_binding.is_public() => { + (&Success(ref name_binding), _) if !value_used_reexport && + directive.is_public && + !name_binding.is_public() => { let msg = format!("`{}` is private, and cannot be reexported", source); let note_msg = format!("Consider marking `{}` as `pub` in the imported module", source); @@ -481,8 +466,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { .emit(); } - (_, &Success((_, ref name_binding))) if !type_used_reexport && - directive.is_public => { + (_, &Success(ref name_binding)) if !type_used_reexport && + directive.is_public => { if !name_binding.is_public() { let msg = format!("`{}` is private, and cannot be reexported", source); let note_msg = @@ -534,7 +519,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { { let mut check_and_write_import = |namespace, result, used_public: &mut bool| { - let result: &ResolveResult<(Module<'b>, NameBinding)> = result; + let result: &ResolveResult<NameBinding> = result; let import_resolution = import_resolutions.get_mut(&(target, namespace)).unwrap(); let namespace_name = match namespace { @@ -543,7 +528,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { }; match *result { - Success((ref target_module, ref name_binding)) => { + Success(ref name_binding) => { debug!("(resolving single import) found {:?} target: {:?}", namespace_name, name_binding.def()); @@ -556,9 +541,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { directive.span, target); - import_resolution.target = Some(Target::new(target_module, - name_binding.clone(), - directive.shadowable)); + import_resolution.binding = Some(directive.import(name_binding.clone())); import_resolution.id = directive.id; import_resolution.is_public = directive.is_public; @@ -600,8 +583,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { // Record what this import resolves to for later uses in documentation, // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. - import_resolution_value.target.as_ref().map(|target| { - let def = target.binding.def().unwrap(); + import_resolution_value.binding.as_ref().map(|binding| { + let def = binding.def().unwrap(); let last_private = if value_used_public { lp } else { DependsOn(def.def_id()) }; (def, last_private) }) @@ -612,8 +595,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { assert!(import_resolution_type.outstanding_references >= 1); import_resolution_type.outstanding_references -= 1; - import_resolution_type.target.as_ref().map(|target| { - let def = target.binding.def().unwrap(); + import_resolution_type.binding.as_ref().map(|binding| { + let def = binding.def().unwrap(); let last_private = if type_used_public { lp } else { DependsOn(def.def_id()) }; (def, last_private) }) @@ -695,15 +678,15 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { import_resolutions.entry((name, ns)) .or_insert_with(|| ImportResolution::new(id, is_public)); - match target_import_resolution.target { - Some(ref target) if target_import_resolution.is_public => { + match target_import_resolution.binding { + Some(ref binding) if target_import_resolution.is_public => { self.check_for_conflicting_import(&dest_import_resolution, import_directive.span, name, ns); dest_import_resolution.id = id; dest_import_resolution.is_public = is_public; - dest_import_resolution.target = Some(target.clone()); + dest_import_resolution.binding = Some(import_directive.import(binding.clone())); self.add_export(module_, name, &dest_import_resolution); } _ => {} @@ -778,10 +761,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { name); span_err!(self.resolver.session, import_directive.span, E0251, "{}", msg); } else { - let target = Target::new(containing_module, - name_binding.clone(), - import_directive.shadowable); - dest_import_resolution.target = Some(target); + dest_import_resolution.binding = Some(import_directive.import(name_binding.clone())); dest_import_resolution.id = id; dest_import_resolution.is_public = is_public; self.add_export(module_, name, &dest_import_resolution); @@ -800,7 +780,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some(def_id) => self.resolver.ast_map.as_local_node_id(def_id).unwrap(), None => return, }; - let export = match resolution.target.as_ref().unwrap().binding.def() { + let export = match resolution.binding.as_ref().unwrap().def() { Some(def) => Export { name: name, def_id: def.def_id() }, None => return, }; @@ -813,16 +793,16 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { import_span: Span, name: Name, namespace: Namespace) { - let target = &import_resolution.target; + let binding = &import_resolution.binding; debug!("check_for_conflicting_import: {}; target exists: {}", name, - target.is_some()); + binding.is_some()); - match *target { - Some(ref target) if target.shadowable != Shadowable::Always => { + match *binding { + Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => { let ns_word = match namespace { TypeNS => { - match target.binding.module() { + match binding.module() { Some(ref module) if module.is_normal() => "module", Some(ref module) if module.is_trait() => "trait", _ => "type", @@ -876,8 +856,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { }; if ns == ValueNS { - match import.target { - Some(ref target) if target.shadowable != Shadowable::Always => { + match import.binding { + Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => { let mut err = struct_span_err!(self.resolver.session, import_span, E0255, @@ -892,8 +872,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> { Some(_) | None => {} } } else { - match import.target { - Some(ref target) if target.shadowable != Shadowable::Always => { + match import.binding { + Some(ref binding) if !binding.defined_with(DefModifiers::PRELUDE) => { if name_binding.is_extern_crate() { let msg = format!("import `{0}` conflicts with imported crate \ in this module (maybe you meant `use {0}::*`?)", |
