Auto merge of #52555 - petrochenkov:mresfact, r=alexcrichton

resolve: Some renaming, refactoring and comments

Commits are self-descriptive.
The only functional change is 34bf2f572e that tightens shadowing rules for macro paths (makes the second and third cases in `test/ui/imports/glob-shadowing.rs` an error).
This commit is contained in:
bors 2018-07-21 10:30:11 +00:00
commit ef9781358d
12 changed files with 248 additions and 166 deletions

View file

@ -103,7 +103,7 @@ impl<K, V> LeafNode<K, V> {
}
fn is_shared_root(&self) -> bool {
self as *const _ == &EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V>
ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
}
}

View file

@ -39,7 +39,7 @@ use hir::intravisit;
use hir;
use lint::builtin::BuiltinLintDiagnostics;
use session::{Session, DiagnosticMessageId};
use std::hash;
use std::{hash, ptr};
use syntax::ast;
use syntax::codemap::{MultiSpan, ExpnFormat};
use syntax::edition::Edition;
@ -354,7 +354,7 @@ pub struct LintId {
impl PartialEq for LintId {
fn eq(&self, other: &LintId) -> bool {
(self.lint as *const Lint) == (other.lint as *const Lint)
ptr::eq(self.lint, other.lint)
}
}

View file

@ -47,7 +47,7 @@ use std::ops::Deref;
use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter};
use std::slice;
use std::vec::IntoIter;
use std::mem;
use std::{mem, ptr};
use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
use syntax::attr;
use syntax::ext::hygiene::Mark;
@ -527,8 +527,7 @@ impl<'tcx> PartialOrd for TyS<'tcx> {
impl<'tcx> PartialEq for TyS<'tcx> {
#[inline]
fn eq(&self, other: &TyS<'tcx>) -> bool {
// (self as *const _) == (other as *const _)
(self as *const TyS<'tcx>) == (other as *const TyS<'tcx>)
ptr::eq(self, other)
}
}
impl<'tcx> Eq for TyS<'tcx> {}
@ -678,7 +677,7 @@ impl<T> PartialOrd for Slice<T> where T: PartialOrd {
impl<T: PartialEq> PartialEq for Slice<T> {
#[inline]
fn eq(&self, other: &Slice<T>) -> bool {
(self as *const _) == (other as *const _)
ptr::eq(self, other)
}
}
impl<T: Eq> Eq for Slice<T> {}
@ -1730,7 +1729,7 @@ impl Ord for AdtDef {
impl PartialEq for AdtDef {
// AdtDef are always interned and this is part of TyS equality
#[inline]
fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ }
fn eq(&self, other: &Self) -> bool { ptr::eq(self, other) }
}
impl Eq for AdtDef {}

View file

@ -20,7 +20,7 @@ use ty::query::plumbing::CycleError;
use ty::context::TyCtxt;
use errors::Diagnostic;
use std::process;
use std::fmt;
use std::{fmt, ptr};
use std::collections::HashSet;
#[cfg(parallel_queries)]
use {
@ -124,7 +124,7 @@ impl<'tcx> QueryJob<'tcx> {
while let Some(job) = current_job {
cycle.insert(0, job.info.clone());
if &*job as *const _ == self as *const _ {
if ptr::eq(&*job, self) {
// This is the end of the cycle
// The span entry we included was for the usage
// of the cycle itself, and not part of the cycle

View file

@ -56,29 +56,30 @@ extern crate rustc_cratesio_shim;
pub use rustc_serialize::hex::ToHex;
pub mod array_vec;
pub mod accumulate_vec;
pub mod small_vec;
pub mod array_vec;
pub mod base_n;
pub mod bitslice;
pub mod bitvec;
pub mod flock;
pub mod fx;
pub mod graph;
pub mod indexed_set;
pub mod indexed_vec;
pub mod obligation_forest;
pub mod owning_ref;
pub mod ptr_key;
pub mod sip128;
pub mod small_vec;
pub mod snapshot_map;
pub use ena::snapshot_vec;
pub mod stable_hasher;
pub mod transitive_relation;
pub use ena::unify;
pub mod fx;
pub mod tuple_slice;
pub mod graph;
pub mod flock;
pub mod sync;
pub mod owning_ref;
pub mod tiny_list;
pub mod sorted_map;
pub mod stable_hasher;
pub mod sync;
pub mod tiny_list;
pub mod transitive_relation;
pub mod tuple_slice;
pub use ena::unify;
pub mod work_queue;
pub struct OnDrop<F: Fn()>(pub F);

View file

@ -0,0 +1,45 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::{hash, ptr};
use std::ops::Deref;
/// A wrapper around reference that compares and hashes like a pointer.
/// Can be used as a key in sets/maps indexed by pointers to avoid `unsafe`.
#[derive(Debug)]
pub struct PtrKey<'a, T: 'a>(pub &'a T);
impl<'a, T> Clone for PtrKey<'a, T> {
fn clone(&self) -> Self { *self }
}
impl<'a, T> Copy for PtrKey<'a, T> {}
impl<'a, T> PartialEq for PtrKey<'a, T> {
fn eq(&self, rhs: &Self) -> bool {
ptr::eq(self.0, rhs.0)
}
}
impl<'a, T> Eq for PtrKey<'a, T> {}
impl<'a, T> hash::Hash for PtrKey<'a, T> {
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
(self.0 as *const T).hash(hasher)
}
}
impl<'a, T> Deref for PtrKey<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.0
}
}

View file

@ -651,7 +651,7 @@ impl<'a> Resolver<'a> {
binding: &'a NameBinding<'a>,
span: Span,
allow_shadowing: bool) {
if self.global_macros.insert(name, binding).is_some() && !allow_shadowing {
if self.macro_prelude.insert(name, binding).is_some() && !allow_shadowing {
let msg = format!("`{}` is already in scope", name);
let note =
"macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
@ -704,8 +704,7 @@ impl<'a> Resolver<'a> {
} else {
for (name, span) in legacy_imports.imports {
let ident = Ident::with_empty_ctxt(name);
let result = self.resolve_ident_in_module(module, ident, MacroNS,
false, false, span);
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, span);
if let Ok(binding) = result {
let directive = macro_use_directive(span);
self.potentially_unused_imports.push(directive);

View file

@ -1393,7 +1393,7 @@ pub struct Resolver<'a> {
crate_loader: &'a mut dyn CrateLoader,
macro_names: FxHashSet<Ident>,
global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
pub all_macros: FxHashMap<Name, Def>,
lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
@ -1715,7 +1715,7 @@ impl<'a> Resolver<'a> {
crate_loader,
macro_names: FxHashSet(),
global_macros: FxHashMap(),
macro_prelude: FxHashMap(),
all_macros: FxHashMap(),
lexical_macro_resolutions: Vec::new(),
macro_map: FxHashMap(),
@ -2002,7 +2002,6 @@ impl<'a> Resolver<'a> {
module: Module<'a>,
mut ident: Ident,
ns: Namespace,
ignore_unresolved_invocations: bool,
record_used: bool,
span: Span)
-> Result<&'a NameBinding<'a>, Determinacy> {
@ -2012,7 +2011,7 @@ impl<'a> Resolver<'a> {
self.current_module = self.macro_def_scope(def);
}
let result = self.resolve_ident_in_module_unadjusted(
module, ident, ns, ignore_unresolved_invocations, record_used, span,
module, ident, ns, false, record_used, span,
);
self.current_module = orig_current_module;
result
@ -2518,7 +2517,7 @@ impl<'a> Resolver<'a> {
// If there is a TraitRef in scope for an impl, then the method must be in the
// trait.
if let Some((module, _)) = self.current_trait_ref {
if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() {
if self.resolve_ident_in_module(module, ident, ns, false, span).is_err() {
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
}
@ -3225,7 +3224,7 @@ impl<'a> Resolver<'a> {
};
}
}
let is_global = self.global_macros.get(&path[0].name).cloned()
let is_global = self.macro_prelude.get(&path[0].name).cloned()
.map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
if primary_ns != MacroNS && (is_global ||
self.macro_names.contains(&path[0].modern())) {
@ -3468,7 +3467,7 @@ impl<'a> Resolver<'a> {
}
let binding = if let Some(module) = module {
self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
} else if opt_ns == Some(MacroNS) {
self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
.map(MacroBinding::binding)
@ -3762,7 +3761,7 @@ impl<'a> Resolver<'a> {
// Look for associated items in the current trait.
if let Some((module, _)) = self.current_trait_ref {
if let Ok(binding) =
self.resolve_ident_in_module(module, ident, ns, false, false, module.span) {
self.resolve_ident_in_module(module, ident, ns, false, module.span) {
let def = binding.def();
if filter_fn(def) {
return Some(if self.has_self.contains(&def.def_id()) {
@ -4075,7 +4074,7 @@ impl<'a> Resolver<'a> {
let mut found_traits = Vec::new();
// Look for the current trait.
if let Some((module, _)) = self.current_trait_ref {
if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() {
if self.resolve_ident_in_module(module, ident, ns, false, module.span).is_ok() {
let def_id = module.def_id().unwrap();
found_traits.push(TraitCandidate { def_id: def_id, import_id: None });
}

View file

@ -220,7 +220,7 @@ impl<'a> base::Resolver for Resolver<'a> {
vis: ty::Visibility::Invisible,
expansion: Mark::root(),
});
self.global_macros.insert(ident.name, binding);
self.macro_prelude.insert(ident.name, binding);
}
fn resolve_imports(&mut self) {
@ -238,7 +238,7 @@ impl<'a> base::Resolver for Resolver<'a> {
attr::mark_known(&attrs[i]);
}
match self.global_macros.get(&name).cloned() {
match self.macro_prelude.get(&name).cloned() {
Some(binding) => match *binding.get_macro(self) {
MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
return Some(attrs.remove(i))
@ -274,7 +274,7 @@ impl<'a> base::Resolver for Resolver<'a> {
}
let trait_name = traits[j].segments[0].ident.name;
let legacy_name = Symbol::intern(&format!("derive_{}", trait_name));
if !self.global_macros.contains_key(&legacy_name) {
if !self.macro_prelude.contains_key(&legacy_name) {
continue
}
let span = traits.remove(j).span;
@ -565,7 +565,7 @@ impl<'a> Resolver<'a> {
module, ident, ns, true, record_used, path_span,
).map(MacroBinding::Modern)
} else {
self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
self.macro_prelude.get(&ident.name).cloned().ok_or(determinacy)
.map(MacroBinding::Global)
};
self.current_module = orig_current_module;
@ -588,8 +588,7 @@ impl<'a> Resolver<'a> {
return potential_illegal_shadower;
}
}
if binding.expansion != Mark::root() ||
(binding.is_glob_import() && module.unwrap().def().is_some()) {
if binding.is_glob_import() || binding.expansion != Mark::root() {
potential_illegal_shadower = result;
} else {
return result;
@ -652,7 +651,7 @@ impl<'a> Resolver<'a> {
let binding = if let Some(binding) = binding {
MacroBinding::Legacy(binding)
} else if let Some(binding) = self.global_macros.get(&ident.name).cloned() {
} else if let Some(binding) = self.macro_prelude.get(&ident.name).cloned() {
if !self.use_extern_macros {
self.record_use(ident, MacroNS, binding, DUMMY_SP);
}
@ -762,8 +761,8 @@ impl<'a> Resolver<'a> {
// Then check global macros.
}.or_else(|| {
// FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
let global_macros = self.global_macros.clone();
let names = global_macros.iter().filter_map(|(name, binding)| {
let macro_prelude = self.macro_prelude.clone();
let names = macro_prelude.iter().filter_map(|(name, binding)| {
if binding.get_macro(self).kind() == kind {
Some(name)
} else {

View file

@ -17,6 +17,7 @@ use Resolver;
use {names_to_string, module_to_string};
use {resolve_error, ResolutionError};
use rustc_data_structures::ptr_key::PtrKey;
use rustc::ty;
use rustc::lint::builtin::BuiltinLintDiagnostics;
use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
@ -104,67 +105,20 @@ impl<'a> ImportDirective<'a> {
#[derive(Clone, Default, Debug)]
/// Records information about the resolution of a name in a namespace of a module.
pub struct NameResolution<'a> {
/// The single imports that define the name in the namespace.
single_imports: SingleImports<'a>,
/// Single imports that may define the name in the namespace.
/// Import directives are arena-allocated, so it's ok to use pointers as keys.
single_imports: FxHashSet<PtrKey<'a, ImportDirective<'a>>>,
/// The least shadowable known binding for this name, or None if there are no known bindings.
pub binding: Option<&'a NameBinding<'a>>,
shadows_glob: Option<&'a NameBinding<'a>>,
}
#[derive(Clone, Debug)]
enum SingleImports<'a> {
/// No single imports can define the name in the namespace.
None,
/// Only the given single import can define the name in the namespace.
MaybeOne(&'a ImportDirective<'a>),
/// Only one of these two single imports can define the name in the namespace.
MaybeTwo(&'a ImportDirective<'a>, &'a ImportDirective<'a>),
/// At least one single import will define the name in the namespace.
AtLeastOne,
}
impl<'a> Default for SingleImports<'a> {
/// Creates a `SingleImports<'a>` of None type.
fn default() -> Self {
SingleImports::None
}
}
impl<'a> SingleImports<'a> {
fn add_directive(&mut self, directive: &'a ImportDirective<'a>, use_extern_macros: bool) {
match *self {
SingleImports::None => *self = SingleImports::MaybeOne(directive),
SingleImports::MaybeOne(directive_one) => *self = if use_extern_macros {
SingleImports::MaybeTwo(directive_one, directive)
} else {
SingleImports::AtLeastOne
},
// If three single imports can define the name in the namespace, we can assume that at
// least one of them will define it since otherwise we'd get duplicate errors in one of
// other namespaces.
SingleImports::MaybeTwo(..) => *self = SingleImports::AtLeastOne,
SingleImports::AtLeastOne => {}
};
}
fn directive_failed(&mut self, dir: &'a ImportDirective<'a>) {
match *self {
SingleImports::None => unreachable!(),
SingleImports::MaybeOne(_) => *self = SingleImports::None,
SingleImports::MaybeTwo(dir1, dir2) =>
*self = SingleImports::MaybeOne(if ptr::eq(dir1, dir) { dir1 } else { dir2 }),
SingleImports::AtLeastOne => {}
}
}
shadowed_glob: Option<&'a NameBinding<'a>>,
}
impl<'a> NameResolution<'a> {
// Returns the binding for the name if it is known or None if it not known.
fn binding(&self) -> Option<&'a NameBinding<'a>> {
self.binding.and_then(|binding| match self.single_imports {
SingleImports::None => Some(binding),
_ if !binding.is_glob_import() => Some(binding),
_ => None, // The binding could be shadowed by a single import, so it is not known.
self.binding.and_then(|binding| {
if !binding.is_glob_import() ||
self.single_imports.is_empty() { Some(binding) } else { None }
})
}
}
@ -177,7 +131,7 @@ impl<'a> Resolver<'a> {
}
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
/// Invariant: if `record_used` is `Some`, import resolution must be complete.
/// Invariant: if `record_used` is `Some`, expansion and import resolution must be complete.
pub fn resolve_ident_in_module_unadjusted(&mut self,
module: Module<'a>,
ident: Ident,
@ -194,7 +148,7 @@ impl<'a> Resolver<'a> {
if record_used {
if let Some(binding) = resolution.binding {
if let Some(shadowed_glob) = resolution.shadows_glob {
if let Some(shadowed_glob) = resolution.shadowed_glob {
let name = ident.name;
// Forbid expanded shadowing to avoid time travel.
if restricted_shadowing &&
@ -227,81 +181,72 @@ impl<'a> Resolver<'a> {
if usable { Ok(binding) } else { Err(Determined) }
};
// Items and single imports are not shadowable.
// Items and single imports are not shadowable, if we have one, then it's determined.
if let Some(binding) = resolution.binding {
if !binding.is_glob_import() {
return check_usable(self, binding);
}
}
// Check if a single import can still define the name.
let resolve_single_import = |this: &mut Self, directive: &'a ImportDirective<'a>| {
let module = match directive.imported_module.get() {
Some(module) => module,
None => return false,
};
let ident = match directive.subclass {
// --- From now on we either have a glob resolution or no resolution. ---
// Check if one of single imports can still define the name,
// if it can then our result is not determined and can be invalidated.
for single_import in &resolution.single_imports {
if !self.is_accessible(single_import.vis.get()) {
continue;
}
let module = unwrap_or!(single_import.imported_module.get(), return Err(Undetermined));
let ident = match single_import.subclass {
SingleImport { source, .. } => source,
_ => unreachable!(),
};
match this.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
Err(Determined) => {}
_ => return false,
match self.resolve_ident_in_module(module, ident, ns, false, path_span) {
Err(Determined) => continue,
Ok(_) | Err(Undetermined) => return Err(Undetermined),
}
true
};
match resolution.single_imports {
SingleImports::AtLeastOne => return Err(Undetermined),
SingleImports::MaybeOne(directive) => {
let accessible = self.is_accessible(directive.vis.get());
if accessible {
if !resolve_single_import(self, directive) {
return Err(Undetermined)
}
}
}
SingleImports::MaybeTwo(directive1, directive2) => {
let accessible1 = self.is_accessible(directive1.vis.get());
let accessible2 = self.is_accessible(directive2.vis.get());
if accessible1 && accessible2 {
if !resolve_single_import(self, directive1) &&
!resolve_single_import(self, directive2) {
return Err(Undetermined)
}
} else if accessible1 {
if !resolve_single_import(self, directive1) {
return Err(Undetermined)
}
} else {
if !resolve_single_import(self, directive2) {
return Err(Undetermined)
}
}
}
SingleImports::None => {},
}
let no_unresolved_invocations =
restricted_shadowing || module.unresolved_invocations.borrow().is_empty();
match resolution.binding {
// In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`).
Some(binding) if no_unresolved_invocations || ns == MacroNS =>
return check_usable(self, binding),
None if no_unresolved_invocations => {}
_ => return Err(Undetermined),
// So we have a resolution that's from a glob import. This resolution is determined
// if it cannot be shadowed by some new item/import expanded from a macro.
// This happens either if there are no unexpanded macros, or expanded names cannot
// shadow globs (that happens in macro namespace or with restricted shadowing).
let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty();
if let Some(binding) = resolution.binding {
if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
return check_usable(self, binding);
} else {
return Err(Undetermined);
}
}
// Check if the globs are determined
if restricted_shadowing && module.def().is_some() {
// --- From now on we have no resolution. ---
// Now we are in situation when new item/import can appear only from a glob or a macro
// expansion. With restricted shadowing names from globs and macro expansions cannot
// shadow names from outer scopes, so we can freely fallback from module search to search
// in outer scopes. To continue search in outer scopes we have to lie a bit and return
// `Determined` to `resolve_lexical_macro_path_segment` even if the correct answer
// for in-module resolution could be `Undetermined`.
if restricted_shadowing {
return Err(Determined);
}
for directive in module.globs.borrow().iter() {
if !self.is_accessible(directive.vis.get()) {
// Check if one of unexpanded macros can still define the name,
// if it can then our "no resolution" result is not determined and can be invalidated.
if unexpanded_macros {
return Err(Undetermined);
}
// Check if one of glob imports can still define the name,
// if it can then our "no resolution" result is not determined and can be invalidated.
for glob_import in module.globs.borrow().iter() {
if !self.is_accessible(glob_import.vis.get()) {
continue
}
let module = unwrap_or!(directive.imported_module.get(), return Err(Undetermined));
let module = unwrap_or!(glob_import.imported_module.get(), return Err(Undetermined));
let (orig_current_module, mut ident) = (self.current_module, ident.modern());
match ident.span.glob_adjust(module.expansion, directive.span.ctxt().modern()) {
match ident.span.glob_adjust(module.expansion, glob_import.span.ctxt().modern()) {
Some(Some(def)) => self.current_module = self.macro_def_scope(def),
Some(None) => {}
None => continue,
@ -310,11 +255,13 @@ impl<'a> Resolver<'a> {
module, ident, ns, false, false, path_span,
);
self.current_module = orig_current_module;
if let Err(Undetermined) = result {
return Err(Undetermined);
match result {
Err(Determined) => continue,
Ok(_) | Err(Undetermined) => return Err(Undetermined),
}
}
// No resolution and no one else can define the name - determinate error.
Err(Determined)
}
@ -348,7 +295,7 @@ impl<'a> Resolver<'a> {
SingleImport { target, type_ns_only, .. } => {
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
resolution.single_imports.add_directive(directive, this.use_extern_macros);
resolution.single_imports.insert(PtrKey(directive));
});
}
// We don't add prelude imports to the globs since they only affect lexical scopes,
@ -401,7 +348,7 @@ impl<'a> Resolver<'a> {
if binding.is_glob_import() {
if !old_binding.is_glob_import() &&
!(ns == MacroNS && old_binding.expansion != Mark::root()) {
resolution.shadows_glob = Some(binding);
resolution.shadowed_glob = Some(binding);
} else if binding.def() != old_binding.def() {
resolution.binding = Some(this.ambiguity(old_binding, binding));
} else if !old_binding.vis.is_at_least(binding.vis, &*this) {
@ -414,7 +361,7 @@ impl<'a> Resolver<'a> {
resolution.binding = Some(this.ambiguity(binding, old_binding));
} else {
resolution.binding = Some(binding);
resolution.shadows_glob = Some(old_binding);
resolution.shadowed_glob = Some(old_binding);
}
} else {
return Err(old_binding);
@ -455,7 +402,7 @@ impl<'a> Resolver<'a> {
_ if old_binding.is_some() => return t,
None => return t,
Some(binding) => match old_binding {
Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
Some(old_binding) if ptr::eq(old_binding, binding) => return t,
_ => (binding, t),
}
}
@ -630,7 +577,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
source,
ns,
false,
false,
directive.span));
} else {
return
@ -641,7 +587,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
Err(Undetermined) => indeterminate = true,
Err(Determined) => {
this.update_resolution(parent, target, ns, |_, resolution| {
resolution.single_imports.directive_failed(directive)
resolution.single_imports.remove(&PtrKey(directive));
});
}
Ok(binding) if !binding.is_importable() => {
@ -803,7 +749,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
if all_ns_err {
let mut all_ns_failed = true;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
match this.resolve_ident_in_module(module, ident, ns, false, true, span) {
match this.resolve_ident_in_module(module, ident, ns, true, span) {
Ok(_) => all_ns_failed = false,
_ => {}
}
@ -827,7 +773,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
_ => Some(&i.name),
}
},
NameResolution { single_imports: SingleImports::None, .. } => None,
NameResolution { ref single_imports, .. }
if single_imports.is_empty() => None,
_ => Some(&i.name),
}
});
@ -973,7 +920,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
let mut reexports = Vec::new();
let mut exported_macro_names = FxHashMap();
if module as *const _ == self.graph_root as *const _ {
if ptr::eq(module, self.graph_root) {
let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
for export in macro_exports.into_iter().rev() {
if let Some(later_span) = exported_macro_names.insert(export.ident.modern(),

View file

@ -0,0 +1,44 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(decl_macro)]
mod m {
pub macro env($e: expr) { $e }
pub macro fenv() { 0 }
}
mod glob_in_normal_module {
use m::*;
fn check() {
let x = env!("PATH"); //~ ERROR `env` is ambiguous
}
}
mod glob_in_block_module {
fn block() {
use m::*;
fn check() {
let x = env!("PATH"); //~ ERROR `env` is ambiguous
}
}
}
mod glob_shadows_item {
pub macro fenv($e: expr) { $e }
fn block() {
use m::*;
fn check() {
let x = fenv!(); //~ ERROR `fenv` is ambiguous
}
}
}
fn main() {}

View file

@ -0,0 +1,49 @@
error[E0659]: `env` is ambiguous
--> $DIR/glob-shadowing.rs:21:17
|
LL | let x = env!("PATH"); //~ ERROR `env` is ambiguous
| ^^^
|
note: `env` could refer to the name imported here
--> $DIR/glob-shadowing.rs:19:9
|
LL | use m::*;
| ^^^^
= note: `env` is also a builtin macro
= note: consider adding an explicit import of `env` to disambiguate
error[E0659]: `env` is ambiguous
--> $DIR/glob-shadowing.rs:29:21
|
LL | let x = env!("PATH"); //~ ERROR `env` is ambiguous
| ^^^
|
note: `env` could refer to the name imported here
--> $DIR/glob-shadowing.rs:27:13
|
LL | use m::*;
| ^^^^
= note: `env` is also a builtin macro
= note: consider adding an explicit import of `env` to disambiguate
error[E0659]: `fenv` is ambiguous
--> $DIR/glob-shadowing.rs:39:21
|
LL | let x = fenv!(); //~ ERROR `fenv` is ambiguous
| ^^^^
|
note: `fenv` could refer to the name imported here
--> $DIR/glob-shadowing.rs:37:13
|
LL | use m::*;
| ^^^^
note: `fenv` could also refer to the name defined here
--> $DIR/glob-shadowing.rs:35:5
|
LL | pub macro fenv($e: expr) { $e }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: consider adding an explicit import of `fenv` to disambiguate
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0659`.