2015-03-16 10:44:19 +13:00
|
|
|
// Copyright 2015 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 self::ImportDirectiveSubclass::*;
|
|
|
|
|
2016-11-27 10:58:46 +00:00
|
|
|
use {AmbiguityError, Module, PerNS};
|
2016-11-10 10:29:36 +00:00
|
|
|
use Namespace::{self, TypeNS, MacroNS};
|
2017-12-10 03:30:47 +03:00
|
|
|
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
|
2015-03-16 10:44:19 +13:00
|
|
|
use Resolver;
|
|
|
|
use {names_to_string, module_to_string};
|
2015-07-14 19:42:38 +02:00
|
|
|
use {resolve_error, ResolutionError};
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2016-04-09 23:19:53 +00:00
|
|
|
use rustc::ty;
|
2017-06-25 05:50:51 +03:00
|
|
|
use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE;
|
2017-12-10 03:30:47 +03:00
|
|
|
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
|
2016-03-29 12:54:26 +03:00
|
|
|
use rustc::hir::def::*;
|
2017-11-24 11:21:43 -08:00
|
|
|
use rustc::session::DiagnosticMessageId;
|
2017-07-23 15:15:45 -07:00
|
|
|
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2017-11-07 18:01:35 -08:00
|
|
|
use syntax::ast::{Ident, Name, SpannedIdent, NodeId};
|
2016-10-11 03:41:48 +00:00
|
|
|
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
2016-11-07 22:23:26 +00:00
|
|
|
use syntax::ext::hygiene::Mark;
|
2016-12-05 03:51:11 +00:00
|
|
|
use syntax::parse::token;
|
2016-11-25 06:07:21 +00:00
|
|
|
use syntax::symbol::keywords;
|
2015-12-14 22:36:31 +05:30
|
|
|
use syntax::util::lev_distance::find_best_match_for_name;
|
2016-08-22 04:05:49 +00:00
|
|
|
use syntax_pos::Span;
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2016-03-30 22:21:56 +00:00
|
|
|
use std::cell::{Cell, RefCell};
|
2016-10-28 06:52:45 +00:00
|
|
|
use std::mem;
|
2015-03-16 10:44:19 +13:00
|
|
|
|
|
|
|
/// Contains data for specific types of import directives.
|
2016-02-13 21:49:16 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2016-08-17 20:48:53 +00:00
|
|
|
pub enum ImportDirectiveSubclass<'a> {
|
2016-02-13 21:49:16 +00:00
|
|
|
SingleImport {
|
2016-11-29 02:07:12 +00:00
|
|
|
target: Ident,
|
|
|
|
source: Ident,
|
2016-11-10 06:19:54 +00:00
|
|
|
result: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
|
2016-12-12 03:35:48 +00:00
|
|
|
type_ns_only: bool,
|
2016-02-13 21:49:16 +00:00
|
|
|
},
|
2016-08-20 00:23:32 +00:00
|
|
|
GlobImport {
|
|
|
|
is_prelude: bool,
|
2018-01-12 16:41:25 -05:00
|
|
|
max_vis: Cell<ty::Visibility>, // The visibility of the greatest re-export.
|
|
|
|
// n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
|
2016-08-20 00:23:32 +00:00
|
|
|
},
|
2017-11-07 18:01:35 -08:00
|
|
|
ExternCrate(Option<Name>),
|
2017-01-14 08:58:50 +00:00
|
|
|
MacroUse,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
/// One import directive.
|
2016-01-31 19:26:16 -08:00
|
|
|
#[derive(Debug,Clone)]
|
2016-03-17 01:13:31 +00:00
|
|
|
pub struct ImportDirective<'a> {
|
2016-04-17 01:57:09 +00:00
|
|
|
pub id: NodeId,
|
2016-10-28 03:40:58 +00:00
|
|
|
pub parent: Module<'a>,
|
2017-07-23 15:15:45 -07:00
|
|
|
pub module_path: Vec<SpannedIdent>,
|
2016-10-28 03:40:58 +00:00
|
|
|
pub imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
|
|
|
|
pub subclass: ImportDirectiveSubclass<'a>,
|
|
|
|
pub span: Span,
|
|
|
|
pub vis: Cell<ty::Visibility>,
|
2016-11-07 22:23:26 +00:00
|
|
|
pub expansion: Mark,
|
2017-01-14 07:35:54 +00:00
|
|
|
pub used: Cell<bool>,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-03-17 01:13:31 +00:00
|
|
|
impl<'a> ImportDirective<'a> {
|
2016-04-17 01:57:09 +00:00
|
|
|
pub fn is_glob(&self) -> bool {
|
2016-04-17 19:23:25 +00:00
|
|
|
match self.subclass { ImportDirectiveSubclass::GlobImport { .. } => true, _ => false }
|
2016-04-17 01:57:09 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2017-11-24 11:21:43 -08:00
|
|
|
#[derive(Clone, Default, Debug)]
|
2016-03-17 08:43:17 +00:00
|
|
|
/// Records information about the resolution of a name in a namespace of a module.
|
2016-02-07 22:28:54 +00:00
|
|
|
pub struct NameResolution<'a> {
|
2016-03-17 08:43:17 +00:00
|
|
|
/// The single imports that define the name in the namespace.
|
|
|
|
single_imports: SingleImports<'a>,
|
2016-02-07 23:58:14 +00:00
|
|
|
/// The least shadowable known binding for this name, or None if there are no known bindings.
|
2016-02-07 21:23:58 +00:00
|
|
|
pub binding: Option<&'a NameBinding<'a>>,
|
2016-11-27 10:58:46 +00:00
|
|
|
shadows_glob: Option<&'a NameBinding<'a>>,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-03-17 08:43:17 +00:00
|
|
|
#[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>),
|
|
|
|
/// At least one single import will define the name in the namespace.
|
|
|
|
AtLeastOne,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Default for SingleImports<'a> {
|
2016-09-11 17:00:09 +05:30
|
|
|
/// Creates a `SingleImports<'a>` of None type.
|
2016-03-17 08:43:17 +00:00
|
|
|
fn default() -> Self {
|
|
|
|
SingleImports::None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> SingleImports<'a> {
|
|
|
|
fn add_directive(&mut self, directive: &'a ImportDirective<'a>) {
|
|
|
|
match *self {
|
|
|
|
SingleImports::None => *self = SingleImports::MaybeOne(directive),
|
|
|
|
// If two single imports can define the name in the namespace, we can assume that at
|
|
|
|
// least one of them will define it since otherwise both would have to define only one
|
|
|
|
// namespace, leading to a duplicate error.
|
|
|
|
SingleImports::MaybeOne(_) => *self = SingleImports::AtLeastOne,
|
|
|
|
SingleImports::AtLeastOne => {}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
fn directive_failed(&mut self) {
|
|
|
|
match *self {
|
|
|
|
SingleImports::None => unreachable!(),
|
|
|
|
SingleImports::MaybeOne(_) => *self = SingleImports::None,
|
|
|
|
SingleImports::AtLeastOne => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-07 22:28:54 +00:00
|
|
|
impl<'a> NameResolution<'a> {
|
2016-03-17 08:43:17 +00:00
|
|
|
// 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),
|
2016-04-17 01:57:09 +00:00
|
|
|
_ if !binding.is_glob_import() => Some(binding),
|
2016-03-17 08:43:17 +00:00
|
|
|
_ => None, // The binding could be shadowed by a single import, so it is not known.
|
|
|
|
})
|
|
|
|
}
|
2016-08-01 20:43:48 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 01:33:19 +00:00
|
|
|
impl<'a> Resolver<'a> {
|
2016-11-29 02:07:12 +00:00
|
|
|
fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
|
2016-08-17 01:33:19 +00:00
|
|
|
-> &'a RefCell<NameResolution<'a>> {
|
2017-03-22 08:39:51 +00:00
|
|
|
*module.resolutions.borrow_mut().entry((ident.modern(), ns))
|
2016-08-17 01:33:19 +00:00
|
|
|
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
2016-08-01 20:43:48 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
2016-08-15 08:19:09 +00:00
|
|
|
/// Invariant: if `record_used` is `Some`, import resolution must be complete.
|
2017-03-22 08:39:51 +00:00
|
|
|
pub fn resolve_ident_in_module_unadjusted(&mut self,
|
|
|
|
module: Module<'a>,
|
|
|
|
ident: Ident,
|
|
|
|
ns: Namespace,
|
|
|
|
restricted_shadowing: bool,
|
|
|
|
record_used: bool,
|
|
|
|
path_span: Span)
|
|
|
|
-> Result<&'a NameBinding<'a>, Determinacy> {
|
2016-08-01 20:43:48 +00:00
|
|
|
self.populate_module_if_necessary(module);
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
let resolution = self.resolution(module, ident, ns)
|
2016-12-14 13:02:00 -08:00
|
|
|
.try_borrow_mut()
|
|
|
|
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
|
2016-08-01 20:43:48 +00:00
|
|
|
|
2017-05-12 11:21:11 +02:00
|
|
|
if record_used {
|
2016-08-15 08:19:09 +00:00
|
|
|
if let Some(binding) = resolution.binding {
|
2016-11-27 10:58:46 +00:00
|
|
|
if let Some(shadowed_glob) = resolution.shadows_glob {
|
2016-11-29 02:07:12 +00:00
|
|
|
let name = ident.name;
|
2017-03-11 10:58:19 +00:00
|
|
|
// Forbid expanded shadowing to avoid time travel.
|
|
|
|
if restricted_shadowing &&
|
2016-11-27 10:58:46 +00:00
|
|
|
binding.expansion != Mark::root() &&
|
|
|
|
ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing
|
|
|
|
binding.def() != shadowed_glob.def() {
|
|
|
|
self.ambiguity_errors.push(AmbiguityError {
|
2017-05-12 11:21:11 +02:00
|
|
|
span: path_span,
|
2017-08-06 22:54:09 -07:00
|
|
|
name,
|
2017-05-12 11:21:11 +02:00
|
|
|
lexical: false,
|
|
|
|
b1: binding,
|
|
|
|
b2: shadowed_glob,
|
2016-12-09 11:08:39 +00:00
|
|
|
legacy: false,
|
2016-11-27 10:58:46 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2017-05-12 11:21:11 +02:00
|
|
|
if self.record_use(ident, ns, binding, path_span) {
|
2016-11-26 12:21:47 +00:00
|
|
|
return Ok(self.dummy_binding);
|
2016-08-20 05:23:19 +00:00
|
|
|
}
|
2016-08-15 08:19:09 +00:00
|
|
|
if !self.is_accessible(binding.vis) {
|
2017-05-12 11:21:11 +02:00
|
|
|
self.privacy_errors.push(PrivacyError(path_span, ident.name, binding));
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-26 12:21:47 +00:00
|
|
|
return resolution.binding.ok_or(Determined);
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
|
|
|
|
2016-11-10 10:29:36 +00:00
|
|
|
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
|
2018-02-16 15:56:50 +01:00
|
|
|
// `extern crate` are always usable for backwards compatibility, see issue #37020.
|
2016-10-11 07:47:21 +00:00
|
|
|
let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
|
2016-11-26 12:21:47 +00:00
|
|
|
if usable { Ok(binding) } else { Err(Determined) }
|
2016-11-10 10:29:36 +00:00
|
|
|
};
|
2016-08-01 20:43:48 +00:00
|
|
|
|
2016-11-10 10:29:36 +00:00
|
|
|
// Items and single imports are not shadowable.
|
|
|
|
if let Some(binding) = resolution.binding {
|
|
|
|
if !binding.is_glob_import() {
|
|
|
|
return check_usable(self, binding);
|
2016-08-01 20:43:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-17 08:43:17 +00:00
|
|
|
// Check if a single import can still define the name.
|
2016-08-01 20:43:48 +00:00
|
|
|
match resolution.single_imports {
|
2016-11-26 12:21:47 +00:00
|
|
|
SingleImports::AtLeastOne => return Err(Undetermined),
|
2016-08-18 00:11:56 +00:00
|
|
|
SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => {
|
2016-08-18 01:43:26 +00:00
|
|
|
let module = match directive.imported_module.get() {
|
|
|
|
Some(module) => module,
|
2016-11-26 12:21:47 +00:00
|
|
|
None => return Err(Undetermined),
|
2016-03-18 00:05:08 +00:00
|
|
|
};
|
2016-11-29 02:07:12 +00:00
|
|
|
let ident = match directive.subclass {
|
2016-03-30 22:21:56 +00:00
|
|
|
SingleImport { source, .. } => source,
|
2016-10-28 03:40:58 +00:00
|
|
|
_ => unreachable!(),
|
2016-03-18 00:05:08 +00:00
|
|
|
};
|
2017-05-12 11:21:11 +02:00
|
|
|
match self.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
|
2016-11-26 12:21:47 +00:00
|
|
|
Err(Determined) => {}
|
|
|
|
_ => return Err(Undetermined),
|
2016-03-18 00:05:08 +00:00
|
|
|
}
|
2016-03-17 08:43:17 +00:00
|
|
|
}
|
2016-08-15 08:19:09 +00:00
|
|
|
SingleImports::MaybeOne(_) | SingleImports::None => {},
|
2016-03-13 09:59:16 +00:00
|
|
|
}
|
2016-03-17 08:43:17 +00:00
|
|
|
|
2016-11-10 10:29:36 +00:00
|
|
|
let no_unresolved_invocations =
|
2017-03-11 10:58:19 +00:00
|
|
|
restricted_shadowing || module.unresolved_invocations.borrow().is_empty();
|
2016-11-10 10:29:36 +00:00
|
|
|
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 => {}
|
2016-11-26 12:21:47 +00:00
|
|
|
_ => return Err(Undetermined),
|
2016-11-11 10:51:15 +00:00
|
|
|
}
|
|
|
|
|
2016-11-10 10:29:36 +00:00
|
|
|
// Check if the globs are determined
|
2017-03-11 10:58:19 +00:00
|
|
|
if restricted_shadowing && module.def().is_some() {
|
|
|
|
return Err(Determined);
|
|
|
|
}
|
2016-11-10 10:29:36 +00:00
|
|
|
for directive in module.globs.borrow().iter() {
|
2017-03-22 08:39:51 +00:00
|
|
|
if !self.is_accessible(directive.vis.get()) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
let module = unwrap_or!(directive.imported_module.get(), return Err(Undetermined));
|
|
|
|
let (orig_current_module, mut ident) = (self.current_module, ident.modern());
|
2017-07-31 23:04:34 +03:00
|
|
|
match ident.ctxt.glob_adjust(module.expansion, directive.span.ctxt().modern()) {
|
2017-03-22 08:39:51 +00:00
|
|
|
Some(Some(def)) => self.current_module = self.macro_def_scope(def),
|
|
|
|
Some(None) => {}
|
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
let result = self.resolve_ident_in_module_unadjusted(
|
|
|
|
module, ident, ns, false, false, path_span,
|
|
|
|
);
|
|
|
|
self.current_module = orig_current_module;
|
|
|
|
if let Err(Undetermined) = result {
|
|
|
|
return Err(Undetermined);
|
2016-11-10 10:29:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-26 12:21:47 +00:00
|
|
|
Err(Determined)
|
2016-03-30 22:21:56 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 00:22:03 +00:00
|
|
|
// Add an import directive to the current module.
|
|
|
|
pub fn add_import_directive(&mut self,
|
2017-07-23 15:15:45 -07:00
|
|
|
module_path: Vec<SpannedIdent>,
|
2016-08-17 20:48:53 +00:00
|
|
|
subclass: ImportDirectiveSubclass<'a>,
|
2016-03-17 08:43:17 +00:00
|
|
|
span: Span,
|
|
|
|
id: NodeId,
|
2016-11-07 22:23:26 +00:00
|
|
|
vis: ty::Visibility,
|
|
|
|
expansion: Mark) {
|
2016-08-17 01:33:19 +00:00
|
|
|
let current_module = self.current_module;
|
2016-03-17 08:43:17 +00:00
|
|
|
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
2016-08-17 01:33:19 +00:00
|
|
|
parent: current_module,
|
2017-08-06 22:54:09 -07:00
|
|
|
module_path,
|
2016-08-18 01:43:26 +00:00
|
|
|
imported_module: Cell::new(None),
|
2017-08-06 22:54:09 -07:00
|
|
|
subclass,
|
|
|
|
span,
|
|
|
|
id,
|
2016-08-18 00:11:56 +00:00
|
|
|
vis: Cell::new(vis),
|
2017-08-06 22:54:09 -07:00
|
|
|
expansion,
|
2017-01-14 07:35:54 +00:00
|
|
|
used: Cell::new(false),
|
2016-03-17 08:43:17 +00:00
|
|
|
});
|
|
|
|
|
2016-08-17 00:52:18 +00:00
|
|
|
self.indeterminate_imports.push(directive);
|
2016-03-17 08:43:17 +00:00
|
|
|
match directive.subclass {
|
|
|
|
SingleImport { target, .. } => {
|
2016-11-10 06:19:54 +00:00
|
|
|
self.per_ns(|this, ns| {
|
|
|
|
let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
|
2016-08-17 00:22:03 +00:00
|
|
|
resolution.single_imports.add_directive(directive);
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2016-03-17 08:43:17 +00:00
|
|
|
}
|
2016-03-17 11:05:09 +00:00
|
|
|
// We don't add prelude imports to the globs since they only affect lexical scopes,
|
|
|
|
// which are not relevant to import resolution.
|
2016-08-20 00:23:32 +00:00
|
|
|
GlobImport { is_prelude: true, .. } => {}
|
2016-08-17 00:22:03 +00:00
|
|
|
GlobImport { .. } => self.current_module.globs.borrow_mut().push(directive),
|
2016-10-28 03:40:58 +00:00
|
|
|
_ => unreachable!(),
|
2016-03-17 11:05:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-31 04:53:04 +00:00
|
|
|
// Given a binding and an import directive that resolves to it,
|
|
|
|
// return the corresponding binding defined by the import directive.
|
2016-12-20 08:32:15 +00:00
|
|
|
pub fn import(&self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
2016-11-29 02:53:00 +00:00
|
|
|
-> &'a NameBinding<'a> {
|
2017-05-21 15:50:38 +03:00
|
|
|
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
|
2017-06-25 05:50:51 +03:00
|
|
|
// c.f. `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
|
|
|
|
!directive.is_glob() && binding.is_extern_crate() {
|
2016-08-19 22:52:26 +00:00
|
|
|
directive.vis.get()
|
|
|
|
} else {
|
|
|
|
binding.pseudo_vis()
|
|
|
|
};
|
|
|
|
|
2016-08-20 00:23:32 +00:00
|
|
|
if let GlobImport { ref max_vis, .. } = directive.subclass {
|
|
|
|
if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) {
|
|
|
|
max_vis.set(vis)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-29 02:53:00 +00:00
|
|
|
self.arenas.alloc_name_binding(NameBinding {
|
2016-07-31 04:53:04 +00:00
|
|
|
kind: NameBindingKind::Import {
|
2017-08-06 22:54:09 -07:00
|
|
|
binding,
|
|
|
|
directive,
|
2016-09-05 05:27:58 +00:00
|
|
|
used: Cell::new(false),
|
2017-01-10 05:15:02 +00:00
|
|
|
legacy_self_import: false,
|
2016-07-31 04:53:04 +00:00
|
|
|
},
|
|
|
|
span: directive.span,
|
2017-08-06 22:54:09 -07:00
|
|
|
vis,
|
2016-11-07 22:23:26 +00:00
|
|
|
expansion: directive.expansion,
|
2016-11-29 02:53:00 +00:00
|
|
|
})
|
2016-07-31 04:53:04 +00:00
|
|
|
}
|
|
|
|
|
2016-07-28 02:34:01 +00:00
|
|
|
// Define the name or return the existing binding if there is a collision.
|
2016-11-29 02:53:00 +00:00
|
|
|
pub fn try_define(&mut self,
|
|
|
|
module: Module<'a>,
|
|
|
|
ident: Ident,
|
|
|
|
ns: Namespace,
|
|
|
|
binding: &'a NameBinding<'a>)
|
|
|
|
-> Result<(), &'a NameBinding<'a>> {
|
2016-11-29 02:07:12 +00:00
|
|
|
self.update_resolution(module, ident, ns, |this, resolution| {
|
2016-07-28 02:34:01 +00:00
|
|
|
if let Some(old_binding) = resolution.binding {
|
|
|
|
if binding.is_glob_import() {
|
2016-10-11 07:47:21 +00:00
|
|
|
if !old_binding.is_glob_import() &&
|
|
|
|
!(ns == MacroNS && old_binding.expansion != Mark::root()) {
|
2016-11-27 10:58:46 +00:00
|
|
|
resolution.shadows_glob = Some(binding);
|
2016-08-20 03:28:35 +00:00
|
|
|
} else if binding.def() != old_binding.def() {
|
2016-11-10 10:29:36 +00:00
|
|
|
resolution.binding = Some(this.ambiguity(old_binding, binding));
|
2016-12-20 08:32:15 +00:00
|
|
|
} else if !old_binding.vis.is_at_least(binding.vis, &*this) {
|
2016-08-20 03:28:35 +00:00
|
|
|
// We are glob-importing the same item but with greater visibility.
|
|
|
|
resolution.binding = Some(binding);
|
|
|
|
}
|
2016-07-28 02:34:01 +00:00
|
|
|
} else if old_binding.is_glob_import() {
|
2016-10-11 07:47:21 +00:00
|
|
|
if ns == MacroNS && binding.expansion != Mark::root() &&
|
|
|
|
binding.def() != old_binding.def() {
|
2016-11-10 10:29:36 +00:00
|
|
|
resolution.binding = Some(this.ambiguity(binding, old_binding));
|
|
|
|
} else {
|
|
|
|
resolution.binding = Some(binding);
|
2016-11-27 10:58:46 +00:00
|
|
|
resolution.shadows_glob = Some(old_binding);
|
2016-11-10 10:29:36 +00:00
|
|
|
}
|
2016-07-28 02:34:01 +00:00
|
|
|
} else {
|
|
|
|
return Err(old_binding);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
resolution.binding = Some(binding);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-12-20 08:32:15 +00:00
|
|
|
pub fn ambiguity(&self, b1: &'a NameBinding<'a>, b2: &'a NameBinding<'a>)
|
2016-12-09 11:08:39 +00:00
|
|
|
-> &'a NameBinding<'a> {
|
2016-11-10 10:29:36 +00:00
|
|
|
self.arenas.alloc_name_binding(NameBinding {
|
2016-12-09 11:08:39 +00:00
|
|
|
kind: NameBindingKind::Ambiguity { b1: b1, b2: b2, legacy: false },
|
2016-11-10 10:29:36 +00:00
|
|
|
vis: if b1.vis.is_at_least(b2.vis, self) { b1.vis } else { b2.vis },
|
|
|
|
span: b1.span,
|
|
|
|
expansion: Mark::root(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-07-28 02:34:01 +00:00
|
|
|
// Use `f` to mutate the resolution of the name in the module.
|
2016-02-16 03:54:14 +00:00
|
|
|
// If the resolution becomes a success, define it in the module's glob importers.
|
2016-11-29 02:07:12 +00:00
|
|
|
fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F)
|
|
|
|
-> T
|
2016-07-28 02:34:01 +00:00
|
|
|
where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
|
2016-02-16 03:54:14 +00:00
|
|
|
{
|
2016-07-28 02:34:01 +00:00
|
|
|
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
|
|
|
|
// during which the resolution might end up getting re-defined via a glob cycle.
|
2016-08-20 07:22:32 +00:00
|
|
|
let (binding, t) = {
|
2017-08-01 13:03:03 +01:00
|
|
|
let resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
|
2016-08-20 03:28:35 +00:00
|
|
|
let old_binding = resolution.binding();
|
2016-02-16 03:54:14 +00:00
|
|
|
|
2016-07-28 02:34:01 +00:00
|
|
|
let t = f(self, resolution);
|
2016-04-07 22:14:44 +00:00
|
|
|
|
|
|
|
match resolution.binding() {
|
2016-10-11 07:47:21 +00:00
|
|
|
_ if old_binding.is_some() => return t,
|
2016-04-07 22:14:44 +00:00
|
|
|
None => return t,
|
2016-08-20 03:28:35 +00:00
|
|
|
Some(binding) => match old_binding {
|
|
|
|
Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
|
|
|
|
_ => (binding, t),
|
|
|
|
}
|
2016-02-07 23:58:14 +00:00
|
|
|
}
|
2016-04-07 22:14:44 +00:00
|
|
|
};
|
|
|
|
|
2016-08-20 07:22:32 +00:00
|
|
|
// Define `binding` in `module`s glob importers.
|
2016-08-20 00:33:06 +00:00
|
|
|
for directive in module.glob_importers.borrow_mut().iter() {
|
2017-03-22 08:39:51 +00:00
|
|
|
let mut ident = ident.modern();
|
|
|
|
let scope = match ident.ctxt.reverse_glob_adjust(module.expansion,
|
2017-07-31 23:04:34 +03:00
|
|
|
directive.span.ctxt().modern()) {
|
2017-03-22 08:39:51 +00:00
|
|
|
Some(Some(def)) => self.macro_def_scope(def),
|
|
|
|
Some(None) => directive.parent,
|
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
if self.is_accessible_from(binding.vis, scope) {
|
2016-08-20 07:22:32 +00:00
|
|
|
let imported_binding = self.import(binding, directive);
|
2016-11-29 02:07:12 +00:00
|
|
|
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
2016-07-28 02:34:01 +00:00
|
|
|
}
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
2016-07-28 02:34:01 +00:00
|
|
|
|
|
|
|
t
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
|
|
|
|
// Define a "dummy" resolution containing a Def::Err as a placeholder for a
|
|
|
|
// failed resolution
|
|
|
|
fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
|
|
|
|
if let SingleImport { target, .. } = directive.subclass {
|
|
|
|
let dummy_binding = self.dummy_binding;
|
|
|
|
let dummy_binding = self.import(dummy_binding, directive);
|
|
|
|
self.per_ns(|this, ns| {
|
2016-11-29 02:53:00 +00:00
|
|
|
let _ = this.try_define(directive.parent, target, ns, dummy_binding);
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-11-10 10:11:25 +00:00
|
|
|
pub struct ImportResolver<'a, 'b: 'a> {
|
|
|
|
pub resolver: &'a mut Resolver<'b>,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-07-28 16:17:01 +00:00
|
|
|
impl<'a, 'b: 'a> ::std::ops::Deref for ImportResolver<'a, 'b> {
|
|
|
|
type Target = Resolver<'b>;
|
|
|
|
fn deref(&self) -> &Resolver<'b> {
|
|
|
|
self.resolver
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b: 'a> ::std::ops::DerefMut for ImportResolver<'a, 'b> {
|
|
|
|
fn deref_mut(&mut self) -> &mut Resolver<'b> {
|
|
|
|
self.resolver
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-20 08:32:15 +00:00
|
|
|
impl<'a, 'b: 'a> ty::DefIdTree for &'a ImportResolver<'a, 'b> {
|
|
|
|
fn parent(self, id: DefId) -> Option<DefId> {
|
|
|
|
self.resolver.parent(id)
|
2016-07-28 16:17:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-24 03:26:10 +00:00
|
|
|
impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
2015-03-16 10:44:19 +13:00
|
|
|
// Import resolution
|
|
|
|
//
|
|
|
|
// This is a fixed-point algorithm. We resolve imports until our efforts
|
|
|
|
// are stymied by an unresolved import; then we bail out of the current
|
|
|
|
// module and continue. We terminate successfully once no more imports
|
|
|
|
// remain or unsuccessfully when no forward progress in resolving imports
|
|
|
|
// is made.
|
|
|
|
|
|
|
|
/// Resolves all imports for the crate. This method performs the fixed-
|
|
|
|
/// point iteration.
|
2016-11-10 10:11:25 +00:00
|
|
|
pub fn resolve_imports(&mut self) {
|
2016-08-17 00:52:18 +00:00
|
|
|
let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
|
|
|
|
while self.indeterminate_imports.len() < prev_num_indeterminates {
|
|
|
|
prev_num_indeterminates = self.indeterminate_imports.len();
|
2016-11-10 10:11:25 +00:00
|
|
|
for import in mem::replace(&mut self.indeterminate_imports, Vec::new()) {
|
2016-08-17 00:52:18 +00:00
|
|
|
match self.resolve_import(&import) {
|
2016-11-26 12:21:47 +00:00
|
|
|
true => self.determined_imports.push(import),
|
|
|
|
false => self.indeterminate_imports.push(import),
|
2016-04-17 20:23:10 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2016-08-17 00:52:18 +00:00
|
|
|
}
|
2016-11-10 10:11:25 +00:00
|
|
|
}
|
2016-08-17 00:52:18 +00:00
|
|
|
|
2016-11-10 10:11:25 +00:00
|
|
|
pub fn finalize_imports(&mut self) {
|
2016-08-17 00:52:18 +00:00
|
|
|
for module in self.arenas.local_modules().iter() {
|
|
|
|
self.finalize_resolutions_in(module);
|
|
|
|
}
|
|
|
|
|
2016-08-18 03:39:48 +00:00
|
|
|
let mut errors = false;
|
2017-07-23 15:15:45 -07:00
|
|
|
let mut seen_spans = FxHashSet();
|
2016-08-15 08:19:09 +00:00
|
|
|
for i in 0 .. self.determined_imports.len() {
|
|
|
|
let import = self.determined_imports[i];
|
2017-07-23 15:15:45 -07:00
|
|
|
if let Some((span, err)) = self.finalize_import(import) {
|
2016-08-18 03:39:48 +00:00
|
|
|
errors = true;
|
|
|
|
|
2017-06-10 10:55:19 +01:00
|
|
|
if let SingleImport { source, ref result, .. } = import.subclass {
|
|
|
|
if source.name == "self" {
|
|
|
|
// Silence `unresolved import` error if E0429 is already emitted
|
|
|
|
match result.value_ns.get() {
|
|
|
|
Err(Determined) => continue,
|
|
|
|
_ => {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-18 03:39:48 +00:00
|
|
|
// If the error is a single failed import then create a "fake" import
|
|
|
|
// resolution for it so that later resolve stages won't complain.
|
|
|
|
self.import_dummy_binding(import);
|
2017-07-23 15:15:45 -07:00
|
|
|
if !seen_spans.contains(&span) {
|
|
|
|
let path = import_path_to_string(&import.module_path[..],
|
|
|
|
&import.subclass,
|
|
|
|
span);
|
|
|
|
let error = ResolutionError::UnresolvedImport(Some((span, &path, &err)));
|
|
|
|
resolve_error(self.resolver, span, error);
|
|
|
|
seen_spans.insert(span);
|
|
|
|
}
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-17 00:52:18 +00:00
|
|
|
// Report unresolved imports only if no hard error was already reported
|
|
|
|
// to avoid generating multiple errors on the same import.
|
2016-08-18 03:39:48 +00:00
|
|
|
if !errors {
|
2016-08-17 00:52:18 +00:00
|
|
|
if let Some(import) = self.indeterminate_imports.iter().next() {
|
|
|
|
let error = ResolutionError::UnresolvedImport(None);
|
|
|
|
resolve_error(self.resolver, import.span, error);
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2016-08-17 00:52:18 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-11-26 12:21:47 +00:00
|
|
|
/// Attempts to resolve the given import, returning true if its resolution is determined.
|
2015-03-16 10:44:19 +13:00
|
|
|
/// If successful, the resolved bindings are written into the module.
|
2016-11-26 12:21:47 +00:00
|
|
|
fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
|
2015-03-16 10:44:19 +13:00
|
|
|
debug!("(resolving import for module) resolving import `{}::...` in `{}`",
|
2017-07-23 15:15:45 -07:00
|
|
|
names_to_string(&directive.module_path[..]),
|
2018-01-16 14:47:14 -05:00
|
|
|
module_to_string(self.current_module).unwrap_or("???".to_string()));
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2016-08-22 00:24:11 +00:00
|
|
|
self.current_module = directive.parent;
|
2016-08-17 00:52:18 +00:00
|
|
|
|
2016-08-18 01:43:26 +00:00
|
|
|
let module = if let Some(module) = directive.imported_module.get() {
|
2016-08-18 00:11:56 +00:00
|
|
|
module
|
|
|
|
} else {
|
|
|
|
let vis = directive.vis.get();
|
|
|
|
// For better failure detection, pretend that the import will not define any names
|
|
|
|
// while resolving its module path.
|
2016-12-20 08:32:15 +00:00
|
|
|
directive.vis.set(ty::Visibility::Invisible);
|
2017-07-23 15:15:45 -07:00
|
|
|
let result = self.resolve_path(&directive.module_path[..], None, false, directive.span);
|
2016-08-18 00:11:56 +00:00
|
|
|
directive.vis.set(vis);
|
|
|
|
|
|
|
|
match result {
|
2016-11-25 06:07:21 +00:00
|
|
|
PathResult::Module(module) => module,
|
2016-11-26 12:21:47 +00:00
|
|
|
PathResult::Indeterminate => return false,
|
|
|
|
_ => return true,
|
2016-08-18 00:11:56 +00:00
|
|
|
}
|
2016-03-13 02:53:22 +00:00
|
|
|
};
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2016-08-18 01:43:26 +00:00
|
|
|
directive.imported_module.set(Some(module));
|
2016-12-12 03:35:48 +00:00
|
|
|
let (source, target, result, type_ns_only) = match directive.subclass {
|
|
|
|
SingleImport { source, target, ref result, type_ns_only } =>
|
|
|
|
(source, target, result, type_ns_only),
|
2016-08-15 08:19:09 +00:00
|
|
|
GlobImport { .. } => {
|
|
|
|
self.resolve_glob_import(directive);
|
2016-11-26 12:21:47 +00:00
|
|
|
return true;
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
2016-10-28 03:40:58 +00:00
|
|
|
_ => unreachable!(),
|
2016-02-13 21:49:16 +00:00
|
|
|
};
|
2016-02-07 23:58:14 +00:00
|
|
|
|
2016-08-15 08:19:09 +00:00
|
|
|
let mut indeterminate = false;
|
2016-12-12 03:35:48 +00:00
|
|
|
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
|
2016-11-10 06:19:54 +00:00
|
|
|
if let Err(Undetermined) = result[ns].get() {
|
2017-05-12 11:21:11 +02:00
|
|
|
result[ns].set(this.resolve_ident_in_module(module,
|
|
|
|
source,
|
|
|
|
ns,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
directive.span));
|
2016-08-17 20:48:53 +00:00
|
|
|
} else {
|
2016-11-10 06:19:54 +00:00
|
|
|
return
|
2016-08-17 20:48:53 +00:00
|
|
|
};
|
|
|
|
|
2016-11-29 02:53:00 +00:00
|
|
|
let parent = directive.parent;
|
2016-11-10 06:19:54 +00:00
|
|
|
match result[ns].get() {
|
2016-08-18 05:39:32 +00:00
|
|
|
Err(Undetermined) => indeterminate = true,
|
|
|
|
Err(Determined) => {
|
2016-11-29 02:53:00 +00:00
|
|
|
this.update_resolution(parent, target, ns, |_, resolution| {
|
2016-07-25 23:04:42 +00:00
|
|
|
resolution.single_imports.directive_failed()
|
|
|
|
});
|
|
|
|
}
|
2016-08-17 20:48:53 +00:00
|
|
|
Ok(binding) if !binding.is_importable() => {
|
2016-02-13 21:49:16 +00:00
|
|
|
let msg = format!("`{}` is not directly importable", target);
|
2016-11-10 06:19:54 +00:00
|
|
|
struct_span_err!(this.session, directive.span, E0253, "{}", &msg)
|
2017-05-04 14:17:23 +02:00
|
|
|
.span_label(directive.span, "cannot be imported directly")
|
2016-08-09 22:31:57 +01:00
|
|
|
.emit();
|
2016-07-13 01:36:09 -04:00
|
|
|
// Do not import this illegal binding. Import a dummy binding and pretend
|
|
|
|
// everything is fine
|
2016-11-10 06:19:54 +00:00
|
|
|
this.import_dummy_binding(directive);
|
2016-02-13 21:49:16 +00:00
|
|
|
}
|
2016-08-15 08:19:09 +00:00
|
|
|
Ok(binding) => {
|
2016-11-10 06:19:54 +00:00
|
|
|
let imported_binding = this.import(binding, directive);
|
2016-11-29 02:53:00 +00:00
|
|
|
let conflict = this.try_define(parent, target, ns, imported_binding);
|
2016-07-25 23:04:42 +00:00
|
|
|
if let Err(old_binding) = conflict {
|
2016-11-29 02:53:00 +00:00
|
|
|
this.report_conflict(parent, target, ns, imported_binding, old_binding);
|
2016-07-25 23:04:42 +00:00
|
|
|
}
|
2016-02-16 13:14:32 +00:00
|
|
|
}
|
2016-02-13 21:49:16 +00:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2016-11-26 12:21:47 +00:00
|
|
|
!indeterminate
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
|
|
|
|
2016-11-26 12:21:47 +00:00
|
|
|
// If appropriate, returns an error to report.
|
2017-07-23 15:15:45 -07:00
|
|
|
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> {
|
2016-08-22 00:24:11 +00:00
|
|
|
self.current_module = directive.parent;
|
2016-08-15 08:19:09 +00:00
|
|
|
let ImportDirective { ref module_path, span, .. } = *directive;
|
2017-12-10 03:30:47 +03:00
|
|
|
|
2018-01-01 17:42:32 +03:00
|
|
|
// FIXME: Last path segment is treated specially in import resolution, so extern crate
|
|
|
|
// mode for absolute paths needs some special support for single-segment imports.
|
|
|
|
if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() ||
|
|
|
|
module_path[0].node.name == keywords::Extern.name()) {
|
|
|
|
let is_extern = module_path[0].node.name == keywords::Extern.name() ||
|
2018-02-14 16:11:02 +01:00
|
|
|
self.session.features_untracked().extern_absolute_paths;
|
2017-12-10 03:30:47 +03:00
|
|
|
match directive.subclass {
|
2018-01-01 17:42:32 +03:00
|
|
|
GlobImport { .. } if is_extern => {
|
2017-12-10 03:30:47 +03:00
|
|
|
return Some((directive.span,
|
|
|
|
"cannot glob-import all possible crates".to_string()));
|
|
|
|
}
|
|
|
|
SingleImport { source, target, .. } => {
|
2018-01-01 17:42:32 +03:00
|
|
|
let crate_root = if source.name == keywords::Crate.name() &&
|
|
|
|
module_path[0].node.name != keywords::Extern.name() {
|
2017-12-10 03:30:47 +03:00
|
|
|
if target.name == keywords::Crate.name() {
|
|
|
|
return Some((directive.span,
|
|
|
|
"crate root imports need to be explicitly named: \
|
|
|
|
`use crate as name;`".to_string()));
|
|
|
|
} else {
|
2017-11-29 01:05:31 -08:00
|
|
|
Some(self.resolve_crate_root(source.ctxt.modern(), false))
|
2017-12-10 03:30:47 +03:00
|
|
|
}
|
2018-01-01 17:42:32 +03:00
|
|
|
} else if is_extern && !token::Ident(source).is_path_segment_keyword() {
|
2017-12-10 03:30:47 +03:00
|
|
|
let crate_id =
|
|
|
|
self.crate_loader.resolve_crate_from_path(source.name, directive.span);
|
|
|
|
let crate_root =
|
|
|
|
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
|
|
|
|
self.populate_module_if_necessary(crate_root);
|
|
|
|
Some(crate_root)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(crate_root) = crate_root {
|
|
|
|
let binding = (crate_root, ty::Visibility::Public, directive.span,
|
|
|
|
directive.expansion).to_name_binding(self.arenas);
|
|
|
|
let binding = self.arenas.alloc_name_binding(NameBinding {
|
|
|
|
kind: NameBindingKind::Import {
|
|
|
|
binding,
|
|
|
|
directive,
|
|
|
|
used: Cell::new(false),
|
|
|
|
legacy_self_import: false,
|
|
|
|
},
|
|
|
|
vis: directive.vis.get(),
|
|
|
|
span: directive.span,
|
|
|
|
expansion: directive.expansion,
|
|
|
|
});
|
|
|
|
let _ = self.try_define(directive.parent, target, TypeNS, binding);
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-12 11:21:11 +02:00
|
|
|
let module_result = self.resolve_path(&module_path, None, true, span);
|
2016-08-15 08:19:09 +00:00
|
|
|
let module = match module_result {
|
2016-11-25 06:07:21 +00:00
|
|
|
PathResult::Module(module) => module,
|
2017-11-19 17:05:29 +03:00
|
|
|
PathResult::Failed(span, msg, false) => {
|
|
|
|
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
PathResult::Failed(span, msg, true) => {
|
2016-12-05 03:51:11 +00:00
|
|
|
let (mut self_path, mut self_result) = (module_path.clone(), None);
|
2017-07-23 15:15:45 -07:00
|
|
|
if !self_path.is_empty() &&
|
2017-11-19 17:05:29 +03:00
|
|
|
!token::Ident(self_path[0].node).is_path_segment_keyword() &&
|
|
|
|
!(self_path.len() > 1 &&
|
|
|
|
token::Ident(self_path[1].node).is_path_segment_keyword())
|
2017-07-23 15:15:45 -07:00
|
|
|
{
|
|
|
|
self_path[0].node.name = keywords::SelfValue.name();
|
2017-05-12 11:21:11 +02:00
|
|
|
self_result = Some(self.resolve_path(&self_path, None, false, span));
|
2016-12-05 03:51:11 +00:00
|
|
|
}
|
|
|
|
return if let Some(PathResult::Module(..)) = self_result {
|
2017-07-23 15:15:45 -07:00
|
|
|
Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))
|
2016-09-05 23:08:21 -04:00
|
|
|
} else {
|
2017-07-23 15:15:45 -07:00
|
|
|
Some((span, msg))
|
2016-09-05 21:48:02 -04:00
|
|
|
};
|
|
|
|
},
|
2016-11-26 12:21:47 +00:00
|
|
|
_ => return None,
|
2016-08-15 08:19:09 +00:00
|
|
|
};
|
|
|
|
|
2016-12-12 03:35:48 +00:00
|
|
|
let (ident, result, type_ns_only) = match directive.subclass {
|
|
|
|
SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only),
|
2016-08-15 08:19:09 +00:00
|
|
|
GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
|
|
|
|
// Importing a module into itself is not allowed.
|
2017-07-23 15:15:45 -07:00
|
|
|
return Some((directive.span,
|
|
|
|
"Cannot glob-import a module into itself.".to_string()));
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
2016-08-20 00:23:32 +00:00
|
|
|
GlobImport { is_prelude, ref max_vis } => {
|
|
|
|
if !is_prelude &&
|
2016-12-20 08:32:15 +00:00
|
|
|
max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
|
|
|
|
!max_vis.get().is_at_least(directive.vis.get(), &*self) {
|
2016-08-20 00:23:32 +00:00
|
|
|
let msg = "A non-empty glob must import something with the glob's visibility";
|
|
|
|
self.session.span_err(directive.span, msg);
|
|
|
|
}
|
2016-11-26 12:21:47 +00:00
|
|
|
return None;
|
2016-08-20 00:23:32 +00:00
|
|
|
}
|
2016-10-28 03:40:58 +00:00
|
|
|
_ => unreachable!(),
|
2016-08-15 08:19:09 +00:00
|
|
|
};
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
let mut all_ns_err = true;
|
2017-01-10 05:15:02 +00:00
|
|
|
let mut legacy_self_import = None;
|
2016-12-12 03:35:48 +00:00
|
|
|
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
|
2016-11-10 06:19:54 +00:00
|
|
|
if let Ok(binding) = result[ns].get() {
|
|
|
|
all_ns_err = false;
|
2016-11-29 02:07:12 +00:00
|
|
|
if this.record_use(ident, ns, binding, directive.span) {
|
|
|
|
this.resolution(module, ident, ns).borrow_mut().binding =
|
2016-11-10 06:19:54 +00:00
|
|
|
Some(this.dummy_binding);
|
2016-08-20 05:23:19 +00:00
|
|
|
}
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
2017-05-12 11:21:11 +02:00
|
|
|
} else if let Ok(binding) = this.resolve_ident_in_module(module,
|
|
|
|
ident,
|
|
|
|
ns,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
directive.span) {
|
2017-01-10 05:15:02 +00:00
|
|
|
legacy_self_import = Some(directive);
|
|
|
|
let binding = this.arenas.alloc_name_binding(NameBinding {
|
|
|
|
kind: NameBindingKind::Import {
|
2017-08-06 22:54:09 -07:00
|
|
|
binding,
|
|
|
|
directive,
|
2017-01-10 05:15:02 +00:00
|
|
|
used: Cell::new(false),
|
|
|
|
legacy_self_import: true,
|
|
|
|
},
|
|
|
|
..*binding
|
|
|
|
});
|
|
|
|
let _ = this.try_define(directive.parent, ident, ns, binding);
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2016-08-15 08:19:09 +00:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
if all_ns_err {
|
2017-01-10 05:15:02 +00:00
|
|
|
if let Some(directive) = legacy_self_import {
|
|
|
|
self.warn_legacy_self_import(directive);
|
|
|
|
return None;
|
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
let mut all_ns_failed = true;
|
2016-12-12 03:35:48 +00:00
|
|
|
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
|
2017-05-12 11:21:11 +02:00
|
|
|
match this.resolve_ident_in_module(module, ident, ns, false, true, span) {
|
2016-11-26 12:21:47 +00:00
|
|
|
Ok(_) => all_ns_failed = false,
|
2016-11-10 06:19:54 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
});
|
2016-08-15 08:19:09 +00:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
return if all_ns_failed {
|
2016-08-15 08:19:09 +00:00
|
|
|
let resolutions = module.resolutions.borrow();
|
2016-11-29 02:07:12 +00:00
|
|
|
let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| {
|
|
|
|
if *i == ident { return None; } // Never suggest the same name
|
2016-03-31 04:44:04 +00:00
|
|
|
match *resolution.borrow() {
|
2017-02-02 22:05:49 +11:00
|
|
|
NameResolution { binding: Some(name_binding), .. } => {
|
|
|
|
match name_binding.kind {
|
|
|
|
NameBindingKind::Import { binding, .. } => {
|
|
|
|
match binding.kind {
|
|
|
|
// Never suggest the name that has binding error
|
|
|
|
// i.e. the name that cannot be previously resolved
|
|
|
|
NameBindingKind::Def(Def::Err) => return None,
|
|
|
|
_ => Some(&i.name),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => Some(&i.name),
|
|
|
|
}
|
|
|
|
},
|
2016-03-31 04:44:04 +00:00
|
|
|
NameResolution { single_imports: SingleImports::None, .. } => None,
|
2016-11-29 02:07:12 +00:00
|
|
|
_ => Some(&i.name),
|
2016-03-31 04:44:04 +00:00
|
|
|
}
|
|
|
|
});
|
2016-11-29 02:07:12 +00:00
|
|
|
let lev_suggestion =
|
|
|
|
match find_best_match_for_name(names, &ident.name.as_str(), None) {
|
|
|
|
Some(name) => format!(". Did you mean to use `{}`?", name),
|
|
|
|
None => "".to_owned(),
|
|
|
|
};
|
2016-08-15 08:19:09 +00:00
|
|
|
let module_str = module_to_string(module);
|
2018-01-16 14:47:14 -05:00
|
|
|
let msg = if let Some(module_str) = module_str {
|
2016-11-29 02:07:12 +00:00
|
|
|
format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
|
2018-01-16 14:47:14 -05:00
|
|
|
} else {
|
|
|
|
format!("no `{}` in the root{}", ident, lev_suggestion)
|
2016-04-09 01:06:57 +00:00
|
|
|
};
|
2017-07-23 15:15:45 -07:00
|
|
|
Some((span, msg))
|
2016-08-15 08:19:09 +00:00
|
|
|
} else {
|
2016-11-29 02:07:12 +00:00
|
|
|
// `resolve_ident_in_module` reported a privacy error.
|
2016-08-15 08:19:09 +00:00
|
|
|
self.import_dummy_binding(directive);
|
2016-11-26 12:21:47 +00:00
|
|
|
None
|
2016-07-25 23:04:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
let mut reexport_error = None;
|
|
|
|
let mut any_successful_reexport = false;
|
|
|
|
self.per_ns(|this, ns| {
|
|
|
|
if let Ok(binding) = result[ns].get() {
|
2016-08-19 22:52:26 +00:00
|
|
|
let vis = directive.vis.get();
|
2016-12-20 08:32:15 +00:00
|
|
|
if !binding.pseudo_vis().is_at_least(vis, &*this) {
|
2016-11-10 06:19:54 +00:00
|
|
|
reexport_error = Some((ns, binding));
|
2016-02-16 03:54:14 +00:00
|
|
|
} else {
|
2016-11-10 06:19:54 +00:00
|
|
|
any_successful_reexport = true;
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2016-01-14 01:42:45 +00:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2015-12-14 22:36:31 +05:30
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
// All namespaces must be re-exported with extra visibility for an error to occur.
|
|
|
|
if !any_successful_reexport {
|
2017-05-21 15:50:38 +03:00
|
|
|
let (ns, binding) = reexport_error.unwrap();
|
|
|
|
if ns == TypeNS && binding.is_extern_crate() {
|
2018-01-12 16:41:45 -05:00
|
|
|
let msg = format!("extern crate `{}` is private, and cannot be \
|
|
|
|
re-exported (error E0365), consider declaring with \
|
|
|
|
`pub`",
|
2017-05-21 15:50:38 +03:00
|
|
|
ident);
|
2017-07-26 21:51:09 -07:00
|
|
|
self.session.buffer_lint(PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
|
|
|
directive.id,
|
|
|
|
directive.span,
|
|
|
|
&msg);
|
2017-05-21 15:50:38 +03:00
|
|
|
} else if ns == TypeNS {
|
2016-11-10 06:19:54 +00:00
|
|
|
struct_span_err!(self.session, directive.span, E0365,
|
2018-01-12 16:41:45 -05:00
|
|
|
"`{}` is private, and cannot be re-exported", ident)
|
|
|
|
.span_label(directive.span, format!("re-export of private `{}`", ident))
|
2016-11-29 02:07:12 +00:00
|
|
|
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
|
2016-11-10 06:19:54 +00:00
|
|
|
.emit();
|
|
|
|
} else {
|
2018-01-12 16:41:45 -05:00
|
|
|
let msg = format!("`{}` is private, and cannot be re-exported", ident);
|
2016-11-10 06:19:54 +00:00
|
|
|
let note_msg =
|
2016-11-29 02:07:12 +00:00
|
|
|
format!("consider marking `{}` as `pub` in the imported module", ident);
|
2016-11-10 06:19:54 +00:00
|
|
|
struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
|
|
|
|
.span_note(directive.span, ¬e_msg)
|
|
|
|
.emit();
|
|
|
|
}
|
2016-01-14 01:42:45 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2016-02-07 23:06:10 +00:00
|
|
|
// 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.
|
2016-11-10 06:19:54 +00:00
|
|
|
self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() {
|
|
|
|
this.def_map.entry(directive.id).or_insert(PathResolution::new(binding.def()));
|
|
|
|
});
|
2015-03-16 10:44:19 +13:00
|
|
|
|
|
|
|
debug!("(resolving single import) successfully resolved import");
|
2016-11-26 12:21:47 +00:00
|
|
|
None
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-08-15 08:19:09 +00:00
|
|
|
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
|
2016-08-18 01:43:26 +00:00
|
|
|
let module = directive.imported_module.get().unwrap();
|
|
|
|
self.populate_module_if_necessary(module);
|
2016-08-15 08:19:09 +00:00
|
|
|
|
2016-09-18 09:45:06 +00:00
|
|
|
if let Some(Def::Trait(_)) = module.def() {
|
2016-07-28 16:17:01 +00:00
|
|
|
self.session.span_err(directive.span, "items in traits are not importable.");
|
2016-08-19 21:46:28 +00:00
|
|
|
return;
|
|
|
|
} else if module.def_id() == directive.parent.def_id() {
|
2016-08-15 08:19:09 +00:00
|
|
|
return;
|
2016-08-20 00:23:32 +00:00
|
|
|
} else if let GlobImport { is_prelude: true, .. } = directive.subclass {
|
2016-08-18 01:43:26 +00:00
|
|
|
self.prelude = Some(module);
|
2016-08-15 08:19:09 +00:00
|
|
|
return;
|
2016-03-09 01:46:46 +00:00
|
|
|
}
|
|
|
|
|
2016-08-18 01:43:26 +00:00
|
|
|
// Add to module's glob_importers
|
|
|
|
module.glob_importers.borrow_mut().push(directive);
|
2016-02-16 03:54:14 +00:00
|
|
|
|
2016-07-28 02:34:01 +00:00
|
|
|
// Ensure that `resolutions` isn't borrowed during `try_define`,
|
2016-04-11 18:30:48 +00:00
|
|
|
// since it might get updated via a glob cycle.
|
2016-11-29 02:07:12 +00:00
|
|
|
let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| {
|
|
|
|
resolution.borrow().binding().map(|binding| (ident, binding))
|
2016-04-07 22:14:44 +00:00
|
|
|
}).collect::<Vec<_>>();
|
2017-03-22 08:39:51 +00:00
|
|
|
for ((mut ident, ns), binding) in bindings {
|
|
|
|
let scope = match ident.ctxt.reverse_glob_adjust(module.expansion,
|
2017-07-31 23:04:34 +03:00
|
|
|
directive.span.ctxt().modern()) {
|
2017-03-22 08:39:51 +00:00
|
|
|
Some(Some(def)) => self.macro_def_scope(def),
|
|
|
|
Some(None) => self.current_module,
|
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
if self.is_accessible_from(binding.pseudo_vis(), scope) {
|
2016-07-31 04:53:04 +00:00
|
|
|
let imported_binding = self.import(binding, directive);
|
2016-11-29 02:07:12 +00:00
|
|
|
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
2016-02-07 23:58:14 +00:00
|
|
|
}
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
|
|
|
|
// Record the destination of this import
|
2016-12-01 01:35:25 +03:00
|
|
|
self.record_def(directive.id, PathResolution::new(module.def().unwrap()));
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2018-01-12 16:41:25 -05:00
|
|
|
// Miscellaneous post-processing, including recording re-exports,
|
2017-05-21 14:11:08 +03:00
|
|
|
// reporting conflicts, and reporting unresolved imports.
|
2016-08-17 00:52:18 +00:00
|
|
|
fn finalize_resolutions_in(&mut self, module: Module<'b>) {
|
2016-02-16 03:54:14 +00:00
|
|
|
// Since import resolution is finished, globs will not define any more names.
|
2016-03-17 11:05:09 +00:00
|
|
|
*module.globs.borrow_mut() = Vec::new();
|
2016-02-16 03:54:14 +00:00
|
|
|
|
|
|
|
let mut reexports = Vec::new();
|
2017-03-14 05:16:54 +00:00
|
|
|
let mut exported_macro_names = FxHashMap();
|
2016-10-28 06:52:45 +00:00
|
|
|
if module as *const _ == self.graph_root as *const _ {
|
2017-03-14 05:16:54 +00:00
|
|
|
let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
|
|
|
|
for export in macro_exports.into_iter().rev() {
|
2017-03-27 00:46:00 +00:00
|
|
|
if exported_macro_names.insert(export.ident.modern(), export.span).is_none() {
|
2017-01-03 00:36:34 +00:00
|
|
|
reexports.push(export);
|
|
|
|
}
|
|
|
|
}
|
2016-10-28 06:52:45 +00:00
|
|
|
}
|
|
|
|
|
2016-11-29 02:07:12 +00:00
|
|
|
for (&(ident, ns), resolution) in module.resolutions.borrow().iter() {
|
2016-12-09 11:08:39 +00:00
|
|
|
let resolution = &mut *resolution.borrow_mut();
|
2016-02-16 03:54:14 +00:00
|
|
|
let binding = match resolution.binding {
|
|
|
|
Some(binding) => binding,
|
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
|
2017-11-29 11:20:49 -08:00
|
|
|
if binding.is_import() || binding.is_macro_def() {
|
2016-08-20 05:23:19 +00:00
|
|
|
let def = binding.def();
|
|
|
|
if def != Def::Err {
|
2016-11-27 02:57:15 +00:00
|
|
|
if !def.def_id().is_local() {
|
2017-09-05 16:48:24 +02:00
|
|
|
self.cstore.export_macros_untracked(def.def_id().krate);
|
2016-11-27 02:57:15 +00:00
|
|
|
}
|
2017-03-14 05:16:54 +00:00
|
|
|
if let Def::Macro(..) = def {
|
2017-03-27 00:46:00 +00:00
|
|
|
if let Some(&span) = exported_macro_names.get(&ident.modern()) {
|
2017-03-14 05:16:54 +00:00
|
|
|
let msg =
|
|
|
|
format!("a macro named `{}` has already been exported", ident);
|
|
|
|
self.session.struct_span_err(span, &msg)
|
2017-05-04 14:17:23 +02:00
|
|
|
.span_label(span, format!("`{}` already exported", ident))
|
2017-03-14 05:16:54 +00:00
|
|
|
.span_note(binding.span, "previous macro export here")
|
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
}
|
2017-11-29 11:20:49 -08:00
|
|
|
reexports.push(Export {
|
|
|
|
ident: ident.modern(),
|
|
|
|
def: def,
|
|
|
|
span: binding.span,
|
|
|
|
vis: binding.vis,
|
2017-12-04 21:17:42 -08:00
|
|
|
is_import: true,
|
2017-11-29 11:20:49 -08:00
|
|
|
});
|
2016-08-20 05:23:19 +00:00
|
|
|
}
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
|
|
|
|
2016-12-09 11:08:39 +00:00
|
|
|
match binding.kind {
|
2017-11-24 11:21:43 -08:00
|
|
|
NameBindingKind::Import { binding: orig_binding, directive, .. } => {
|
2016-12-09 11:08:39 +00:00
|
|
|
if ns == TypeNS && orig_binding.is_variant() &&
|
2017-11-24 11:21:43 -08:00
|
|
|
!orig_binding.vis.is_at_least(binding.vis, &*self) {
|
|
|
|
let msg = match directive.subclass {
|
|
|
|
ImportDirectiveSubclass::SingleImport { .. } => {
|
2018-01-12 16:41:45 -05:00
|
|
|
format!("variant `{}` is private and cannot be re-exported",
|
2017-11-24 11:21:43 -08:00
|
|
|
ident)
|
|
|
|
},
|
|
|
|
ImportDirectiveSubclass::GlobImport { .. } => {
|
|
|
|
let msg = "enum is private and its variants \
|
2018-01-12 16:41:45 -05:00
|
|
|
cannot be re-exported".to_owned();
|
2017-11-24 11:21:43 -08:00
|
|
|
let error_id = (DiagnosticMessageId::ErrorId(0), // no code?!
|
|
|
|
Some(binding.span),
|
|
|
|
msg.clone());
|
|
|
|
let fresh = self.session.one_time_diagnostics
|
|
|
|
.borrow_mut().insert(error_id);
|
|
|
|
if !fresh {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
msg
|
|
|
|
},
|
|
|
|
ref s @ _ => bug!("unexpected import subclass {:?}", s)
|
|
|
|
};
|
|
|
|
let mut err = self.session.struct_span_err(binding.span, &msg);
|
|
|
|
|
|
|
|
let imported_module = directive.imported_module.get()
|
|
|
|
.expect("module should exist");
|
|
|
|
let resolutions = imported_module.parent.expect("parent should exist")
|
|
|
|
.resolutions.borrow();
|
|
|
|
let enum_path_segment_index = directive.module_path.len() - 1;
|
|
|
|
let enum_ident = directive.module_path[enum_path_segment_index].node;
|
|
|
|
|
|
|
|
let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
|
|
|
|
.expect("resolution should exist");
|
|
|
|
let enum_span = enum_resolution.borrow()
|
|
|
|
.binding.expect("binding should exist")
|
|
|
|
.span;
|
|
|
|
let enum_def_span = self.session.codemap().def_span(enum_span);
|
|
|
|
let enum_def_snippet = self.session.codemap()
|
|
|
|
.span_to_snippet(enum_def_span).expect("snippet should exist");
|
|
|
|
// potentially need to strip extant `crate`/`pub(path)` for suggestion
|
|
|
|
let after_vis_index = enum_def_snippet.find("enum")
|
|
|
|
.expect("`enum` keyword should exist in snippet");
|
|
|
|
let suggestion = format!("pub {}",
|
|
|
|
&enum_def_snippet[after_vis_index..]);
|
|
|
|
|
|
|
|
self.session
|
|
|
|
.diag_span_suggestion_once(&mut err,
|
|
|
|
DiagnosticMessageId::ErrorId(0),
|
|
|
|
enum_def_span,
|
|
|
|
"consider making the enum public",
|
|
|
|
suggestion);
|
|
|
|
err.emit();
|
2016-12-09 11:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
NameBindingKind::Ambiguity { b1, b2, .. }
|
|
|
|
if b1.is_glob_import() && b2.is_glob_import() => {
|
|
|
|
let (orig_b1, orig_b2) = match (&b1.kind, &b2.kind) {
|
|
|
|
(&NameBindingKind::Import { binding: b1, .. },
|
|
|
|
&NameBindingKind::Import { binding: b2, .. }) => (b1, b2),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
let (b1, b2) = match (orig_b1.vis, orig_b2.vis) {
|
|
|
|
(ty::Visibility::Public, ty::Visibility::Public) => continue,
|
|
|
|
(ty::Visibility::Public, _) => (b1, b2),
|
|
|
|
(_, ty::Visibility::Public) => (b2, b1),
|
|
|
|
_ => continue,
|
|
|
|
};
|
|
|
|
resolution.binding = Some(self.arenas.alloc_name_binding(NameBinding {
|
|
|
|
kind: NameBindingKind::Ambiguity { b1: b1, b2: b2, legacy: true }, ..*b1
|
|
|
|
}));
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
2016-12-09 11:08:39 +00:00
|
|
|
_ => {}
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if reexports.len() > 0 {
|
|
|
|
if let Some(def_id) = module.def_id() {
|
2017-09-08 13:51:57 -07:00
|
|
|
self.export_map.insert(def_id, reexports);
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2017-07-23 15:15:45 -07:00
|
|
|
fn import_path_to_string(names: &[SpannedIdent],
|
|
|
|
subclass: &ImportDirectiveSubclass,
|
|
|
|
span: Span) -> String {
|
|
|
|
let pos = names.iter()
|
|
|
|
.position(|p| span == p.span && p.node.name != keywords::CrateRoot.name());
|
|
|
|
let global = !names.is_empty() && names[0].node.name == keywords::CrateRoot.name();
|
|
|
|
if let Some(pos) = pos {
|
|
|
|
let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
|
|
|
|
names_to_string(names)
|
2015-03-16 10:44:19 +13:00
|
|
|
} else {
|
2017-07-23 15:15:45 -07:00
|
|
|
let names = if global { &names[1..] } else { names };
|
|
|
|
if names.is_empty() {
|
|
|
|
import_directive_subclass_to_string(subclass)
|
|
|
|
} else {
|
2018-02-11 05:05:11 +08:00
|
|
|
// FIXME: Remove this entire logic after #48116 is fixed.
|
|
|
|
//
|
2018-02-10 07:03:35 -08:00
|
|
|
// Note that this code looks a little wonky, it's currently here to
|
|
|
|
// hopefully help debug #48116, but otherwise isn't intended to
|
|
|
|
// cause any problems.
|
|
|
|
let x = format!(
|
|
|
|
"{}::{}",
|
|
|
|
names_to_string(names),
|
|
|
|
import_directive_subclass_to_string(subclass),
|
|
|
|
);
|
2018-02-11 05:05:11 +08:00
|
|
|
if names.is_empty() || x.starts_with("::") {
|
|
|
|
span_bug!(
|
|
|
|
span,
|
|
|
|
"invalid name `{}` at {:?}; global = {}, names = {:?}, subclass = {:?}",
|
|
|
|
x,
|
|
|
|
span,
|
|
|
|
global,
|
|
|
|
names,
|
|
|
|
subclass
|
|
|
|
);
|
|
|
|
}
|
rustc: Upgrade to LLVM 6
The following submodules have been updated for a new version of LLVM:
- `src/llvm`
- `src/libcompiler_builtins` - transitively contains compiler-rt
- `src/dlmalloc`
This also updates the docker container for dist-i686-freebsd as the old 16.04
container is no longer capable of building LLVM. The
compiler-rt/compiler-builtins and dlmalloc updates are pretty routine without
much interesting happening, but the LLVM update here is of particular note.
Unlike previous updates I haven't cherry-picked all existing patches we had on
top of our LLVM branch as we have a [huge amount][patches4] and have at this
point forgotten what most of them are for. Instead I started from the current
`release_60` branch in LLVM and only applied patches that were necessary to get
our tests working and building.
The current set of custom rustc-specific patches included in this LLVM update are:
* rust-lang/llvm@1187443 - this is how we actually implement
`cfg(target_feature)` for now and continues to not be upstreamed. While a
hazard for SIMD stabilization this commit is otherwise keeping the status
quo of a small rustc-specific feature.
* rust-lang/llvm@013f2ec - this is a rustc-specific optimization that we haven't
upstreamed, notably teaching LLVM about our allocation-related routines (which
aren't malloc/free). Once we stabilize the global allocator routines we will
likely want to upstream this patch, but for now it seems reasonable to keep it
on our fork.
* rust-lang/llvm@a65bbfd - I found this necessary to fix compilation of LLVM in
our 32-bit linux container. I'm not really sure why it's necessary but my
guess is that it's because of the absolutely ancient glibc that we're using.
In any case it's only updating pieces we're not actually using in LLVM so I'm
hoping it'll turn out alright. This doesn't seem like something we'll want to
upstream.c
* rust-lang/llvm@77ab1f0 - this is what's actually enabling LLVM to build in our
i686-freebsd container, I'm not really sure what's going on but we for sure
probably don't want to upstream this and otherwise it seems not too bad for
now at least.
* rust-lang/llvm@9eb9267 - we currently suffer on MSVC from an [upstream bug]
which although diagnosed to a particular revision isn't currently fixed
upstream (and the bug itself doesn't seem too active). This commit is a
partial revert of the suspected cause of this regression (found via a
bisection). I'm sort of hoping that this eventually gets fixed upstream with a
similar fix (which we can replace in our branch), but for now I'm also hoping
it's a relatively harmless change to have.
After applying these patches (plus one [backport] which should be [backported
upstream][llvm-back]) I believe we should have all tests working on all
platforms in our current test suite. I'm like 99% sure that we'll need some more
backports as issues are reported for LLVM 6 when this propagates through
nightlies, but that's sort of just par for the course nowadays!
In any case though some extra scrutiny of the patches here would definitely be
welcome, along with scrutiny of the "missing patches" like a [change to pass
manager order](rust-lang/llvm@27174447533), [another change to pass manager
order](rust-lang/llvm@c782febb7b9), some [compile fixes for
sparc](rust-lang/llvm@1a83de63c42), and some [fixes for
solaris](rust-lang/llvm@c2bfe0abb).
[patches4]: https://github.com/rust-lang/llvm/compare/5401fdf23...rust-llvm-release-4-0-1
[backport]: https://github.com/rust-lang/llvm/commit/5c54c252db
[llvm-back]: https://bugs.llvm.org/show_bug.cgi?id=36114
[upstream bug]: https://bugs.llvm.org/show_bug.cgi?id=36096
---
The update to LLVM 6 is desirable for a number of reasons, notably:
* This'll allow us to keep up with the upstream wasm backend, picking up new
features as they start landing.
* Upstream LLVM has fixed a number of SIMD-related compilation errors,
especially around AVX-512 and such.
* There's a few assorted known bugs which are fixed in LLVM 5 and aren't fixed
in the LLVM 4 branch we're using.
* Overall it's not a great idea to stagnate with our codegen backend!
This update is mostly powered by #47730 which is allowing us to update LLVM
*independent* of the version of LLVM that Emscripten is locked to. This means
that when compiling code for Emscripten we'll still be using the old LLVM 4
backend, but when compiling code for any other target we'll be using the new
LLVM 6 target. Once Emscripten updates we may no longer need this distinction,
but we're not sure when that will happen!
Closes #43370
Closes #43418
Closes #47015
Closes #47683
Closes rust-lang-nursery/stdsimd#157
Closes rust-lang-nursery/rust-wasm#3
2018-01-22 14:23:30 -08:00
|
|
|
return x
|
2017-07-23 15:15:45 -07:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-15 02:22:59 +00:00
|
|
|
fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass) -> String {
|
|
|
|
match *subclass {
|
2016-02-13 21:49:16 +00:00
|
|
|
SingleImport { source, .. } => source.to_string(),
|
2016-04-17 19:23:25 +00:00
|
|
|
GlobImport { .. } => "*".to_string(),
|
2017-11-07 18:01:35 -08:00
|
|
|
ExternCrate(_) => "<extern crate>".to_string(),
|
2017-01-14 08:58:50 +00:00
|
|
|
MacroUse => "#[macro_use]".to_string(),
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
}
|