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"
}
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,
)
}

View File

@ -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

View File

@ -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<Namespace>, // `None` indicates a module path
record_used: bool,
path_span: Span,
_node_id: Option<NodeId>)
node_id: Option<NodeId>) // 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) => {

View File

@ -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[..]))))