From: Eduard-Mihai Burtescu Date: Thu, 13 Sep 2018 17:47:47 +0000 (+0300) Subject: rustc_resolve: only process uniform_paths canaries in namespaces they're present in. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=439423834713e7d10d688ef912747e3e9a2fecd2;p=rust.git rustc_resolve: only process uniform_paths canaries in namespaces they're present in. --- diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index dfbea0ffe22..7ee19d0f318 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -630,15 +630,16 @@ pub fn finalize_imports(&mut self) { self.finalize_resolutions_in(module); } - #[derive(Default)] - struct UniformPathsCanaryResult<'a> { + struct UniformPathsCanaryResults<'a> { + name: Name, module_scope: Option<&'a NameBinding<'a>>, block_scopes: Vec<&'a NameBinding<'a>>, } + // Collect all tripped `uniform_paths` canaries separately. let mut uniform_paths_canaries: BTreeMap< - (Span, NodeId), - (Name, PerNS), + (Span, NodeId, Namespace), + UniformPathsCanaryResults, > = BTreeMap::new(); let mut errors = false; @@ -665,21 +666,25 @@ struct UniformPathsCanaryResult<'a> { import.module_path.len() > 0 && import.module_path[0].name == keywords::SelfValue.name(); - let (prev_name, canary_results) = - uniform_paths_canaries.entry((import.span, import.id)) - .or_insert((name, PerNS::default())); - - // All the canaries with the same `id` should have the same `name`. - assert_eq!(*prev_name, name); - self.per_ns(|_, ns| { if let Some(result) = result[ns].get().ok() { + let canary_results = + uniform_paths_canaries.entry((import.span, import.id, ns)) + .or_insert(UniformPathsCanaryResults { + name, + module_scope: None, + block_scopes: vec![], + }); + + // All the canaries with the same `id` should have the same `name`. + assert_eq!(canary_results.name, name); + if has_explicit_self { // There should only be one `self::x` (module-scoped) canary. - assert!(canary_results[ns].module_scope.is_none()); - canary_results[ns].module_scope = Some(result); + assert!(canary_results.module_scope.is_none()); + canary_results.module_scope = Some(result); } else { - canary_results[ns].block_scopes.push(result); + canary_results.block_scopes.push(result); } } }); @@ -720,77 +725,76 @@ struct UniformPathsCanaryResult<'a> { } let uniform_paths_feature = self.session.features_untracked().uniform_paths; - for ((span, _), (name, results)) in uniform_paths_canaries { - self.per_ns(|this, ns| { - let external_crate = if ns == TypeNS && this.extern_prelude.contains(&name) { - let crate_id = - this.crate_loader.process_path_extern(name, span); - Some(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) - } else { - None - }; - let result_filter = |result: &&NameBinding| { - // Ignore canaries that resolve to an import of the same crate. - // That is, we allow `use crate_name; use crate_name::foo;`. - if let Some(def_id) = external_crate { - if let Some(module) = result.module() { - if module.normal_ancestor_id == def_id { - return false; - } + for ((span, _, ns), results) in uniform_paths_canaries { + let name = results.name; + let external_crate = if ns == TypeNS && self.extern_prelude.contains(&name) { + let crate_id = + self.crate_loader.process_path_extern(name, span); + Some(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) + } else { + None + }; + + let result_filter = |result: &&NameBinding| { + // Ignore canaries that resolve to an import of the same crate. + // That is, we allow `use crate_name; use crate_name::foo;`. + if let Some(def_id) = external_crate { + if let Some(module) = result.module() { + if module.normal_ancestor_id == def_id { + return false; } } + } - true - }; - let module_scope = results[ns].module_scope.filter(result_filter); - let block_scopes = || { - results[ns].block_scopes.iter().cloned().filter(result_filter) - }; + true + }; + let module_scope = results.module_scope.filter(result_filter); + let block_scopes = || { + results.block_scopes.iter().cloned().filter(result_filter) + }; - // An ambiguity requires more than one possible resolution. - let possible_resultions = - (external_crate.is_some() as usize) + - (module_scope.is_some() as usize) + - (block_scopes().next().is_some() as usize); - if possible_resultions <= 1 { - return; - } + // An ambiguity requires more than one possible resolution. + let possible_resultions = + (external_crate.is_some() as usize) + + module_scope.into_iter().chain(block_scopes()).count(); + if possible_resultions <= 1 { + return; + } - errors = true; + errors = true; - let msg = format!("`{}` import is ambiguous", name); - let mut err = this.session.struct_span_err(span, &msg); - let mut suggestion_choices = String::new(); - if external_crate.is_some() { - write!(suggestion_choices, "`::{}`", name); - err.span_label(span, - format!("can refer to external crate `::{}`", name)); - } - if let Some(result) = module_scope { - if !suggestion_choices.is_empty() { - suggestion_choices.push_str(" or "); - } - write!(suggestion_choices, "`self::{}`", name); - if uniform_paths_feature { - err.span_label(result.span, - format!("can refer to `self::{}`", name)); - } else { - err.span_label(result.span, - format!("may refer to `self::{}` in the future", name)); - } - } - for result in block_scopes() { - err.span_label(result.span, - format!("shadowed by block-scoped `{}`", name)); + let msg = format!("`{}` import is ambiguous", name); + let mut err = self.session.struct_span_err(span, &msg); + let mut suggestion_choices = String::new(); + if external_crate.is_some() { + write!(suggestion_choices, "`::{}`", name); + err.span_label(span, + format!("can refer to external crate `::{}`", name)); + } + if let Some(result) = module_scope { + if !suggestion_choices.is_empty() { + suggestion_choices.push_str(" or "); } - err.help(&format!("write {} explicitly instead", suggestion_choices)); + write!(suggestion_choices, "`self::{}`", name); if uniform_paths_feature { - err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`"); + err.span_label(result.span, + format!("can refer to `self::{}`", name)); } else { - err.note("in the future, `#![feature(uniform_paths)]` may become the default"); + err.span_label(result.span, + format!("may refer to `self::{}` in the future", name)); } - err.emit(); - }); + } + for result in block_scopes() { + err.span_label(result.span, + format!("shadowed by block-scoped `{}`", name)); + } + err.help(&format!("write {} explicitly instead", suggestion_choices)); + if uniform_paths_feature { + err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`"); + } else { + err.note("in the future, `#![feature(uniform_paths)]` may become the default"); + } + err.emit(); } if !error_vec.is_empty() {