Skip to content

Commit ad70813

Browse files
committed
auto merge of #7706 : sanxiyn/rust/qualification-lint, r=pcwalton
Fix #2551. Lint is off by default because I didn't bother to fix all of std and extra.
2 parents f679352 + f20c78c commit ad70813

File tree

4 files changed

+63
-26
lines changed

4 files changed

+63
-26
lines changed

src/librustc/middle/lint.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ use syntax::{ast, visit, ast_util};
7171
pub enum lint {
7272
ctypes,
7373
unused_imports,
74+
unnecessary_qualification,
7475
while_true,
7576
path_statement,
7677
implicit_copies,
@@ -148,6 +149,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
148149
default: warn
149150
}),
150151

152+
("unnecessary_qualification",
153+
LintSpec {
154+
lint: unnecessary_qualification,
155+
desc: "detects unnecessarily qualified names",
156+
default: allow
157+
}),
158+
151159
("while_true",
152160
LintSpec {
153161
lint: while_true,
@@ -557,11 +565,7 @@ fn item_stopping_visitor<E: Copy>(outer: visit::vt<E>) -> visit::vt<E> {
557565
_ => (outer.visit_fn)(fk, fd, b, s, id, (e, v))
558566
}
559567
},
560-
.. **(ty_stopping_visitor(outer))})
561-
}
562-
563-
fn ty_stopping_visitor<E>(v: visit::vt<E>) -> visit::vt<E> {
564-
visit::mk_vt(@visit::Visitor {visit_ty: |_t, (_e, _v)| { },.. **v})
568+
.. **outer})
565569
}
566570

567571
fn lint_while_true() -> visit::vt<@mut Context> {

src/librustc/middle/resolve.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use metadata::csearch::get_type_name_if_impl;
1717
use metadata::cstore::find_extern_mod_stmt_cnum;
1818
use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
1919
use middle::lang_items::LanguageItems;
20-
use middle::lint::unused_imports;
20+
use middle::lint::{unnecessary_qualification, unused_imports};
2121
use middle::pat_util::pat_bindings;
2222

2323
use syntax::ast::*;
@@ -3561,7 +3561,7 @@ impl Resolver {
35613561

35623562
// Resolve derived traits.
35633563
for traits.iter().advance |trt| {
3564-
self.resolve_trait_reference(trt, visitor, TraitDerivation);
3564+
self.resolve_trait_reference(item.id, trt, visitor, TraitDerivation);
35653565
}
35663566

35673567
for (*methods).iter().advance |method| {
@@ -3802,27 +3802,29 @@ impl Resolver {
38023802
visitor: ResolveVisitor) {
38033803
for type_parameters.iter().advance |type_parameter| {
38043804
for type_parameter.bounds.iter().advance |bound| {
3805-
self.resolve_type_parameter_bound(bound, visitor);
3805+
self.resolve_type_parameter_bound(type_parameter.id, bound, visitor);
38063806
}
38073807
}
38083808
}
38093809

38103810
pub fn resolve_type_parameter_bound(@mut self,
3811+
id: node_id,
38113812
type_parameter_bound: &TyParamBound,
38123813
visitor: ResolveVisitor) {
38133814
match *type_parameter_bound {
38143815
TraitTyParamBound(ref tref) => {
3815-
self.resolve_trait_reference(tref, visitor, TraitBoundingTypeParameter)
3816+
self.resolve_trait_reference(id, tref, visitor, TraitBoundingTypeParameter)
38163817
}
38173818
RegionTyParamBound => {}
38183819
}
38193820
}
38203821

38213822
pub fn resolve_trait_reference(@mut self,
3823+
id: node_id,
38223824
trait_reference: &trait_ref,
38233825
visitor: ResolveVisitor,
38243826
reference_type: TraitReferenceType) {
3825-
match self.resolve_path(&trait_reference.path, TypeNS, true, visitor) {
3827+
match self.resolve_path(id, &trait_reference.path, TypeNS, true, visitor) {
38263828
None => {
38273829
let path_str = self.idents_to_str(trait_reference.path.idents);
38283830

@@ -3930,7 +3932,8 @@ impl Resolver {
39303932
let original_trait_refs;
39313933
match opt_trait_reference {
39323934
&Some(ref trait_reference) => {
3933-
self.resolve_trait_reference(trait_reference, visitor, TraitImplementation);
3935+
self.resolve_trait_reference(id, trait_reference, visitor,
3936+
TraitImplementation);
39343937

39353938
// Record the current set of trait references.
39363939
let mut new_trait_refs = ~[];
@@ -4142,7 +4145,7 @@ impl Resolver {
41424145

41434146
match result_def {
41444147
None => {
4145-
match self.resolve_path(path, TypeNS, true, visitor) {
4148+
match self.resolve_path(ty.id, path, TypeNS, true, visitor) {
41464149
Some(def) => {
41474150
debug!("(resolving type) resolved `%s` to \
41484151
type %?",
@@ -4179,15 +4182,15 @@ impl Resolver {
41794182

41804183
do bounds.map |bound_vec| {
41814184
for bound_vec.iter().advance |bound| {
4182-
self.resolve_type_parameter_bound(bound, visitor);
4185+
self.resolve_type_parameter_bound(ty.id, bound, visitor);
41834186
}
41844187
};
41854188
}
41864189

41874190
ty_closure(c) => {
41884191
do c.bounds.map |bounds| {
41894192
for bounds.iter().advance |bound| {
4190-
self.resolve_type_parameter_bound(bound, visitor);
4193+
self.resolve_type_parameter_bound(ty.id, bound, visitor);
41914194
}
41924195
};
41934196
visit_ty(ty, ((), visitor));
@@ -4340,7 +4343,7 @@ impl Resolver {
43404343

43414344
pat_ident(binding_mode, ref path, _) => {
43424345
// This must be an enum variant, struct, or constant.
4343-
match self.resolve_path(path, ValueNS, false, visitor) {
4346+
match self.resolve_path(pat_id, path, ValueNS, false, visitor) {
43444347
Some(def @ def_variant(*)) |
43454348
Some(def @ def_struct(*)) => {
43464349
self.record_def(pattern.id, def);
@@ -4373,7 +4376,7 @@ impl Resolver {
43734376

43744377
pat_enum(ref path, _) => {
43754378
// This must be an enum variant, struct or const.
4376-
match self.resolve_path(path, ValueNS, false, visitor) {
4379+
match self.resolve_path(pat_id, path, ValueNS, false, visitor) {
43774380
Some(def @ def_fn(*)) |
43784381
Some(def @ def_variant(*)) |
43794382
Some(def @ def_struct(*)) |
@@ -4410,7 +4413,7 @@ impl Resolver {
44104413
}
44114414

44124415
pat_struct(ref path, _, _) => {
4413-
match self.resolve_path(path, TypeNS, false, visitor) {
4416+
match self.resolve_path(pat_id, path, TypeNS, false, visitor) {
44144417
Some(def_ty(class_id))
44154418
if self.structs.contains(&class_id) => {
44164419
let class_def = def_struct(class_id);
@@ -4484,6 +4487,7 @@ impl Resolver {
44844487
/// If `check_ribs` is true, checks the local definitions first; i.e.
44854488
/// doesn't skip straight to the containing module.
44864489
pub fn resolve_path(@mut self,
4490+
id: node_id,
44874491
path: &Path,
44884492
namespace: Namespace,
44894493
check_ribs: bool,
@@ -4500,16 +4504,24 @@ impl Resolver {
45004504
namespace);
45014505
}
45024506

4507+
let unqualified_def = self.resolve_identifier(
4508+
*path.idents.last(), namespace, check_ribs, path.span);
4509+
45034510
if path.idents.len() > 1 {
4504-
return self.resolve_module_relative_path(path,
4505-
self.xray_context,
4506-
namespace);
4511+
let def = self.resolve_module_relative_path(
4512+
path, self.xray_context, namespace);
4513+
match (def, unqualified_def) {
4514+
(Some(d), Some(ud)) if d == ud => {
4515+
self.session.add_lint(unnecessary_qualification,
4516+
id, path.span,
4517+
~"unnecessary qualification");
4518+
}
4519+
_ => ()
4520+
}
4521+
return def;
45074522
}
45084523

4509-
return self.resolve_identifier(*path.idents.last(),
4510-
namespace,
4511-
check_ribs,
4512-
path.span);
4524+
return unqualified_def;
45134525
}
45144526

45154527
pub fn resolve_identifier(@mut self,
@@ -4920,7 +4932,7 @@ impl Resolver {
49204932
// This is a local path in the value namespace. Walk through
49214933
// scopes looking for it.
49224934

4923-
match self.resolve_path(path, ValueNS, true, visitor) {
4935+
match self.resolve_path(expr.id, path, ValueNS, true, visitor) {
49244936
Some(def) => {
49254937
// Write the result into the def map.
49264938
debug!("(resolving expr) resolved `%s`",
@@ -4987,7 +4999,7 @@ impl Resolver {
49874999

49885000
expr_struct(ref path, _, _) => {
49895001
// Resolve the path to the structure it goes to.
4990-
match self.resolve_path(path, TypeNS, false, visitor) {
5002+
match self.resolve_path(expr.id, path, TypeNS, false, visitor) {
49915003
Some(def_ty(class_id)) | Some(def_struct(class_id))
49925004
if self.structs.contains(&class_id) => {
49935005
let class_def = def_struct(class_id);

src/libsyntax/ast_util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> {
462462
},
463463

464464
visit_ty: |ty, (t, vt)| {
465+
vfn(ty.id, copy t);
465466
match ty.node {
466467
ty_path(_, _, id) => vfn(id, copy t),
467468
_ => { /* fall through */ }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[deny(unnecessary_qualification)];
12+
13+
mod foo {
14+
pub fn bar() {}
15+
}
16+
17+
fn main() {
18+
use foo::bar;
19+
foo::bar(); //~ ERROR: unnecessary qualification
20+
}

0 commit comments

Comments
 (0)