Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

beta backports #56240

Merged
merged 8 commits into from
Nov 26, 2018
Prev Previous commit
Next Next commit
resolve: Generalize early_resolve_ident_in_lexical_scope slightly
Flatten `ModuleOrUniformRoot` variants
petrochenkov committed Nov 25, 2018
commit 2a0adc3a3e549bc9d133e0e396664d5dde87da4b
51 changes: 25 additions & 26 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
@@ -102,6 +102,12 @@ enum Weak {
No,
}

enum ScopeSet {
Import(Namespace),
Macro(MacroKind),
Module,
}

/// A free importable items suggested in case of resolution failure.
struct ImportSuggestion {
path: Path,
@@ -997,31 +1003,28 @@ impl<'a> LexicalScopeBinding<'a> {
}
}


#[derive(Clone, Copy, PartialEq, Debug)]
enum UniformRootKind {
CurrentScope,
ExternPrelude,
}

#[derive(Copy, Clone, Debug)]
enum ModuleOrUniformRoot<'a> {
/// Regular module.
Module(Module<'a>),

/// This "virtual module" denotes either resolution in extern prelude
/// for paths starting with `::` on 2018 edition or `extern::`,
/// or resolution in current scope for single-segment imports.
UniformRoot(UniformRootKind),
/// Virtual module that denotes resolution in extern prelude.
/// Used for paths starting with `::` on 2018 edition or `extern::`.
ExternPrelude,

/// Virtual module that denotes resolution in current scope.
/// Used only for resolving single-segment imports. The reason it exists is that import paths
/// are always split into two parts, the first of which should be some kind of module.
CurrentScope,
}

impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
fn eq(&self, other: &Self) -> bool {
match (*self, *other) {
(ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) =>
ptr::eq(lhs, rhs),
(ModuleOrUniformRoot::UniformRoot(lhs), ModuleOrUniformRoot::UniformRoot(rhs)) =>
lhs == rhs,
(ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) => true,
(ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true,
_ => false,
}
}
@@ -1763,8 +1766,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
error_callback(self, span, ResolutionError::FailedToResolve(msg));
Def::Err
}
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
PathResult::Indeterminate => unreachable!(),
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
PathResult::Failed(span, msg, _) => {
error_callback(self, span, ResolutionError::FailedToResolve(&msg));
Def::Err
@@ -2225,11 +2227,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
self.current_module = self.macro_def_scope(def);
}
}
ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude) => {
ModuleOrUniformRoot::ExternPrelude => {
ident.span = ident.span.modern();
ident.span.adjust(Mark::root());
}
ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope) => {
ModuleOrUniformRoot::CurrentScope => {
// No adjustments
}
}
@@ -3669,8 +3671,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
err_path_resolution()
}
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
PathResult::Failed(..) => return None,
PathResult::Module(..) | PathResult::Failed(..) => return None,
PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
};

