From 199ed20aa6aa64ca58b4a924395bf9e1e71cf8a8 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 22 Oct 2016 22:08:08 +0000 Subject: [PATCH 1/3] Fix `$crate`-related regressions. --- src/librustc_resolve/lib.rs | 10 +++++++--- src/test/compile-fail/lint-qualification.rs | 7 +++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c6f73b804e3..210cabdd8ec 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> { @@ -1585,8 +1589,7 @@ impl<'a> Resolver<'a> { 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 }; + let crate_root = if module.is_local() { self.graph_root } else { module }; return Success(PrefixFound(crate_root, 1)) } @@ -2569,7 +2572,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/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 } From 04ca378b897012026fb5a4ebe8e04263e32c236b Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 23 Oct 2016 02:44:36 +0000 Subject: [PATCH 2/3] Support `use $crate;` with a future compatibility warning. --- src/librustc_resolve/build_reduced_graph.rs | 19 ++++++++++++++--- src/librustc_resolve/lib.rs | 16 +++++++------- .../auxiliary/import_crate_var.rs | 12 +++++++++++ src/test/compile-fail/import-crate-var.rs | 21 +++++++++++++++++++ 4 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/auxiliary/import_crate_var.rs create mode 100644 src/test/compile-fail/import-crate-var.rs 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() {} From 0d30325286d01a5689735b1599173ba32a796aa4 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sun, 23 Oct 2016 05:05:24 +0000 Subject: [PATCH 3/3] Avoid false positive `unused_extern_crates`. --- src/librustc_resolve/build_reduced_graph.rs | 1 + src/test/compile-fail/lint-unused-extern-crate.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1c9d1fb061f..d90fe769caf 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -513,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/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;