diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index db86840fd38..1c9d1fb061f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -130,14 +130,27 @@ impl<'b> Resolver<'b> { match view_path.node { ViewPathSimple(binding, ref full_path) => { - let source_name = full_path.segments.last().unwrap().identifier.name; - if source_name.as_str() == "mod" || source_name.as_str() == "self" { + let mut source = full_path.segments.last().unwrap().identifier; + let source_name = source.name.as_str(); + if source_name == "mod" || source_name == "self" { resolve_error(self, view_path.span, ResolutionError::SelfImportsOnlyAllowedWithin); + } else if source_name == "$crate" && full_path.segments.len() == 1 { + let crate_root = self.resolve_crate_var(source.ctxt); + let crate_name = match crate_root.kind { + ModuleKind::Def(_, name) => name, + ModuleKind::Block(..) => unreachable!(), + }; + source.name = crate_name; + + self.session.struct_span_warn(item.span, "`$crate` may not be imported") + .note("`use $crate;` was erroneously allowed and \ + will become a hard error in a future release") + .emit(); } - let subclass = ImportDirectiveSubclass::single(binding.name, source_name); + let subclass = ImportDirectiveSubclass::single(binding.name, source.name); let span = view_path.span; self.add_import_directive(module_path, subclass, span, item.id, vis); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 210cabdd8ec..856eb348eae 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1584,13 +1584,7 @@ impl<'a> Resolver<'a> { fn resolve_module_prefix(&mut self, module_path: &[Ident], span: Option) -> ResolveResult> { if &*module_path[0].name.as_str() == "$crate" { - let mut ctxt = module_path[0].ctxt; - while ctxt.source().0 != SyntaxContext::empty() { - ctxt = ctxt.source().0; - } - let module = self.invocations[&ctxt.source().1].module.get(); - let crate_root = if module.is_local() { self.graph_root } else { module }; - return Success(PrefixFound(crate_root, 1)) + return Success(PrefixFound(self.resolve_crate_var(module_path[0].ctxt), 1)); } // Start at the current module if we see `self` or `super`, or at the @@ -1623,6 +1617,14 @@ impl<'a> Resolver<'a> { return Success(PrefixFound(containing_module, i)); } + fn resolve_crate_var(&mut self, mut crate_var_ctxt: SyntaxContext) -> Module<'a> { + while crate_var_ctxt.source().0 != SyntaxContext::empty() { + crate_var_ctxt = crate_var_ctxt.source().0; + } + let module = self.invocations[&crate_var_ctxt.source().1].module.get(); + if module.is_local() { self.graph_root } else { module } + } + // AST resolution // // We maintain a list of value ribs and type ribs. diff --git a/src/test/compile-fail/auxiliary/import_crate_var.rs b/src/test/compile-fail/auxiliary/import_crate_var.rs new file mode 100644 index 00000000000..1dfc7a128aa --- /dev/null +++ b/src/test/compile-fail/auxiliary/import_crate_var.rs @@ -0,0 +1,12 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[macro_export] +macro_rules! m { () => { use $crate; } } diff --git a/src/test/compile-fail/import-crate-var.rs b/src/test/compile-fail/import-crate-var.rs new file mode 100644 index 00000000000..9f573945483 --- /dev/null +++ b/src/test/compile-fail/import-crate-var.rs @@ -0,0 +1,21 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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 + +#![feature(rustc_attrs)] + +#[macro_use] extern crate import_crate_var; +m!(); + +#[rustc_error] +fn main() {}