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:
commit
ef9781358d
12 changed files with 248 additions and 166 deletions
|
|
@ -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 _)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
45
src/librustc_data_structures/ptr_key.rs
Normal file
45
src/librustc_data_structures/ptr_key.rs
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
44
src/test/ui/imports/glob-shadowing.rs
Normal file
44
src/test/ui/imports/glob-shadowing.rs
Normal 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() {}
|
||||
49
src/test/ui/imports/glob-shadowing.stderr
Normal file
49
src/test/ui/imports/glob-shadowing.stderr
Normal 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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue