]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_lint/builtin.rs
Imported Upstream version 1.1.0+dfsg1
[rustc.git] / src / librustc_lint / builtin.rs
index 141eb3fd1ae0fd745caa9504cc4c5487f6b44f1d..8d555240e707b31751facd1d4c5f8fbca1e010eb 100644 (file)
@@ -910,9 +910,8 @@ impl NonSnakeCase {
         words.connect("_")
     }
 
-    fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
-        fn is_snake_case(ident: ast::Ident) -> bool {
-            let ident = token::get_ident(ident);
+    fn check_snake_case(&self, cx: &Context, sort: &str, name: &str, span: Option<Span>) {
+        fn is_snake_case(ident: &str) -> bool {
             if ident.is_empty() {
                 return true;
             }
@@ -924,6 +923,8 @@ impl NonSnakeCase {
                 allow_underscore = match c {
                     '_' if !allow_underscore => return false,
                     '_' => false,
+                    // It would be more obvious to use `c.is_lowercase()`,
+                    // but some characters do not have a lowercase form
                     c if !c.is_uppercase() => true,
                     _ => return false,
                 };
@@ -931,18 +932,18 @@ impl NonSnakeCase {
             })
         }
 
-        let s = token::get_ident(ident);
-
-        if !is_snake_case(ident) {
-            let sc = NonSnakeCase::to_snake_case(&s);
-            if sc != &s[..] {
-                cx.span_lint(NON_SNAKE_CASE, span,
-                    &*format!("{} `{}` should have a snake case name such as `{}`",
-                            sort, s, sc));
+        if !is_snake_case(name) {
+            let sc = NonSnakeCase::to_snake_case(name);
+            let msg = if sc != name {
+                format!("{} `{}` should have a snake case name such as `{}`",
+                        sort, name, sc)
             } else {
-                cx.span_lint(NON_SNAKE_CASE, span,
-                    &*format!("{} `{}` should have a snake case name",
-                            sort, s));
+                format!("{} `{}` should have a snake case name",
+                        sort, name)
+            };
+            match span {
+                Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
+                None => cx.lint(NON_SNAKE_CASE, &msg),
             }
         }
     }
@@ -953,21 +954,31 @@ impl LintPass for NonSnakeCase {
         lint_array!(NON_SNAKE_CASE)
     }
 
+    fn check_crate(&mut self, cx: &Context, cr: &ast::Crate) {
+        let attr_crate_name = cr.attrs.iter().find(|at| at.check_name("crate_name"))
+                                      .and_then(|at| at.value_str().map(|s| (at, s)));
+        if let Some(ref name) = cx.tcx.sess.opts.crate_name {
+            self.check_snake_case(cx, "crate", name, None);
+        } else if let Some((attr, ref name)) = attr_crate_name {
+            self.check_snake_case(cx, "crate", name, Some(attr.span));
+        }
+    }
+
     fn check_fn(&mut self, cx: &Context,
                 fk: visit::FnKind, _: &ast::FnDecl,
                 _: &ast::Block, span: Span, id: ast::NodeId) {
         match fk {
             visit::FkMethod(ident, _, _) => match method_context(cx, id, span) {
                 MethodContext::PlainImpl => {
-                    self.check_snake_case(cx, "method", ident, span)
+                    self.check_snake_case(cx, "method", &token::get_ident(ident), Some(span))
                 },
                 MethodContext::TraitDefaultImpl => {
-                    self.check_snake_case(cx, "trait method", ident, span)
+                    self.check_snake_case(cx, "trait method", &token::get_ident(ident), Some(span))
                 },
                 _ => (),
             },
             visit::FkItemFn(ident, _, _, _, _) => {
-                self.check_snake_case(cx, "function", ident, span)
+                self.check_snake_case(cx, "function", &token::get_ident(ident), Some(span))
             },
             _ => (),
         }
@@ -975,25 +986,27 @@ impl LintPass for NonSnakeCase {
 
     fn check_item(&mut self, cx: &Context, it: &ast::Item) {
         if let ast::ItemMod(_) = it.node {
-            self.check_snake_case(cx, "module", it.ident, it.span);
+            self.check_snake_case(cx, "module", &token::get_ident(it.ident), Some(it.span));
         }
     }
 
     fn check_trait_item(&mut self, cx: &Context, trait_item: &ast::TraitItem) {
         if let ast::MethodTraitItem(_, None) = trait_item.node {
-            self.check_snake_case(cx, "trait method", trait_item.ident, trait_item.span);
+            self.check_snake_case(cx, "trait method", &token::get_ident(trait_item.ident),
+                                  Some(trait_item.span));
         }
     }
 
     fn check_lifetime_def(&mut self, cx: &Context, t: &ast::LifetimeDef) {
-        self.check_snake_case(cx, "lifetime", t.lifetime.name.ident(), t.lifetime.span);
+        self.check_snake_case(cx, "lifetime", &token::get_ident(t.lifetime.name.ident()),
+                              Some(t.lifetime.span));
     }
 
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         if let &ast::PatIdent(_, ref path1, _) = &p.node {
             let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
             if let Some(def::DefLocal(_)) = def {
-                self.check_snake_case(cx, "variable", path1.node, p.span);
+                self.check_snake_case(cx, "variable", &token::get_ident(path1.node), Some(p.span));
             }
         }
     }
@@ -1002,7 +1015,8 @@ impl LintPass for NonSnakeCase {
                         _: ast::Ident, _: &ast::Generics, _: ast::NodeId) {
         for sf in &s.fields {
             if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node {
-                self.check_snake_case(cx, "structure field", ident, sf.span);
+                self.check_snake_case(cx, "structure field", &token::get_ident(ident),
+                                      Some(sf.span));
             }
         }
     }
@@ -1054,6 +1068,26 @@ impl LintPass for NonUpperCaseGlobals {
         }
     }
 
+    fn check_trait_item(&mut self, cx: &Context, ti: &ast::TraitItem) {
+        match ti.node {
+            ast::ConstTraitItem(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ti.ident, ti.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &Context, ii: &ast::ImplItem) {
+        match ii.node {
+            ast::ConstImplItem(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ii.ident, ii.span);
+            }
+            _ => {}
+        }
+    }
+
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
@@ -1570,8 +1604,9 @@ impl LintPass for MissingDoc {
         if self.private_traits.contains(&trait_item.id) { return }
 
         let desc = match trait_item.node {
+            ast::ConstTraitItem(..) => "an associated constant",
             ast::MethodTraitItem(..) => "a trait method",
-            ast::TypeTraitItem(..) => "an associated type"
+            ast::TypeTraitItem(..) => "an associated type",
         };
 
         self.check_missing_docs_attrs(cx, Some(trait_item.id),
@@ -1586,9 +1621,10 @@ impl LintPass for MissingDoc {
         }
 
         let desc = match impl_item.node {
+            ast::ConstImplItem(..) => "an associated constant",
             ast::MethodImplItem(..) => "a method",
             ast::TypeImplItem(_) => "an associated type",
-            ast::MacImplItem(_) => "an impl item macro"
+            ast::MacImplItem(_) => "an impl item macro",
         };
         self.check_missing_docs_attrs(cx, Some(impl_item.id),
                                       &impl_item.attrs,
@@ -1709,17 +1745,16 @@ impl LintPass for MissingDebugImplementations {
         };
 
         if self.impling_types.is_none() {
-            let impls = cx.tcx.trait_impls.borrow();
-            let impls = match impls.get(&debug) {
-                Some(impls) => {
-                    impls.borrow().iter()
-                         .filter(|d| d.krate == ast::LOCAL_CRATE)
-                         .filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)))
-                         .map(|d| d.node)
-                         .collect()
+            let debug_def = ty::lookup_trait_def(cx.tcx, debug);
+            let mut impls = NodeSet();
+            debug_def.for_each_impl(cx.tcx, |d| {
+                if d.krate == ast::LOCAL_CRATE {
+                    if let Some(ty_def) = ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)) {
+                        impls.insert(ty_def.node);
+                    }
                 }
-                None => NodeSet(),
-            };
+            });
+
             self.impling_types = Some(impls);
             debug!("{:?}", self.impling_types);
         }
@@ -1886,14 +1921,13 @@ impl LintPass for UnconditionalRecursion {
                 continue;
             }
             // add the successors of this node to explore the graph further.
-            cfg.graph.each_outgoing_edge(idx, |_, edge| {
+            for (_, edge) in cfg.graph.outgoing_edges(idx) {
                 let target_idx = edge.target();
                 let target_cfg_id = target_idx.node_id();
                 if !visited.contains(&target_cfg_id) {
                     work_queue.push(target_idx)
                 }
-                true
-            });
+            }
         }
 
         // Check the number of self calls because a function that