@@ -3789,8 +3790,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}
if name == keywords::Extern.name() ||
name == keywords::CrateRoot.name() && ident.span.rust_2018() {
module =
Some(ModuleOrUniformRoot::UniformRoot(UniformRootKind::ExternPrelude));
module = Some(ModuleOrUniformRoot::ExternPrelude);
continue;
}
if name == keywords::CrateRoot.name() ||
@@ -3823,9 +3823,9 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
self.resolve_ident_in_module(module, ident, ns, None, record_used, path_span)
} else if opt_ns.is_none() || opt_ns == Some(MacroNS) {
assert!(ns == TypeNS);
self.early_resolve_ident_in_lexical_scope(ident, ns, None, opt_ns.is_none(),
parent_scope, record_used, record_used,
path_span)
let scopes = if opt_ns.is_none() { ScopeSet::Import(ns) } else { ScopeSet::Module };
self.early_resolve_ident_in_lexical_scope(ident, scopes, parent_scope, record_used,
record_used, path_span)
} else {
let record_used_id =
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
@@ -3914,8 +3914,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {

PathResult::Module(match module {
Some(module) => module,
None if path.is_empty() =>
ModuleOrUniformRoot::UniformRoot(UniformRootKind::CurrentScope),
None if path.is_empty() => ModuleOrUniformRoot::CurrentScope,
_ => span_bug!(path_span, "resolve_path: non-empty path `{:?}` has no module", path),
})
}
22 changes: 12 additions & 10 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
@@ -9,11 +9,11 @@
// except according to those terms.

use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, Resolver, ResolutionError, Weak};
use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
use {is_known_tool, resolve_error};
use ModuleOrUniformRoot;
use Namespace::{self, *};
use Namespace::*;
use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
use resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
@@ -502,7 +502,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
def
} else {
let binding = self.early_resolve_ident_in_lexical_scope(
path[0].ident, MacroNS, Some(kind), false, parent_scope, false, force, path_span
path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span
);
match binding {
Ok(..) => {}
@@ -527,9 +527,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
crate fn early_resolve_ident_in_lexical_scope(
&mut self,
orig_ident: Ident,
ns: Namespace,
macro_kind: Option<MacroKind>,
is_import: bool,
scope_set: ScopeSet,
parent_scope: &ParentScope<'a>,
record_used: bool,
force: bool,
@@ -605,8 +603,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}

assert!(force || !record_used); // `record_used` implies `force`
assert!(macro_kind.is_none() || !is_import); // `is_import` implies no macro kind
let rust_2015 = orig_ident.span.rust_2015();
let mut ident = orig_ident.modern();

// Make sure `self`, `super` etc produce an error when passed to here.
@@ -628,6 +624,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let mut innermost_result: Option<(&NameBinding, Flags)> = None;

// Go through all the scopes and try to resolve the name.
let rust_2015 = orig_ident.span.rust_2015();
let (ns, macro_kind, is_import) = match scope_set {
ScopeSet::Import(ns) => (ns, None, true),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
ScopeSet::Module => (TypeNS, None, false),
};
let mut where_to_resolve = match ns {
_ if is_import && rust_2015 => WhereToResolve::CrateRoot,
TypeNS | ValueNS => WhereToResolve::Module(parent_scope.module),
@@ -1041,7 +1043,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let macro_resolutions =
mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
match self.early_resolve_ident_in_lexical_scope(ident, MacroNS, Some(kind), false,
match self.early_resolve_ident_in_lexical_scope(ident, ScopeSet::Macro(kind),
&parent_scope, true, true, ident.span) {
Ok(binding) => {
let initial_def = initial_binding.map(|initial_binding| {
@@ -1067,7 +1069,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
for (ident, parent_scope) in builtin_attrs {
let _ = self.early_resolve_ident_in_lexical_scope(
ident, MacroNS, Some(MacroKind::Attr), false, &parent_scope, true, true, ident.span
ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, true, true, ident.span
);
}
}
86 changes: 40 additions & 46 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
use self::ImportDirectiveSubclass::*;

use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, Module, ModuleOrUniformRoot, PerNS, UniformRootKind, Weak};
use {CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
use Namespace::{self, TypeNS, MacroNS};
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
use {Resolver, Segment};
@@ -162,46 +162,42 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
let module = match module {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::UniformRoot(uniform_root_kind) => {
ModuleOrUniformRoot::ExternPrelude => {
assert!(!restricted_shadowing);
match uniform_root_kind {
UniformRootKind::ExternPrelude => {
return if let Some(binding) =
self.extern_prelude_get(ident, !record_used) {
Ok(binding)
} else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
// Macro-expanded `extern crate` items can add names to extern prelude.
Err((Undetermined, Weak::No))
} else {
Err((Determined, Weak::No))
}
}
UniformRootKind::CurrentScope => {
let parent_scope =
parent_scope.expect("no parent scope for a single-segment import");

if ns == TypeNS {
if ident.name == keywords::Crate.name() ||
ident.name == keywords::DollarCrate.name() {
let module = self.resolve_crate_root(ident);
let binding = (module, ty::Visibility::Public,
module.span, Mark::root())
.to_name_binding(self.arenas);
return Ok(binding);
} else if ident.name == keywords::Super.name() ||
ident.name == keywords::SelfValue.name() {
// FIXME: Implement these with renaming requirements so that e.g.
// `use super;` doesn't work, but `use super as name;` does.
// Fall through here to get an error from `early_resolve_...`.
}
}

let binding = self.early_resolve_ident_in_lexical_scope(
ident, ns, None, true, parent_scope, record_used, record_used, path_span
);
return binding.map_err(|determinacy| (determinacy, Weak::No));
return if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
Ok(binding)
} else if !self.graph_root.unresolved_invocations.borrow().is_empty() {
// Macro-expanded `extern crate` items can add names to extern prelude.
Err((Undetermined, Weak::No))
} else {
Err((Determined, Weak::No))
}
}
ModuleOrUniformRoot::CurrentScope => {
assert!(!restricted_shadowing);
let parent_scope =
parent_scope.expect("no parent scope for a single-segment import");

if ns == TypeNS {
if ident.name == keywords::Crate.name() ||
ident.name == keywords::DollarCrate.name() {
let module = self.resolve_crate_root(ident);
let binding = (module, ty::Visibility::Public,
module.span, Mark::root())
.to_name_binding(self.arenas);
return Ok(binding);
} else if ident.name == keywords::Super.name() ||
ident.name == keywords::SelfValue.name() {
// FIXME: Implement these with renaming requirements so that e.g.
// `use super;` doesn't work, but `use super as name;` does.
// Fall through here to get an error from `early_resolve_...`.
}
}

let binding = self.early_resolve_ident_in_lexical_scope(
ident, ScopeSet::Import(ns), parent_scope, record_used, record_used, path_span
);
return binding.map_err(|determinacy| (determinacy, Weak::No));
}
};

@@ -334,7 +330,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
}
let module = match glob_import.imported_module.get() {
Some(ModuleOrUniformRoot::Module(module)) => module,
Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
Some(_) => continue,
None => return Err((Undetermined, Weak::Yes)),
};
let (orig_current_module, mut ident) = (self.current_module, ident.modern());
@@ -967,9 +963,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {

return if all_ns_failed {
let resolutions = match module {
ModuleOrUniformRoot::Module(module) =>
Some(module.resolutions.borrow()),
ModuleOrUniformRoot::UniformRoot(_) => None,
ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()),
_ => None,
};
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
@@ -1007,7 +1002,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
format!("no `{}` in the root{}", ident, lev_suggestion)
}
}
ModuleOrUniformRoot::UniformRoot(_) => {
_ => {
if !ident.is_path_segment_keyword() {
format!("no `{}` external crate{}", ident, lev_suggestion)
} else {
@@ -1108,9 +1103,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
let module = match directive.imported_module.get().unwrap() {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::UniformRoot(_) => {
self.session.span_err(directive.span,
"cannot glob-import all possible crates");
_ => {
self.session.span_err(directive.span, "cannot glob-import all possible crates");
return;
}
};