Add ABSOLUTE_PATH_STARTING_WITH_MODULE epoch lint for path breakage

This commit is contained in:
Manish Goregaokar 2018-04-19 16:45:33 -07:00
parent 56ace0aac2
commit 37d3bea3ec
4 changed files with 42 additions and 4 deletions

View File

@ -254,6 +254,13 @@ declare_lint! {
"suggest using `dyn Trait` for trait objects" "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! { declare_lint! {
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
Warn, Warn,
@ -314,6 +321,7 @@ impl LintPass for HardwiredLints {
TYVAR_BEHIND_RAW_POINTER, TYVAR_BEHIND_RAW_POINTER,
ELIDED_LIFETIME_IN_PATH, ELIDED_LIFETIME_IN_PATH,
BARE_TRAIT_OBJECT, BARE_TRAIT_OBJECT,
ABSOLUTE_PATH_STARTING_WITH_MODULE,
UNSTABLE_NAME_COLLISION, UNSTABLE_NAME_COLLISION,
) )
} }

View File

@ -40,7 +40,7 @@ extern crate rustc_mir;
extern crate syntax_pos; extern crate syntax_pos;
use rustc::lint; 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::session;
use rustc::util; 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 // 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. // 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 // Register renamed and removed lints

View File

@ -3189,7 +3189,7 @@ impl<'a> Resolver<'a> {
path[0].name != keywords::CrateRoot.name() && path[0].name != keywords::CrateRoot.name() &&
path[0].name != keywords::DollarCrate.name() { path[0].name != keywords::DollarCrate.name() {
let unqualified_result = { 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::NonModule(path_res) => path_res.base_def(),
PathResult::Module(module) => module.def().unwrap(), PathResult::Module(module) => module.def().unwrap(),
_ => return Some(result), _ => return Some(result),
@ -3209,7 +3209,8 @@ impl<'a> Resolver<'a> {
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,
_node_id: Option<NodeId>) node_id: Option<NodeId>) // None indicates that we don't care about linting
// `::module` paths
-> PathResult<'a> { -> PathResult<'a> {
let mut module = None; let mut module = None;
let mut allow_super = true; let mut allow_super = true;
@ -3328,6 +3329,30 @@ impl<'a> Resolver<'a> {
format!("Not a module `{}`", ident), format!("Not a module `{}`", ident),
is_last); 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(Undetermined) => return PathResult::Indeterminate,
Err(Determined) => { Err(Determined) => {

View File

@ -679,7 +679,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
!(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(&self_path, None, false,
span, Some(directive.id))); span, None));
} }
return if let Some(PathResult::Module(..)) = self_result { return if let Some(PathResult::Module(..)) = self_result {
Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..])))) Some((span, format!("Did you mean `{}`?", names_to_string(&self_path[..]))))