diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index db86840fd38..d90fe769caf 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); } @@ -500,6 +513,7 @@ impl<'b> Resolver<'b> { legacy_imports: LegacyMacroImports, allow_shadowing: bool) { let import_macro = |this: &mut Self, name, ext: Rc<_>, span| { + this.used_crates.insert(module.def_id().unwrap().krate); if let SyntaxExtension::NormalTT(..) = *ext { this.macro_names.insert(name); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c6f73b804e3..856eb348eae 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -845,6 +845,10 @@ impl<'a> ModuleS<'a> { _ => false, } } + + fn is_local(&self) -> bool { + self.normal_ancestor_id.is_some() + } } impl<'a> fmt::Debug for ModuleS<'a> { @@ -1580,14 +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.def_id().unwrap().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 @@ -1620,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. @@ -2569,7 +2574,8 @@ impl<'a> Resolver<'a> { let unqualified_def = resolve_identifier_with_fallback(self, None); let qualified_binding = self.resolve_module_relative_path(span, segments, namespace); match (qualified_binding, unqualified_def) { - (Ok(binding), Some(ref ud)) if binding.def() == ud.def => { + (Ok(binding), Some(ref ud)) if binding.def() == ud.def && + segments[0].identifier.name.as_str() != "$crate" => { self.session .add_lint(lint::builtin::UNUSED_QUALIFICATIONS, id, 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() {} diff --git a/src/test/compile-fail/lint-qualification.rs b/src/test/compile-fail/lint-qualification.rs index 0ad3d2c5e73..af9b21dadd1 100644 --- a/src/test/compile-fail/lint-qualification.rs +++ b/src/test/compile-fail/lint-qualification.rs @@ -18,4 +18,11 @@ fn main() { use foo::bar; foo::bar(); //~ ERROR: unnecessary qualification bar(); + + let _ = || -> Result<(), ()> { try!(Ok(())); Ok(()) }; // issue #37345 + + macro_rules! m { + () => { $crate::foo::bar(); } + } + m!(); // issue #37357 } diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs index 854c51d0769..52cb84f662d 100644 --- a/src/test/compile-fail/lint-unused-extern-crate.rs +++ b/src/test/compile-fail/lint-unused-extern-crate.rs @@ -26,6 +26,8 @@ extern crate rand; // no error, the use marks it as used extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used +#[macro_use] extern crate core; // no error, the `#[macro_use]` marks it as used + #[allow(unused_imports)] use rand::isaac::IsaacRng;