From 37d3bea3ec3d47dbf1f7352c32fab75ce408798c Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 19 Apr 2018 16:45:33 -0700 Subject: [PATCH] Add ABSOLUTE_PATH_STARTING_WITH_MODULE epoch lint for path breakage --- src/librustc/lint/builtin.rs | 8 +++++++ src/librustc_lint/lib.rs | 7 +++++- src/librustc_resolve/lib.rs | 29 +++++++++++++++++++++++-- src/librustc_resolve/resolve_imports.rs | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 97cfcf0f607..30ae830ee46 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -254,6 +254,13 @@ declare_lint! { "suggest using `dyn Trait` for trait objects" } +declare_lint! { + pub ABSOLUTE_PATH_STARTING_WITH_MODULE, + Allow, + "fully qualified paths that start with a module name \ + instead of `crate`, `self`, or an extern crate name" +} + declare_lint! { pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, Warn, @@ -314,6 +321,7 @@ impl LintPass for HardwiredLints { TYVAR_BEHIND_RAW_POINTER, ELIDED_LIFETIME_IN_PATH, BARE_TRAIT_OBJECT, + ABSOLUTE_PATH_STARTING_WITH_MODULE, UNSTABLE_NAME_COLLISION, ) } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 16e8600f2d8..038d47dd5ea 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -40,7 +40,7 @@ extern crate rustc_mir; extern crate syntax_pos; use rustc::lint; -use rustc::lint::builtin::BARE_TRAIT_OBJECT; +use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_STARTING_WITH_MODULE}; use rustc::session; use rustc::util; @@ -278,6 +278,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { // Note: this item represents future incompatibility of all unstable functions in the // standard library, and thus should never be removed or changed to an error. }, + FutureIncompatibleInfo { + id: LintId::of(ABSOLUTE_PATH_STARTING_WITH_MODULE), + reference: "issue TBD", + edition: Some(Edition::Edition2018), + }, ]); // Register renamed and removed lints diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 1abf336ed73..c0bb6921b69 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3189,7 +3189,7 @@ impl<'a> Resolver<'a> { path[0].name != keywords::CrateRoot.name() && path[0].name != keywords::DollarCrate.name() { let unqualified_result = { - match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, Some(id)) { + match self.resolve_path(&[*path.last().unwrap()], Some(ns), false, span, None) { PathResult::NonModule(path_res) => path_res.base_def(), PathResult::Module(module) => module.def().unwrap(), _ => return Some(result), @@ -3209,7 +3209,8 @@ impl<'a> Resolver<'a> { opt_ns: Option, // `None` indicates a module path record_used: bool, path_span: Span, - _node_id: Option) + node_id: Option) // None indicates that we don't care about linting + // `::module` paths -> PathResult<'a> { let mut module = None; let mut allow_super = true; @@ -3328,6 +3329,30 @@ impl<'a> Resolver<'a> { format!("Not a module `{}`", ident), is_last); } + + if let Some(id) = node_id { + if i == 1 && self.session.features_untracked().crate_in_paths + && !self.session.rust_2018() { + let prev_name = path[0].name; + if prev_name == keywords::Extern.name() || + prev_name == keywords::CrateRoot.name() { + let mut is_crate = false; + if let NameBindingKind::Import { directive: d, .. } = binding.kind { + if let ImportDirectiveSubclass::ExternCrate(..) = d.subclass { + is_crate = true; + } + } + + if !is_crate { + self.session.buffer_lint( + lint::builtin::ABSOLUTE_PATH_STARTING_WITH_MODULE, + id, path_span, + "Fully-qualified paths must start with `self`, `super`, + `crate`, or an external crate name in the 2018 edition"); + } + } + } + } } Err(Undetermined) => return PathResult::Indeterminate, Err(Determined) => { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index d6230cc4a67..e2a7f5668d2 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -679,7 +679,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { !(self_path.len() > 1 && is_special(self_path[1])) { self_path[0].name = keywords::SelfValue.name(); self_result = Some(self.resolve_path(&self_path, None, false, - span, Some(directive.id))); + span, None)); } return if let Some(PathResult::Module(..)) = self_result { Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))