rustc_resolve: fix special-case for one-segment import paths.

This commit is contained in:
Eduard-Mihai Burtescu 2018-08-09 16:29:22 +03:00
parent cd47831bf0
commit f9b1176eef
17 changed files with 433 additions and 238 deletions

View file

@ -1139,32 +1139,4 @@ impl<'a> CrateLoader<'a> {
cnum cnum
} }
pub fn process_use_extern(
&mut self,
name: Symbol,
span: Span,
id: ast::NodeId,
definitions: &Definitions,
) -> CrateNum {
let cnum = self.resolve_crate(
&None, name, name, None, None, span, PathKind::Crate, DepKind::Explicit
).0;
let def_id = definitions.opt_local_def_id(id).unwrap();
let path_len = definitions.def_path(def_id.index).data.len();
self.update_extern_crate(
cnum,
ExternCrate {
src: ExternCrateSource::Use,
span,
path_len,
direct: true,
},
&mut FxHashSet(),
);
cnum
}
} }

View file

@ -17,7 +17,7 @@ use macros::{InvocationData, LegacyScope};
use resolve_imports::ImportDirective; use resolve_imports::ImportDirective;
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
use {PerNS, Resolver, ResolverArenas}; use {ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas};
use Namespace::{self, TypeNS, ValueNS, MacroNS}; use Namespace::{self, TypeNS, ValueNS, MacroNS};
use {resolve_error, resolve_struct_error, ResolutionError}; use {resolve_error, resolve_struct_error, ResolutionError};
@ -175,7 +175,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
ModuleKind::Def(_, name) => name, ModuleKind::Def(_, name) => name,
ModuleKind::Block(..) => unreachable!(), ModuleKind::Block(..) => unreachable!(),
}; };
source.name = crate_name; // HACK(eddyb) unclear how good this is, but keeping `$crate`
// in `source` breaks `src/test/compile-fail/import-crate-var.rs`,
// while the current crate doesn't have a valid `crate_name`.
if crate_name != keywords::Invalid.name() {
source.name = crate_name;
}
if rename.is_none() { if rename.is_none() {
ident.name = crate_name; ident.name = crate_name;
} }
@ -187,6 +192,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
} }
} }
if ident.name == keywords::Crate.name() {
self.session.span_err(ident.span,
"crate root imports need to be explicitly named: \
`use crate as name;`");
}
let subclass = SingleImport { let subclass = SingleImport {
target: ident, target: ident,
source, source,
@ -299,7 +310,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
root_id: item.id, root_id: item.id,
id: item.id, id: item.id,
parent, parent,
imported_module: Cell::new(Some(module)), imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
subclass: ImportDirectiveSubclass::ExternCrate(orig_name), subclass: ImportDirectiveSubclass::ExternCrate(orig_name),
root_span: item.span, root_span: item.span,
span: item.span, span: item.span,
@ -701,7 +712,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
root_id: item.id, root_id: item.id,
id: item.id, id: item.id,
parent: graph_root, parent: graph_root,
imported_module: Cell::new(Some(module)), imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
subclass: ImportDirectiveSubclass::MacroUse, subclass: ImportDirectiveSubclass::MacroUse,
root_span: span, root_span: span,
span, span,
@ -721,7 +732,13 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
} else { } else {
for (name, span) in legacy_imports.imports { for (name, span) in legacy_imports.imports {
let ident = Ident::with_empty_ctxt(name); let ident = Ident::with_empty_ctxt(name);
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, span); let result = self.resolve_ident_in_module(
ModuleOrUniformRoot::Module(module),
ident,
MacroNS,
false,
span,
);
if let Ok(binding) = result { if let Ok(binding) = result {
let directive = macro_use_directive(span); let directive = macro_use_directive(span);
self.potentially_unused_imports.push(directive); self.potentially_unused_imports.push(directive);

View file

@ -953,9 +953,20 @@ impl<'a> LexicalScopeBinding<'a> {
} }
} }
#[derive(Copy, Clone, Debug)]
pub enum ModuleOrUniformRoot<'a> {
/// Regular module.
Module(Module<'a>),
/// The `{{root}}` (`CrateRoot` aka "global") / `extern` initial segment
/// in which external crates resolve, and also `crate` (only in `{{root}}`,
/// but *not* `extern`), in the Rust 2018 edition.
UniformRoot(Name),
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum PathResult<'a> { enum PathResult<'a> {
Module(Module<'a>), Module(ModuleOrUniformRoot<'a>),
NonModule(PathResolution), NonModule(PathResolution),
Indeterminate, Indeterminate,
Failed(Span, String, bool /* is the error from the last segment? */), Failed(Span, String, bool /* is the error from the last segment? */),
@ -1583,11 +1594,13 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
let hir::Path { ref segments, span, ref mut def } = *path; let hir::Path { ref segments, span, ref mut def } = *path;
let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect(); let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
// FIXME (Manishearth): Intra doc links won't get warned of epoch changes // FIXME (Manishearth): Intra doc links won't get warned of epoch changes
match self.resolve_path(&path, Some(namespace), true, span, CrateLint::No) { match self.resolve_path(None, &path, Some(namespace), true, span, CrateLint::No) {
PathResult::Module(module) => *def = module.def().unwrap(), PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
*def = module.def().unwrap(),
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
*def = path_res.base_def(), *def = path_res.base_def(),
PathResult::NonModule(..) => match self.resolve_path( PathResult::NonModule(..) => match self.resolve_path(
None,
&path, &path,
None, None,
true, true,
@ -1599,6 +1612,7 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
} }
_ => {} _ => {}
}, },
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
PathResult::Indeterminate => unreachable!(), PathResult::Indeterminate => unreachable!(),
PathResult::Failed(span, msg, _) => { PathResult::Failed(span, msg, _) => {
error_callback(self, span, ResolutionError::FailedToResolve(&msg)); error_callback(self, span, ResolutionError::FailedToResolve(&msg));
@ -1881,7 +1895,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}; };
let item = self.resolve_ident_in_module_unadjusted( let item = self.resolve_ident_in_module_unadjusted(
module, ident, ns, false, record_used, path_span, ModuleOrUniformRoot::Module(module),
ident,
ns,
false,
record_used,
path_span,
); );
if let Ok(binding) = item { if let Ok(binding) = item {
// The ident resolves to an item. // The ident resolves to an item.
@ -1906,7 +1925,12 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
let orig_current_module = self.current_module; let orig_current_module = self.current_module;
self.current_module = module; // Lexical resolutions can never be a privacy error. self.current_module = module; // Lexical resolutions can never be a privacy error.
let result = self.resolve_ident_in_module_unadjusted( let result = self.resolve_ident_in_module_unadjusted(
module, ident, ns, false, record_used, path_span, ModuleOrUniformRoot::Module(module),
ident,
ns,
false,
record_used,
path_span,
); );
self.current_module = orig_current_module; self.current_module = orig_current_module;
@ -1954,8 +1978,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
return Some(LexicalScopeBinding::Item(binding)); return Some(LexicalScopeBinding::Item(binding));
} }
if let Some(prelude) = self.prelude { if let Some(prelude) = self.prelude {
if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns, if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
false, false, path_span) { ModuleOrUniformRoot::Module(prelude),
ident,
ns,
false,
false,
path_span,
) {
return Some(LexicalScopeBinding::Item(binding)); return Some(LexicalScopeBinding::Item(binding));
} }
} }
@ -2013,7 +2043,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
} }
fn resolve_ident_in_module(&mut self, fn resolve_ident_in_module(&mut self,
module: Module<'a>, module: ModuleOrUniformRoot<'a>,
mut ident: Ident, mut ident: Ident,
ns: Namespace, ns: Namespace,
record_used: bool, record_used: bool,
@ -2021,8 +2051,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
-> Result<&'a NameBinding<'a>, Determinacy> { -> Result<&'a NameBinding<'a>, Determinacy> {
ident.span = ident.span.modern(); ident.span = ident.span.modern();
let orig_current_module = self.current_module; let orig_current_module = self.current_module;
if let Some(def) = ident.span.adjust(module.expansion) { if let ModuleOrUniformRoot::Module(module) = module {
self.current_module = self.macro_def_scope(def); if let Some(def) = ident.span.adjust(module.expansion) {
self.current_module = self.macro_def_scope(def);
}
} }
let result = self.resolve_ident_in_module_unadjusted( let result = self.resolve_ident_in_module_unadjusted(
module, ident, ns, false, record_used, span, module, ident, ns, false, record_used, span,
@ -2410,13 +2442,16 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
if def != Def::Err { if def != Def::Err {
new_id = Some(def.def_id()); new_id = Some(def.def_id());
let span = trait_ref.path.span; let span = trait_ref.path.span;
if let PathResult::Module(module) = self.resolve_path( if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
&path, self.resolve_path(
None, None,
false, &path,
span, None,
CrateLint::SimplePath(trait_ref.ref_id), false,
) { span,
CrateLint::SimplePath(trait_ref.ref_id),
)
{
new_val = Some((module, trait_ref.clone())); new_val = Some((module, trait_ref.clone()));
} }
} }
@ -2533,7 +2568,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// If there is a TraitRef in scope for an impl, then the method must be in the // If there is a TraitRef in scope for an impl, then the method must be in the
// trait. // trait.
if let Some((module, _)) = self.current_trait_ref { if let Some((module, _)) = self.current_trait_ref {
if self.resolve_ident_in_module(module, ident, ns, false, span).is_err() { if self.resolve_ident_in_module(
ModuleOrUniformRoot::Module(module),
ident,
ns,
false,
span,
).is_err() {
let path = &self.current_trait_ref.as_ref().unwrap().1.path; let path = &self.current_trait_ref.as_ref().unwrap().1.path;
resolve_error(self, span, err(ident.name, &path_names_to_string(path))); resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
} }
@ -2908,9 +2949,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
(String::new(), "the crate root".to_string()) (String::new(), "the crate root".to_string())
} else { } else {
let mod_path = &path[..path.len() - 1]; let mod_path = &path[..path.len() - 1];
let mod_prefix = match this.resolve_path(mod_path, Some(TypeNS), let mod_prefix = match this.resolve_path(None, mod_path, Some(TypeNS),
false, span, CrateLint::No) { false, span, CrateLint::No) {
PathResult::Module(module) => module.def(), PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
module.def(),
_ => None, _ => None,
}.map_or(String::new(), |def| format!("{} ", def.kind_name())); }.map_or(String::new(), |def| format!("{} ", def.kind_name()));
(mod_prefix, format!("`{}`", names_to_string(mod_path))) (mod_prefix, format!("`{}`", names_to_string(mod_path)))
@ -3319,6 +3361,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
} }
let result = match self.resolve_path( let result = match self.resolve_path(
None,
&path, &path,
Some(ns), Some(ns),
true, true,
@ -3326,7 +3369,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
crate_lint, crate_lint,
) { ) {
PathResult::NonModule(path_res) => path_res, PathResult::NonModule(path_res) => path_res,
PathResult::Module(module) if !module.is_normal() => { PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
PathResolution::new(module.def().unwrap()) PathResolution::new(module.def().unwrap())
} }
// In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we
@ -3341,18 +3384,21 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// //
// Such behavior is required for backward compatibility. // Such behavior is required for backward compatibility.
// The same fallback is used when `a` resolves to nothing. // The same fallback is used when `a` resolves to nothing.
PathResult::Module(..) | PathResult::Failed(..) PathResult::Module(ModuleOrUniformRoot::Module(_)) |
PathResult::Failed(..)
if (ns == TypeNS || path.len() > 1) && if (ns == TypeNS || path.len() > 1) &&
self.primitive_type_table.primitive_types self.primitive_type_table.primitive_types
.contains_key(&path[0].name) => { .contains_key(&path[0].name) => {
let prim = self.primitive_type_table.primitive_types[&path[0].name]; let prim = self.primitive_type_table.primitive_types[&path[0].name];
PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1) PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
} }
PathResult::Module(module) => PathResolution::new(module.def().unwrap()), PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
PathResolution::new(module.def().unwrap()),
PathResult::Failed(span, msg, false) => { PathResult::Failed(span, msg, false) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
err_path_resolution() err_path_resolution()
} }
PathResult::Module(ModuleOrUniformRoot::UniformRoot(_)) |
PathResult::Failed(..) => return None, PathResult::Failed(..) => return None,
PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"), PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
}; };
@ -3362,6 +3408,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
path[0].name != keywords::DollarCrate.name() { path[0].name != keywords::DollarCrate.name() {
let unqualified_result = { let unqualified_result = {
match self.resolve_path( match self.resolve_path(
None,
&[*path.last().unwrap()], &[*path.last().unwrap()],
Some(ns), Some(ns),
false, false,
@ -3369,7 +3416,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
CrateLint::No, CrateLint::No,
) { ) {
PathResult::NonModule(path_res) => path_res.base_def(), PathResult::NonModule(path_res) => path_res.base_def(),
PathResult::Module(module) => module.def().unwrap(), PathResult::Module(ModuleOrUniformRoot::Module(module)) =>
module.def().unwrap(),
_ => return Some(result), _ => return Some(result),
} }
}; };
@ -3384,13 +3432,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
fn resolve_path( fn resolve_path(
&mut self, &mut self,
base_module: Option<ModuleOrUniformRoot<'a>>,
path: &[Ident], path: &[Ident],
opt_ns: Option<Namespace>, // `None` indicates a module path opt_ns: Option<Namespace>, // `None` indicates a module path
record_used: bool, record_used: bool,
path_span: Span, path_span: Span,
crate_lint: CrateLint, crate_lint: CrateLint,
) -> PathResult<'a> { ) -> PathResult<'a> {
let mut module = None; let mut module = base_module;
let mut allow_super = true; let mut allow_super = true;
let mut second_binding = None; let mut second_binding = None;
@ -3412,49 +3461,48 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() { if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
let mut ctxt = ident.span.ctxt().modern(); let mut ctxt = ident.span.ctxt().modern();
module = Some(self.resolve_self(&mut ctxt, self.current_module)); module = Some(ModuleOrUniformRoot::Module(
self.resolve_self(&mut ctxt, self.current_module)));
continue continue
} else if allow_super && ns == TypeNS && name == keywords::Super.name() { } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
let mut ctxt = ident.span.ctxt().modern(); let mut ctxt = ident.span.ctxt().modern();
let self_module = match i { let self_module_parent = match i {
0 => self.resolve_self(&mut ctxt, self.current_module), 0 => self.resolve_self(&mut ctxt, self.current_module).parent,
_ => module.unwrap(), _ => match module {
Some(ModuleOrUniformRoot::Module(module)) => module.parent,
_ => None,
},
}; };
if let Some(parent) = self_module.parent { if let Some(parent) = self_module_parent {
module = Some(self.resolve_self(&mut ctxt, parent)); module = Some(ModuleOrUniformRoot::Module(
self.resolve_self(&mut ctxt, parent)));
continue continue
} else { } else {
let msg = "There are too many initial `super`s.".to_string(); let msg = "There are too many initial `super`s.".to_string();
return PathResult::Failed(ident.span, msg, false); return PathResult::Failed(ident.span, msg, false);
} }
} else if i == 0 && ns == TypeNS && name == keywords::Extern.name() {
continue;
} }
allow_super = false; allow_super = false;
if ns == TypeNS { if ns == TypeNS {
if i == 0 {
if name == keywords::Extern.name() ||
name == keywords::CrateRoot.name() &&
self.session.features_untracked().extern_absolute_paths &&
self.session.rust_2018() {
module = Some(ModuleOrUniformRoot::UniformRoot(name));
continue;
}
}
if (i == 0 && name == keywords::CrateRoot.name()) || if (i == 0 && name == keywords::CrateRoot.name()) ||
(i == 0 && name == keywords::Crate.name()) || (i == 0 && name == keywords::Crate.name()) ||
(i == 0 && name == keywords::DollarCrate.name()) || (i == 0 && name == keywords::DollarCrate.name()) ||
(i == 1 && name == keywords::Crate.name() && (i == 1 && name == keywords::Crate.name() &&
path[0].name == keywords::CrateRoot.name()) { path[0].name == keywords::CrateRoot.name()) {
// `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b` // `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b`
module = Some(self.resolve_crate_root(ident)); module = Some(ModuleOrUniformRoot::Module(
self.resolve_crate_root(ident)));
continue continue
} else if i == 1 && !ident.is_path_segment_keyword() {
let prev_name = path[0].name;
if prev_name == keywords::Extern.name() ||
prev_name == keywords::CrateRoot.name() &&
self.session.features_untracked().extern_absolute_paths &&
self.session.rust_2018() {
// `::extern_crate::a::b`
let crate_id = self.crate_loader.process_path_extern(name, ident.span);
let crate_root =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(crate_root);
module = Some(crate_root);
continue
}
} }
} }
@ -3513,7 +3561,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
let def = binding.def(); let def = binding.def();
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def); let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
if let Some(next_module) = binding.module() { if let Some(next_module) = binding.module() {
module = Some(next_module); module = Some(ModuleOrUniformRoot::Module(next_module));
} else if def == Def::ToolMod && i + 1 != path.len() { } else if def == Def::ToolMod && i + 1 != path.len() {
let def = Def::NonMacroAttr(NonMacroAttrKind::Tool); let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
return PathResult::NonModule(PathResolution::new(def)); return PathResult::NonModule(PathResolution::new(def));
@ -3537,14 +3585,18 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
} }
Err(Undetermined) => return PathResult::Indeterminate, Err(Undetermined) => return PathResult::Indeterminate,
Err(Determined) => { Err(Determined) => {
if let Some(module) = module { if let Some(ModuleOrUniformRoot::Module(module)) = module {
if opt_ns.is_some() && !module.is_normal() { if opt_ns.is_some() && !module.is_normal() {
return PathResult::NonModule(PathResolution::with_unresolved_segments( return PathResult::NonModule(PathResolution::with_unresolved_segments(
module.def().unwrap(), path.len() - i module.def().unwrap(), path.len() - i
)); ));
} }
} }
let msg = if module.and_then(ModuleData::def) == self.graph_root.def() { let module_def = match module {
Some(ModuleOrUniformRoot::Module(module)) => module.def(),
_ => None,
};
let msg = if module_def == self.graph_root.def() {
let is_mod = |def| match def { Def::Mod(..) => true, _ => false }; let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
let mut candidates = let mut candidates =
self.lookup_import_candidates(name, TypeNS, is_mod); self.lookup_import_candidates(name, TypeNS, is_mod);
@ -3568,7 +3620,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding); self.lint_if_path_starts_with_module(crate_lint, path, path_span, second_binding);
PathResult::Module(module.unwrap_or(self.graph_root)) PathResult::Module(module.unwrap_or_else(|| {
span_bug!(path_span, "resolve_path: empty(?) path {:?} has no module", path);
}))
} }
fn lint_if_path_starts_with_module( fn lint_if_path_starts_with_module(
@ -3578,6 +3633,17 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
path_span: Span, path_span: Span,
second_binding: Option<&NameBinding>, second_binding: Option<&NameBinding>,
) { ) {
// In the 2018 edition this lint is a hard error, so nothing to do
if self.session.rust_2018() {
return
}
// In the 2015 edition there's no use in emitting lints unless the
// crate's already enabled the feature that we're going to suggest
if !self.session.features_untracked().crate_in_paths {
return
}
let (diag_id, diag_span) = match crate_lint { let (diag_id, diag_span) = match crate_lint {
CrateLint::No => return, CrateLint::No => return,
CrateLint::SimplePath(id) => (id, path_span), CrateLint::SimplePath(id) => (id, path_span),
@ -3620,24 +3686,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
} }
} }
self.lint_path_starts_with_module(diag_id, diag_span);
}
fn lint_path_starts_with_module(&self, id: NodeId, span: Span) {
// In the 2018 edition this lint is a hard error, so nothing to do
if self.session.rust_2018() {
return
}
// In the 2015 edition there's no use in emitting lints unless the
// crate's already enabled the feature that we're going to suggest
if !self.session.features_untracked().crate_in_paths {
return
}
let diag = lint::builtin::BuiltinLintDiagnostics let diag = lint::builtin::BuiltinLintDiagnostics
::AbsPathWithModule(span); ::AbsPathWithModule(diag_span);
self.session.buffer_lint_with_diagnostic( self.session.buffer_lint_with_diagnostic(
lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
id, span, diag_id, diag_span,
"absolute paths must start with `self`, `super`, \ "absolute paths must start with `self`, `super`, \
`crate`, or an external crate name in the 2018 edition", `crate`, or an external crate name in the 2018 edition",
diag); diag);
@ -3782,8 +3835,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// Look for associated items in the current trait. // Look for associated items in the current trait.
if let Some((module, _)) = self.current_trait_ref { if let Some((module, _)) = self.current_trait_ref {
if let Ok(binding) = if let Ok(binding) = self.resolve_ident_in_module(
self.resolve_ident_in_module(module, ident, ns, false, module.span) { ModuleOrUniformRoot::Module(module),
ident,
ns,
false,
module.span,
) {
let def = binding.def(); let def = binding.def();
if filter_fn(def) { if filter_fn(def) {
return Some(if self.has_self.contains(&def.def_id()) { return Some(if self.has_self.contains(&def.def_id()) {
@ -3855,9 +3913,11 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
} else { } else {
// Search in module. // Search in module.
let mod_path = &path[..path.len() - 1]; let mod_path = &path[..path.len() - 1];
if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), if let PathResult::Module(module) = self.resolve_path(None, mod_path, Some(TypeNS),
false, span, CrateLint::No) { false, span, CrateLint::No) {
add_module_candidates(module, &mut names); if let ModuleOrUniformRoot::Module(module) = module {
add_module_candidates(module, &mut names);
}
} }
} }
@ -4096,7 +4156,13 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
let mut found_traits = Vec::new(); let mut found_traits = Vec::new();
// Look for the current trait. // Look for the current trait.
if let Some((module, _)) = self.current_trait_ref { if let Some((module, _)) = self.current_trait_ref {
if self.resolve_ident_in_module(module, ident, ns, false, module.span).is_ok() { if self.resolve_ident_in_module(
ModuleOrUniformRoot::Module(module),
ident,
ns,
false,
module.span,
).is_ok() {
let def_id = module.def_id().unwrap(); let def_id = module.def_id().unwrap();
found_traits.push(TraitCandidate { def_id: def_id, import_id: None }); found_traits.push(TraitCandidate { def_id: def_id, import_id: None });
} }
@ -4144,8 +4210,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() { if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() {
continue continue
} }
if self.resolve_ident_in_module_unadjusted(module, ident, ns, false, false, module.span) if self.resolve_ident_in_module_unadjusted(
.is_ok() { ModuleOrUniformRoot::Module(module),
ident,
ns,
false,
false,
module.span,
).is_ok() {
let import_id = match binding.kind { let import_id = match binding.kind {
NameBindingKind::Import { directive, .. } => { NameBindingKind::Import { directive, .. } => {
self.maybe_unused_trait_imports.insert(directive.id); self.maybe_unused_trait_imports.insert(directive.id);

View file

@ -10,6 +10,7 @@
use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error}; use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding}; use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
use ModuleOrUniformRoot;
use Namespace::{self, TypeNS, MacroNS}; use Namespace::{self, TypeNS, MacroNS};
use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport}; use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
use resolve_imports::ImportResolver; use resolve_imports::ImportResolver;
@ -538,7 +539,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
return Err(Determinacy::Determined); return Err(Determinacy::Determined);
} }
let def = match self.resolve_path(&path, Some(MacroNS), false, span, CrateLint::No) { let res = self.resolve_path(None, &path, Some(MacroNS), false, span, CrateLint::No);
let def = match res {
PathResult::NonModule(path_res) => match path_res.base_def() { PathResult::NonModule(path_res) => match path_res.base_def() {
Def::Err => Err(Determinacy::Determined), Def::Err => Err(Determinacy::Determined),
def @ _ => { def @ _ => {
@ -655,7 +657,12 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
WhereToResolve::Module(module) => { WhereToResolve::Module(module) => {
let orig_current_module = mem::replace(&mut self.current_module, module); let orig_current_module = mem::replace(&mut self.current_module, module);
let binding = self.resolve_ident_in_module_unadjusted( let binding = self.resolve_ident_in_module_unadjusted(
module, ident, ns, true, record_used, path_span, ModuleOrUniformRoot::Module(module),
ident,
ns,
true,
record_used,
path_span,
); );
self.current_module = orig_current_module; self.current_module = orig_current_module;
binding.map(MacroBinding::Modern) binding.map(MacroBinding::Modern)
@ -715,9 +722,14 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
let mut result = Err(Determinacy::Determined); let mut result = Err(Determinacy::Determined);
if use_prelude { if use_prelude {
if let Some(prelude) = self.prelude { if let Some(prelude) = self.prelude {
if let Ok(binding) = if let Ok(binding) = self.resolve_ident_in_module_unadjusted(
self.resolve_ident_in_module_unadjusted(prelude, ident, ns, ModuleOrUniformRoot::Module(prelude),
false, false, path_span) { ident,
ns,
false,
false,
path_span,
) {
result = Ok(MacroBinding::Global(binding)); result = Ok(MacroBinding::Global(binding));
} }
} }
@ -893,7 +905,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
pub fn finalize_current_module_macro_resolutions(&mut self) { pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module; let module = self.current_module;
for &(ref path, span) in module.macro_resolutions.borrow().iter() { for &(ref path, span) in module.macro_resolutions.borrow().iter() {
match self.resolve_path(&path, Some(MacroNS), true, span, CrateLint::No) { match self.resolve_path(None, &path, Some(MacroNS), true, span, CrateLint::No) {
PathResult::NonModule(_) => {}, PathResult::NonModule(_) => {},
PathResult::Failed(span, msg, _) => { PathResult::Failed(span, msg, _) => {
resolve_error(self, span, ResolutionError::FailedToResolve(&msg)); resolve_error(self, span, ResolutionError::FailedToResolve(&msg));

View file

@ -10,7 +10,7 @@
use self::ImportDirectiveSubclass::*; use self::ImportDirectiveSubclass::*;
use {AmbiguityError, CrateLint, Module, PerNS}; use {AmbiguityError, CrateLint, Module, ModuleOrUniformRoot, PerNS};
use Namespace::{self, TypeNS, MacroNS}; use Namespace::{self, TypeNS, MacroNS};
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
use Resolver; use Resolver;
@ -85,7 +85,8 @@ pub struct ImportDirective<'a> {
pub parent: Module<'a>, pub parent: Module<'a>,
pub module_path: Vec<Ident>, pub module_path: Vec<Ident>,
pub imported_module: Cell<Option<Module<'a>>>, // the resolution of `module_path` /// The resolution of `module_path`.
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
pub subclass: ImportDirectiveSubclass<'a>, pub subclass: ImportDirectiveSubclass<'a>,
pub vis: Cell<ty::Visibility>, pub vis: Cell<ty::Visibility>,
pub expansion: Mark, pub expansion: Mark,
@ -133,13 +134,38 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
/// Attempts to resolve `ident` in namespaces `ns` of `module`. /// Attempts to resolve `ident` in namespaces `ns` of `module`.
/// Invariant: if `record_used` is `Some`, expansion and 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, pub fn resolve_ident_in_module_unadjusted(&mut self,
module: Module<'a>, module: ModuleOrUniformRoot<'a>,
ident: Ident, ident: Ident,
ns: Namespace, ns: Namespace,
restricted_shadowing: bool, restricted_shadowing: bool,
record_used: bool, record_used: bool,
path_span: Span) path_span: Span)
-> Result<&'a NameBinding<'a>, Determinacy> { -> Result<&'a NameBinding<'a>, Determinacy> {
let module = match module {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::UniformRoot(root) => {
let crate_root = if
root != keywords::Extern.name() &&
(
ident.name == keywords::Crate.name() ||
ident.name == keywords::DollarCrate.name()
)
{
self.resolve_crate_root(ident)
} else if !ident.is_path_segment_keyword() {
let crate_id =
self.crate_loader.process_path_extern(ident.name, ident.span);
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
} else {
return Err(Determined);
};
self.populate_module_if_necessary(crate_root);
let binding = (crate_root, ty::Visibility::Public,
ident.span, Mark::root()).to_name_binding(self.arenas);
return Ok(binding);
}
};
self.populate_module_if_necessary(module); self.populate_module_if_necessary(module);
let resolution = self.resolution(module, ident, ns) let resolution = self.resolution(module, ident, ns)
@ -260,7 +286,11 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
if !self.is_accessible(glob_import.vis.get()) { if !self.is_accessible(glob_import.vis.get()) {
continue continue
} }
let module = unwrap_or!(glob_import.imported_module.get(), return Err(Undetermined)); let module = match glob_import.imported_module.get() {
Some(ModuleOrUniformRoot::Module(module)) => module,
Some(ModuleOrUniformRoot::UniformRoot(_)) => continue,
None => return Err(Undetermined),
};
let (orig_current_module, mut ident) = (self.current_module, ident.modern()); let (orig_current_module, mut ident) = (self.current_module, ident.modern());
match ident.span.glob_adjust(module.expansion, glob_import.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(Some(def)) => self.current_module = self.macro_def_scope(def),
@ -268,7 +298,12 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
None => continue, None => continue,
}; };
let result = self.resolve_ident_in_module_unadjusted( let result = self.resolve_ident_in_module_unadjusted(
module, ident, ns, false, false, path_span, ModuleOrUniformRoot::Module(module),
ident,
ns,
false,
false,
path_span,
); );
self.current_module = orig_current_module; self.current_module = orig_current_module;
match result { match result {
@ -576,8 +611,14 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
// For better failure detection, pretend that the import will not define any names // For better failure detection, pretend that the import will not define any names
// while resolving its module path. // while resolving its module path.
directive.vis.set(ty::Visibility::Invisible); directive.vis.set(ty::Visibility::Invisible);
let result = self.resolve_path(&directive.module_path[..], None, false, let result = self.resolve_path(
directive.span, directive.crate_lint()); Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
&directive.module_path[..],
None,
false,
directive.span,
directive.crate_lint(),
);
directive.vis.set(vis); directive.vis.set(vis);
match result { match result {
@ -644,77 +685,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> { fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> {
self.current_module = directive.parent; self.current_module = directive.parent;
let ImportDirective { ref module_path, span, .. } = *directive; let ImportDirective { ref module_path, span, .. } = *directive;
let mut warn_if_binding_comes_from_local_crate = false;
// 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].name == keywords::CrateRoot.name() ||
module_path[0].name == keywords::Extern.name()) {
let is_extern = module_path[0].name == keywords::Extern.name() ||
(self.session.features_untracked().extern_absolute_paths &&
self.session.rust_2018());
match directive.subclass {
GlobImport { .. } if is_extern => {
return Some((directive.span,
"cannot glob-import all possible crates".to_string()));
}
GlobImport { .. } if self.session.features_untracked().extern_absolute_paths => {
self.lint_path_starts_with_module(
directive.root_id,
directive.root_span,
);
}
SingleImport { source, target, .. } => {
let crate_root = if source.name == keywords::Crate.name() &&
module_path[0].name != keywords::Extern.name() {
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 {
Some(self.resolve_crate_root(source))
}
} else if is_extern && !source.is_path_segment_keyword() {
let crate_id =
self.resolver.crate_loader.process_use_extern(
source.name,
directive.span,
directive.id,
&self.resolver.definitions,
);
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 {
warn_if_binding_comes_from_local_crate = true;
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),
},
vis: directive.vis.get(),
span: directive.span,
expansion: directive.expansion,
});
let _ = self.try_define(directive.parent, target, TypeNS, binding);
let import = self.import_map.entry(directive.id).or_default();
import[TypeNS] = Some(PathResolution::new(binding.def()));
return None;
}
}
_ => {}
}
}
let module_result = self.resolve_path( let module_result = self.resolve_path(
Some(ModuleOrUniformRoot::UniformRoot(keywords::Invalid.name())),
&module_path, &module_path,
None, None,
true, true,
@ -734,7 +707,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
if !self_path.is_empty() && !is_special(self_path[0]) && if !self_path.is_empty() && !is_special(self_path[0]) &&
!(self_path.len() > 1 && is_special(self_path[1])) { !(self_path.len() > 1 && is_special(self_path[1])) {
self_path[0].name = keywords::SelfValue.name(); self_path[0].name = keywords::SelfValue.name();
self_result = Some(self.resolve_path(&self_path, None, false, self_result = Some(self.resolve_path(None, &self_path, None, false,
span, CrateLint::No)); span, CrateLint::No));
} }
return if let Some(PathResult::Module(..)) = self_result { return if let Some(PathResult::Module(..)) = self_result {
@ -748,12 +721,27 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
let (ident, result, type_ns_only) = match directive.subclass { let (ident, result, type_ns_only) = match directive.subclass {
SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only), SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only),
GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
// Importing a module into itself is not allowed.
return Some((directive.span,
"Cannot glob-import a module into itself.".to_string()));
}
GlobImport { is_prelude, ref max_vis } => { GlobImport { is_prelude, ref max_vis } => {
if module_path.len() <= 1 {
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
// 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = module_path.clone();
full_path.push(keywords::Invalid.ident());
self.lint_if_path_starts_with_module(
directive.crate_lint(),
&full_path,
directive.span,
None,
);
}
if let ModuleOrUniformRoot::Module(module) = module {
if module.def_id() == directive.parent.def_id() {
// Importing a module into itself is not allowed.
return Some((directive.span,
"Cannot glob-import a module into itself.".to_string()));
}
}
if !is_prelude && if !is_prelude &&
max_vis.get() != ty::Visibility::Invisible && // Allow empty globs. max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
!max_vis.get().is_at_least(directive.vis.get(), &*self) { !max_vis.get().is_at_least(directive.vis.get(), &*self) {
@ -770,8 +758,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
if let Ok(binding) = result[ns].get() { if let Ok(binding) = result[ns].get() {
all_ns_err = false; all_ns_err = false;
if this.record_use(ident, ns, binding, directive.span) { if this.record_use(ident, ns, binding, directive.span) {
this.resolution(module, ident, ns).borrow_mut().binding = if let ModuleOrUniformRoot::Module(module) = module {
Some(this.dummy_binding); this.resolution(module, ident, ns).borrow_mut().binding =
Some(this.dummy_binding);
}
} }
} }
}); });
@ -786,8 +776,13 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}); });
return if all_ns_failed { return if all_ns_failed {
let resolutions = module.resolutions.borrow(); let resolutions = match module {
let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| { ModuleOrUniformRoot::Module(module) =>
Some(module.resolutions.borrow()),
ModuleOrUniformRoot::UniformRoot(_) => None,
};
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
if *i == ident { return None; } // Never suggest the same name if *i == ident { return None; } // Never suggest the same name
match *resolution.borrow() { match *resolution.borrow() {
NameResolution { binding: Some(name_binding), .. } => { NameResolution { binding: Some(name_binding), .. } => {
@ -813,11 +808,24 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
Some(name) => format!(". Did you mean to use `{}`?", name), Some(name) => format!(". Did you mean to use `{}`?", name),
None => "".to_owned(), None => "".to_owned(),
}; };
let module_str = module_to_string(module); let msg = match module {
let msg = if let Some(module_str) = module_str { ModuleOrUniformRoot::Module(module) => {
format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion) let module_str = module_to_string(module);
} else { if let Some(module_str) = module_str {
format!("no `{}` in the root{}", ident, lev_suggestion) format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
} else {
format!("no `{}` in the root{}", ident, lev_suggestion)
}
}
ModuleOrUniformRoot::UniformRoot(_) => {
if !ident.is_path_segment_keyword() {
format!("no `{}` external crate{}", ident, lev_suggestion)
} else {
// HACK(eddyb) this shows up for `self` & `super`, which
// should work instead - for now keep the same error message.
format!("no `{}` in the root{}", ident, lev_suggestion)
}
}
}; };
Some((span, msg)) Some((span, msg))
} else { } else {
@ -868,26 +876,20 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
} }
} }
if warn_if_binding_comes_from_local_crate { if module_path.len() <= 1 {
let mut warned = false; // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
// 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = module_path.clone();
full_path.push(ident);
self.per_ns(|this, ns| { self.per_ns(|this, ns| {
let binding = match result[ns].get().ok() { if let Ok(binding) = result[ns].get() {
Some(b) => b, this.lint_if_path_starts_with_module(
None => return directive.crate_lint(),
}; &full_path,
if let NameBindingKind::Import { directive: d, .. } = binding.kind { directive.span,
if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass { Some(binding),
return );
}
} }
if warned {
return
}
warned = true;
this.lint_path_starts_with_module(
directive.root_id,
directive.root_span,
);
}); });
} }
@ -904,7 +906,15 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
} }
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
let module = directive.imported_module.get().unwrap(); 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");
return;
}
};
self.populate_module_if_necessary(module); self.populate_module_if_necessary(module);
if let Some(Def::Trait(_)) = module.def() { if let Some(Def::Trait(_)) = module.def() {
@ -1026,8 +1036,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}; };
let mut err = self.session.struct_span_err(binding.span, &msg); let mut err = self.session.struct_span_err(binding.span, &msg);
let imported_module = directive.imported_module.get() let imported_module = match directive.imported_module.get() {
.expect("module should exist"); Some(ModuleOrUniformRoot::Module(module)) => module,
_ => bug!("module should exist"),
};
let resolutions = imported_module.parent.expect("parent should exist") let resolutions = imported_module.parent.expect("parent should exist")
.resolutions.borrow(); .resolutions.borrow();
let enum_path_segment_index = directive.module_path.len() - 1; let enum_path_segment_index = directive.module_path.len() - 1;

View file

@ -101,7 +101,7 @@ impl Path {
// or starts with something like `self`/`super`/`$crate`/etc. // or starts with something like `self`/`super`/`$crate`/etc.
pub fn make_root(&self) -> Option<PathSegment> { pub fn make_root(&self) -> Option<PathSegment> {
if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) { if let Some(ident) = self.segments.get(0).map(|seg| seg.ident) {
if ident.is_path_segment_keyword() && ident.name != keywords::Crate.name() { if ident.is_path_segment_keyword() {
return None; return None;
} }
} }

View file

@ -10,7 +10,11 @@
macro_rules! m { macro_rules! m {
() => { () => {
struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate` // Avoid having more than one `$crate`-named item in the same module,
// as even though they error, they still parse as `$crate` and conflict.
mod foo {
struct $crate {} //~ ERROR expected identifier, found reserved identifier `$crate`
}
use $crate; // OK use $crate; // OK
//~^ WARN `$crate` may not be imported //~^ WARN `$crate` may not be imported

View file

@ -9,15 +9,14 @@
// except according to those terms. // except according to those terms.
// aux-build:import_crate_var.rs // aux-build:import_crate_var.rs
// error-pattern: `$crate` may not be imported
// error-pattern: `use $crate;` was erroneously allowed and will become a hard error
// error-pattern: compilation successful
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#[macro_use] extern crate import_crate_var; #[macro_use] extern crate import_crate_var;
#[rustc_error] #[rustc_error]
fn main() { fn main() { //~ ERROR compilation successful
m!(); m!();
//~^ WARN `$crate` may not be imported
//~| NOTE `use $crate;` was erroneously allowed and will become a hard error
} }

View file

@ -11,5 +11,5 @@
#![feature(extern_in_paths)] #![feature(extern_in_paths)]
fn main() { fn main() {
let extern = 0; //~ ERROR expected unit struct/variant or constant, found module `extern` let extern = 0; //~ ERROR cannot find unit struct/variant or constant `extern` in this scope
} }

View file

@ -11,10 +11,8 @@
// aux-build:xcrate.rs // aux-build:xcrate.rs
// edition:2018 // edition:2018
use crate; //~ ERROR unresolved import `crate` use crate; //~ ERROR crate root imports need to be explicitly named: `use crate as name;`
//~^ NOTE crate root imports need to be explicitly named: `use crate as name;` use *; //~ ERROR cannot glob-import all possible crates
use *; //~ ERROR unresolved import `*`
//~^ NOTE cannot glob-import all possible crates
fn main() { fn main() {
let s = ::xcrate; //~ ERROR expected value, found module `xcrate` let s = ::xcrate; //~ ERROR expected value, found module `xcrate`

View file

@ -14,8 +14,7 @@
use extern; //~ ERROR unresolved import `extern` use extern; //~ ERROR unresolved import `extern`
//~^ NOTE no `extern` in the root //~^ NOTE no `extern` in the root
use extern::*; //~ ERROR unresolved import `extern::*` use extern::*; //~ ERROR cannot glob-import all possible crates
//~^ NOTE cannot glob-import all possible crates
fn main() { fn main() {
let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate` let s = extern::xcrate; //~ ERROR expected value, found module `extern::xcrate`

View file

@ -0,0 +1,15 @@
// 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.
#![crate_type = "lib"]
pub fn hello() {
println!("Hello, world!");
}

View file

@ -0,0 +1,21 @@
// 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.
// aux-build:some_crate.rs
// edition:2018
mod foo {
pub use some_crate;
}
fn main() {
::some_crate::hello();
foo::some_crate::hello();
}

View file

@ -0,0 +1,15 @@
// 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.
#![crate_type = "lib"]
pub fn hello() {
println!("Hello, world!");
}

View file

@ -0,0 +1,24 @@
// 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.
// aux-build:some_crate.rs
// edition:2018
use some_crate as some_name;
mod foo {
pub use crate::some_name::*;
}
fn main() {
::some_crate::hello();
some_name::hello();
foo::hello();
}

View file

@ -0,0 +1,13 @@
// 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.
#![crate_type = "lib"]
pub struct DecodingError;

View file

@ -0,0 +1,22 @@
// 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.
// aux-build:png.rs
// edition:2018
mod png {
use png as png_ext;
fn foo() -> png_ext::DecodingError { unimplemented!() }
}
fn main() {
println!("Hello, world!");
}