Skip to content

Commit c904d98

Browse files
committed
Add lint for crates used through modules
1 parent 78fd719 commit c904d98

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

src/librustc/lint/builtin.rs

+8
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@ declare_lint! {
273273
"detects name collision with an existing but unstable method"
274274
}
275275

276+
277+
declare_lint! {
278+
pub USE_CRATE_IN_MODULE,
279+
Allow,
280+
"attempting to use a crate through another module"
281+
}
282+
276283
/// Does nothing as a lint pass, but registers some `Lint`s
277284
/// which are used by other parts of the compiler.
278285
#[derive(Copy, Clone)]
@@ -323,6 +330,7 @@ impl LintPass for HardwiredLints {
323330
BARE_TRAIT_OBJECT,
324331
ABSOLUTE_PATH_STARTING_WITH_MODULE,
325332
UNSTABLE_NAME_COLLISION,
333+
USE_CRATE_IN_MODULE
326334
)
327335
}
328336
}

src/librustc_lint/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extern crate syntax_pos;
4141

4242
use rustc::lint;
4343
use rustc::lint::builtin::{BARE_TRAIT_OBJECT, ABSOLUTE_PATH_STARTING_WITH_MODULE};
44+
use rustc::lint::builtin::USE_CRATE_IN_MODULE;
4445
use rustc::session;
4546
use rustc::util;
4647

@@ -182,7 +183,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
182183
"rust_2018_idioms",
183184
BARE_TRAIT_OBJECT,
184185
UNREACHABLE_PUB,
185-
UNNECESSARY_EXTERN_CRATE);
186+
UNNECESSARY_EXTERN_CRATE,
187+
USE_CRATE_IN_MODULE);
186188

187189
// Guidelines for creating a future incompatibility lint:
188190
//

src/librustc_resolve/lib.rs

+30
Original file line numberDiff line numberDiff line change
@@ -3233,6 +3233,10 @@ impl<'a> Resolver<'a> {
32333233
let mut module = None;
32343234
let mut allow_super = true;
32353235

3236+
let mut fully_local = true;
3237+
// are we doing the first resolution? I.e. ignoring :: and crate
3238+
// and stuff, have we resolved anything yet?
3239+
let mut first_resolution = true;
32363240
for (i, &ident) in path.iter().enumerate() {
32373241
debug!("resolve_path ident {} {:?}", i, ident);
32383242
let is_last = i == path.len() - 1;
@@ -3242,8 +3246,10 @@ impl<'a> Resolver<'a> {
32423246
if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
32433247
let mut ctxt = ident.span.ctxt().modern();
32443248
module = Some(self.resolve_self(&mut ctxt, self.current_module));
3249+
first_resolution = false;
32453250
continue
32463251
} else if allow_super && ns == TypeNS && name == keywords::Super.name() {
3252+
first_resolution = false;
32473253
let mut ctxt = ident.span.ctxt().modern();
32483254
let self_module = match i {
32493255
0 => self.resolve_self(&mut ctxt, self.current_module),
@@ -3270,6 +3276,7 @@ impl<'a> Resolver<'a> {
32703276
continue
32713277
} else if i == 0 && name == keywords::DollarCrate.name() {
32723278
// `$crate::a::b`
3279+
fully_local = false;
32733280
module = Some(self.resolve_crate_root(ident.span.ctxt(), true));
32743281
continue
32753282
} else if i == 1 && !token::is_path_segment_keyword(ident) {
@@ -3285,6 +3292,8 @@ impl<'a> Resolver<'a> {
32853292
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
32863293
self.populate_module_if_necessary(crate_root);
32873294
module = Some(crate_root);
3295+
fully_local = false;
3296+
first_resolution = false;
32883297
continue
32893298
}
32903299
}
@@ -3337,6 +3346,27 @@ impl<'a> Resolver<'a> {
33373346
let def = binding.def();
33383347
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
33393348
if let Some(next_module) = binding.module() {
3349+
if ns == TypeNS && fully_local && module.is_some() && !first_resolution {
3350+
if let Some(id) = node_id {
3351+
if self.extern_prelude.contains(&ident.name) {
3352+
let crate_id =
3353+
self.crate_loader
3354+
.process_path_extern(ident.name, ident.span);
3355+
let binding_id = binding.def().def_id();
3356+
if binding_id.krate == crate_id &&
3357+
binding_id.index == CRATE_DEF_INDEX {
3358+
self.session.buffer_lint(
3359+
lint::builtin::USE_CRATE_IN_MODULE,
3360+
id, ident.span,
3361+
"The crate can be used directly \
3362+
here.");
3363+
}
3364+
}
3365+
}
3366+
3367+
}
3368+
fully_local = fully_local && next_module.is_local();
3369+
first_resolution = false;
33403370
module = Some(next_module);
33413371
} else if def == Def::Err {
33423372
return PathResult::NonModule(err_path_resolution());

0 commit comments

Comments
 (0)