(index<- )        ./librustc/middle/lint.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
    1  // Copyright 2012-2014 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  //! A 'lint' check is a kind of miscellaneous constraint that a user _might_
   12  //! want to enforce, but might reasonably want to permit as well, on a
   13  //! module-by-module basis. They contrast with static constraints enforced by
   14  //! other phases of the compiler, which are generally required to hold in order
   15  //! to compile the program at all.
   16  //!
   17  //! The lint checking is all consolidated into one pass which runs just before
   18  //! translation to LLVM bytecode. Throughout compilation, lint warnings can be
   19  //! added via the `add_lint` method on the Session structure. This requires a
   20  //! span and an id of the node that the lint is being added to. The lint isn't
   21  //! actually emitted at that time because it is unknown what the actual lint
   22  //! level at that location is.
   23  //!
   24  //! To actually emit lint warnings/errors, a separate pass is used just before
   25  //! translation. A context keeps track of the current state of all lint levels.
   26  //! Upon entering a node of the ast which can modify the lint settings, the
   27  //! previous lint state is pushed onto a stack and the ast is then recursed
   28  //! upon.  As the ast is traversed, this keeps track of the current lint level
   29  //! for all lint attributes.
   30  //!
   31  //! To add a new lint warning, all you need to do is to either invoke `add_lint`
   32  //! on the session at the appropriate time, or write a few linting functions and
   33  //! modify the Context visitor appropriately. If you're adding lints from the
   34  //! Context itself, span_lint should be used instead of add_lint.
   35  
   36  #![allow(non_camel_case_types)]
   37  
   38  use driver::session;
   39  use metadata::csearch;
   40  use middle::dead::DEAD_CODE_LINT_STR;
   41  use middle::pat_util;
   42  use middle::privacy;
   43  use middle::trans::adt; // for `adt::is_ffi_safe`
   44  use middle::ty;
   45  use middle::typeck::astconv::{ast_ty_to_ty, AstConv};
   46  use middle::typeck::infer;
   47  use middle::typeck;
   48  use util::ppaux::{ty_to_str};
   49  
   50  use std::cmp;
   51  use collections::HashMap;
   52  use std::i16;
   53  use std::i32;
   54  use std::i64;
   55  use std::i8;
   56  use std::rc::Rc;
   57  use std::to_str::ToStr;
   58  use std::u16;
   59  use std::u32;
   60  use std::u64;
   61  use std::u8;
   62  use collections::SmallIntMap;
   63  use syntax::abi;
   64  use syntax::ast_map;
   65  use syntax::ast_util::IdVisitingOperation;
   66  use syntax::attr::{AttrMetaMethods, AttributeMethods};
   67  use syntax::attr;
   68  use syntax::codemap::Span;
   69  use syntax::parse::token::InternedString;
   70  use syntax::parse::token;
   71  use syntax::visit::Visitor;
   72  use syntax::{ast, ast_util, visit};
   73  
   74  #[deriving(Clone, Eq, Ord, TotalEq, TotalOrd)]
   75  pub enum Lint {
   76      CTypes,
   77      UnusedImports,
   78      UnnecessaryQualification,
   79      WhileTrue,
   80      PathStatement,
   81      UnrecognizedLint,
   82      NonCamelCaseTypes,
   83      NonUppercaseStatics,
   84      NonUppercasePatternStatics,
   85      UppercaseVariables,
   86      UnnecessaryParens,
   87      TypeLimits,
   88      TypeOverflow,
   89      UnusedUnsafe,
   90      UnsafeBlock,
   91      AttributeUsage,
   92      UnknownFeatures,
   93      UnknownCrateType,
   94      UnsignedNegate,
   95  
   96      ManagedHeapMemory,
   97      OwnedHeapMemory,
   98      HeapMemory,
   99  
  100      UnusedVariable,
  101      DeadAssignment,
  102      UnusedMut,
  103      UnnecessaryAllocation,
  104      DeadCode,
  105      VisiblePrivateTypes,
  106      UnnecessaryTypecast,
  107  
  108      MissingDoc,
  109      UnreachableCode,
  110  
  111      Deprecated,
  112      Experimental,
  113      Unstable,
  114  
  115      UnusedMustUse,
  116      UnusedResult,
  117  
  118      DeprecatedOwnedVector,
  119  
  120      Warnings,
  121  
  122      RawPointerDeriving,
  123  }
  124  
  125  pub fn level_to_str(lvlevel) -> &'static str {
  126      match lv {
  127        allow => "allow",
  128        warn => "warn",
  129        deny => "deny",
  130        forbid => "forbid"
  131      }
  132  }
  133  
  134  #[deriving(Clone, Eq, Ord, TotalEq, TotalOrd)]
  135  pub enum level {
  136      allow, warn, deny, forbid
  137  }
  138  
  139  #[deriving(Clone, Eq, Ord, TotalEq, TotalOrd)]
  140  pub struct LintSpec {
  141      pub default: level,
  142      pub lint: Lint,
  143      pub desc: &'static str,
  144  }
  145  
  146  pub type LintDict = HashMap<&'static str, LintSpec>;
  147  
  148  #[deriving(Eq)]
  149  enum LintSource {
  150      Node(Span),
  151      Default,
  152      CommandLine
  153  }
  154  
  155  static lint_table: &'static [(&'static str, LintSpec)] = &[
  156      ("ctypes",
  157       LintSpec {
  158          lint: CTypes,
  159          desc: "proper use of libc types in foreign modules",
  160          default: warn
  161       }),
  162  
  163      ("unused_imports",
  164       LintSpec {
  165          lint: UnusedImports,
  166          desc: "imports that are never used",
  167          default: warn
  168       }),
  169  
  170      ("unnecessary_qualification",
  171       LintSpec {
  172          lint: UnnecessaryQualification,
  173          desc: "detects unnecessarily qualified names",
  174          default: allow
  175       }),
  176  
  177      ("while_true",
  178       LintSpec {
  179          lint: WhileTrue,
  180          desc: "suggest using `loop { }` instead of `while true { }`",
  181          default: warn
  182       }),
  183  
  184      ("path_statement",
  185       LintSpec {
  186          lint: PathStatement,
  187          desc: "path statements with no effect",
  188          default: warn
  189       }),
  190  
  191      ("unrecognized_lint",
  192       LintSpec {
  193          lint: UnrecognizedLint,
  194          desc: "unrecognized lint attribute",
  195          default: warn
  196       }),
  197  
  198      ("non_camel_case_types",
  199       LintSpec {
  200          lint: NonCamelCaseTypes,
  201          desc: "types, variants and traits should have camel case names",
  202          default: warn
  203       }),
  204  
  205      ("non_uppercase_statics",
  206       LintSpec {
  207           lint: NonUppercaseStatics,
  208           desc: "static constants should have uppercase identifiers",
  209           default: allow
  210       }),
  211  
  212      ("non_uppercase_pattern_statics",
  213       LintSpec {
  214           lint: NonUppercasePatternStatics,
  215           desc: "static constants in match patterns should be all caps",
  216           default: warn
  217       }),
  218  
  219      ("uppercase_variables",
  220       LintSpec {
  221           lint: UppercaseVariables,
  222           desc: "variable and structure field names should start with a lowercase character",
  223           default: warn
  224       }),
  225  
  226       ("unnecessary_parens",
  227       LintSpec {
  228          lint: UnnecessaryParens,
  229          desc: "`if`, `match`, `while` and `return` do not need parentheses",
  230          default: warn
  231       }),
  232  
  233      ("managed_heap_memory",
  234       LintSpec {
  235          lint: ManagedHeapMemory,
  236          desc: "use of managed (type) heap memory",
  237          default: allow
  238       }),
  239  
  240      ("owned_heap_memory",
  241       LintSpec {
  242          lint: OwnedHeapMemory,
  243          desc: "use of owned (Box type) heap memory",
  244          default: allow
  245       }),
  246  
  247      ("heap_memory",
  248       LintSpec {
  249          lint: HeapMemory,
  250          desc: "use of any (Box type or @ type) heap memory",
  251          default: allow
  252       }),
  253  
  254      ("type_limits",
  255       LintSpec {
  256          lint: TypeLimits,
  257          desc: "comparisons made useless by limits of the types involved",
  258          default: warn
  259       }),
  260  
  261      ("type_overflow",
  262       LintSpec {
  263          lint: TypeOverflow,
  264          desc: "literal out of range for its type",
  265          default: warn
  266       }),
  267  
  268  
  269      ("unused_unsafe",
  270       LintSpec {
  271          lint: UnusedUnsafe,
  272          desc: "unnecessary use of an `unsafe` block",
  273          default: warn
  274      }),
  275  
  276      ("unsafe_block",
  277       LintSpec {
  278          lint: UnsafeBlock,
  279          desc: "usage of an `unsafe` block",
  280          default: allow
  281      }),
  282  
  283      ("attribute_usage",
  284       LintSpec {
  285          lint: AttributeUsage,
  286          desc: "detects bad use of attributes",
  287          default: warn
  288      }),
  289  
  290      ("unused_variable",
  291       LintSpec {
  292          lint: UnusedVariable,
  293          desc: "detect variables which are not used in any way",
  294          default: warn
  295      }),
  296  
  297      ("dead_assignment",
  298       LintSpec {
  299          lint: DeadAssignment,
  300          desc: "detect assignments that will never be read",
  301          default: warn
  302      }),
  303  
  304      ("unnecessary_typecast",
  305       LintSpec {
  306          lint: UnnecessaryTypecast,
  307          desc: "detects unnecessary type casts, that can be removed",
  308          default: allow,
  309      }),
  310  
  311      ("unused_mut",
  312       LintSpec {
  313          lint: UnusedMut,
  314          desc: "detect mut variables which don't need to be mutable",
  315          default: warn
  316      }),
  317  
  318      ("unnecessary_allocation",
  319       LintSpec {
  320          lint: UnnecessaryAllocation,
  321          desc: "detects unnecessary allocations that can be eliminated",
  322          default: warn
  323      }),
  324  
  325      (DEAD_CODE_LINT_STR,
  326       LintSpec {
  327          lint: DeadCode,
  328          desc: "detect piece of code that will never be used",
  329          default: warn
  330      }),
  331      ("visible_private_types",
  332       LintSpec {
  333          lint: VisiblePrivateTypes,
  334          desc: "detect use of private types in exported type signatures",
  335          default: warn
  336      }),
  337  
  338      ("missing_doc",
  339       LintSpec {
  340          lint: MissingDoc,
  341          desc: "detects missing documentation for public members",
  342          default: allow
  343      }),
  344  
  345      ("unreachable_code",
  346       LintSpec {
  347          lint: UnreachableCode,
  348          desc: "detects unreachable code",
  349          default: warn
  350      }),
  351  
  352      ("deprecated",
  353       LintSpec {
  354          lint: Deprecated,
  355          desc: "detects use of #[deprecated] items",
  356          default: warn
  357      }),
  358  
  359      ("experimental",
  360       LintSpec {
  361          lint: Experimental,
  362          desc: "detects use of #[experimental] items",
  363          default: warn
  364      }),
  365  
  366      ("unstable",
  367       LintSpec {
  368          lint: Unstable,
  369          desc: "detects use of #[unstable] items (incl. items with no stability attribute)",
  370          default: allow
  371      }),
  372  
  373      ("warnings",
  374       LintSpec {
  375          lint: Warnings,
  376          desc: "mass-change the level for lints which produce warnings",
  377          default: warn
  378      }),
  379  
  380      ("unknown_features",
  381       LintSpec {
  382          lint: UnknownFeatures,
  383          desc: "unknown features found in crate-level #[feature] directives",
  384          default: deny,
  385      }),
  386  
  387      ("unknown_crate_type",
  388      LintSpec {
  389          lint: UnknownCrateType,
  390          desc: "unknown crate type found in #[crate_type] directive",
  391          default: deny,
  392      }),
  393  
  394      ("unsigned_negate",
  395      LintSpec {
  396          lint: UnsignedNegate,
  397          desc: "using an unary minus operator on unsigned type",
  398          default: warn
  399      }),
  400  
  401      ("unused_must_use",
  402      LintSpec {
  403          lint: UnusedMustUse,
  404          desc: "unused result of a type flagged as #[must_use]",
  405          default: warn,
  406      }),
  407  
  408      ("unused_result",
  409      LintSpec {
  410          lint: UnusedResult,
  411          desc: "unused result of an expression in a statement",
  412          default: allow,
  413      }),
  414  
  415      ("deprecated_owned_vector",
  416       LintSpec {
  417          lint: DeprecatedOwnedVector,
  418          desc: "use of a `~[T]` vector",
  419          default: allow,
  420      }),
  421  
  422      ("raw_pointer_deriving",
  423       LintSpec {
  424          lint: RawPointerDeriving,
  425          desc: "uses of #[deriving] with raw pointers are rarely correct",
  426          default: warn,
  427      }),
  428  ];
  429  
  430  /*
  431    Pass names should not contain a '-', as the compiler normalizes
  432    '-' to '_' in command-line flags
  433   */
  434  pub fn get_lint_dict() -> LintDict {
  435      lint_table.iter().map(|&(k, v)| (k, v)).collect()
  436  }
  437  
  438  struct Context<'a> {
  439      // All known lint modes (string versions)
  440      dict: LintDict,
  441      // Current levels of each lint warning
  442      cur: SmallIntMap<(level, LintSource)>,
  443      // context we're checking in (used to access fields like sess)
  444      tcx: &'a ty::ctxt,
  445      // Items exported by the crate; used by the missing_doc lint.
  446      exported_items: &'a privacy::ExportedItems,
  447      // The id of the current `ast::StructDef` being walked.
  448      cur_struct_def_id: ast::NodeId,
  449      // Whether some ancestor of the current node was marked
  450      // #[doc(hidden)].
  451      is_doc_hidden: bool,
  452  
  453      // When recursing into an attributed node of the ast which modifies lint
  454      // levels, this stack keeps track of the previous lint levels of whatever
  455      // was modified.
  456      lint_stack: Vec<(Lint, level, LintSource)> ,
  457  
  458      // id of the last visited negated expression
  459      negated_expr_id: ast::NodeId
  460  }
  461  
  462  impl<'a> Context<'a> {
  463      fn get_level(&self, lintLint) -> level {
  464          match self.cur.find(&(lint as uint)) {
  465            Some(&(lvl, _)) => lvl,
  466            None => allow
  467          }
  468      }
  469  
  470      fn get_source(&self, lintLint) -> LintSource {
  471          match self.cur.find(&(lint as uint)) {
  472            Some(&(_, src)) => src,
  473            None => Default
  474          }
  475      }
  476  
  477      fn set_level(&mut self, lintLint, levellevel, srcLintSource) {
  478          if level == allow {
  479              self.cur.remove(&(lint as uint));
  480          } else {
  481              self.cur.insert(lint as uint, (level, src));
  482          }
  483      }
  484  
  485      fn lint_to_str(&self, lintLint) -> &'static str {
  486          for (k, v) in self.dict.iter() {
  487              if v.lint == lint {
  488                  return *k;
  489              }
  490          }
  491          fail!("unregistered lint {:?}", lint);
  492      }
  493  
  494      fn span_lint(&self, lintLint, spanSpan, msg&str) {
  495          let (level, src) = match self.cur.find(&(lint as uint)) {
  496              None => { return }
  497              Some(&(warn, src)) => (self.get_level(Warnings), src),
  498              Some(&pair) => pair,
  499          };
  500          if level == allow { return }
  501  
  502          let mut note = None;
  503          let msg = match src {
  504              Default => {
  505                  format!("{}, \\#[{}({})] on by default", msg,
  506                      level_to_str(level), self.lint_to_str(lint))
  507              },
  508              CommandLine => {
  509                  format!("{} [-{} {}]", msg,
  510                      match level {
  511                          warn => 'W', deny => 'D', forbid => 'F',
  512                          allow => fail!()
  513                      }, self.lint_to_str(lint).replace("_", "-"))
  514              },
  515              Node(src) => {
  516                  note = Some(src);
  517                  msg.to_str()
  518              }
  519          };
  520          match level {
  521              warn =>          { self.tcx.sess.span_warn(span, msg); }
  522              deny | forbid => { self.tcx.sess.span_err(span, msg);  }
  523              allow => fail!(),
  524          }
  525  
  526          for &span in note.iter() {
  527              self.tcx.sess.span_note(span, "lint level defined here");
  528          }
  529      }
  530  
  531      /**
  532       * Merge the lints specified by any lint attributes into the
  533       * current lint context, call the provided function, then reset the
  534       * lints in effect to their previous state.
  535       */
  536      fn with_lint_attrs(&mut self,
  537                         attrs&[ast::Attribute],
  538                         f|&mut Context|) {
  539          // Parse all of the lint attributes, and then add them all to the
  540          // current dictionary of lint information. Along the way, keep a history
  541          // of what we changed so we can roll everything back after invoking the
  542          // specified closure
  543          let mut pushed = 0u;
  544          each_lint(&self.tcx.sess, attrs, |meta, level, lintname| {
  545              match self.dict.find_equiv(&lintname) {
  546                  None => {
  547                      self.span_lint(
  548                          UnrecognizedLint,
  549                          meta.span,
  550                          format!("unknown `{}` attribute: `{}`",
  551                          level_to_str(level), lintname));
  552                  }
  553                  Some(lint) => {
  554                      let lint = lint.lint;
  555                      let now = self.get_level(lint);
  556                      if now == forbid && level != forbid {
  557                          self.tcx.sess.span_err(meta.span,
  558                          format!("{}({}) overruled by outer forbid({})",
  559                          level_to_str(level),
  560                          lintname, lintname));
  561                      } else if now != level {
  562                          let src = self.get_source(lint);
  563                          self.lint_stack.push((lint, now, src));
  564                          pushed += 1;
  565                          self.set_level(lint, level, Node(meta.span));
  566                      }
  567                  }
  568              }
  569              true
  570          });
  571  
  572          let old_is_doc_hidden = self.is_doc_hidden;
  573          self.is_doc_hidden =
  574              self.is_doc_hidden ||
  575              attrs.iter()
  576                   .any(|attr| {
  577                       attr.name().equiv(&("doc")) &&
  578                       match attr.meta_item_list() {
  579                           None => false,
  580                           Some(l) => {
  581                               attr::contains_name(l.as_slice(), "hidden")
  582                           }
  583                       }
  584                   });
  585  
  586          f(self);
  587  
  588          // rollback
  589          self.is_doc_hidden = old_is_doc_hidden;
  590          for _ in range(0, pushed) {
  591              let (lint, lvl, src) = self.lint_stack.pop().unwrap();
  592              self.set_level(lint, lvl, src);
  593          }
  594      }
  595  
  596      fn visit_ids(&self, f|&mut ast_util::IdVisitor<Context>|) {
  597          let mut v = ast_util::IdVisitor {
  598              operation: self,
  599              pass_through_items: false,
  600              visited_outermost: false,
  601          };
  602          f(&mut v);
  603      }
  604  }
  605  
  606  // Check that every lint from the list of attributes satisfies `f`.
  607  // Return true if that's the case. Otherwise return false.
  608  pub fn each_lint(sess: &session::Session,
  609                   attrs: &[ast::Attribute],
  610                   f: |@ast::MetaItem, level, InternedString-> bool)
  611                   -> bool {
  612      let xs = [allow, warn, deny, forbid];
  613      for &level in xs.iter() {
  614          let level_name = level_to_str(level);
  615          for attr in attrs.iter().filter(|m| m.name().equiv(&level_name)) {
  616              let meta = attr.node.value;
  617              let metas = match meta.node {
  618                  ast::MetaList(_, ref metas) => metas,
  619                  _ => {
  620                      sess.span_err(meta.span, "malformed lint attribute");
  621                      continue;
  622                  }
  623              };
  624              for meta in metas.iter() {
  625                  match meta.node {
  626                      ast::MetaWord(ref lintname) => {
  627                          if !f(*meta, level, (*lintname).clone()) {
  628                              return false;
  629                          }
  630                      }
  631                      _ => {
  632                          sess.span_err(meta.span, "malformed lint attribute");
  633                      }
  634                  }
  635              }
  636          }
  637      }
  638      true
  639  }
  640  
  641  // Check from a list of attributes if it contains the appropriate
  642  // `#[level(lintname)]` attribute (e.g. `#[allow(dead_code)]).
  643  pub fn contains_lint(attrs: &[ast::Attribute],
  644                       levellevel,
  645                       lintname: &'static str)
  646                       -> bool {
  647      let level_name = level_to_str(level);
  648      for attr in attrs.iter().filter(|m| m.name().equiv(&level_name)) {
  649          if attr.meta_item_list().is_none() {
  650              continue
  651          }
  652          let list = attr.meta_item_list().unwrap();
  653          for meta_item in list.iter() {
  654              if meta_item.name().equiv(&lintname) {
  655                  return true;
  656              }
  657          }
  658      }
  659      false
  660  }
  661  
  662  fn check_while_true_expr(cx: &Context, e: &ast::Expr) {
  663      match e.node {
  664          ast::ExprWhile(cond, _) => {
  665              match cond.node {
  666                  ast::ExprLit(lit) => {
  667                      match lit.node {
  668                          ast::LitBool(true) => {
  669                              cx.span_lint(WhileTrue,
  670                                           e.span,
  671                                           "denote infinite loops with loop \
  672                                            { ... }");
  673                          }
  674                          _ => {}
  675                      }
  676                  }
  677                  _ => ()
  678              }
  679          }
  680          _ => ()
  681      }
  682  }
  683  impl<'a> AstConv for Context<'a>{
  684      fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
  685  
  686      fn get_item_ty(&self, idast::DefId) -> ty::ty_param_bounds_and_ty {
  687          ty::lookup_item_type(self.tcx, id)
  688      }
  689  
  690      fn get_trait_def(&self, idast::DefId) -> Rc<ty::TraitDef> {
  691          ty::lookup_trait_def(self.tcx, id)
  692      }
  693  
  694      fn ty_infer(&self, _spanSpan) -> ty::t {
  695          infer::new_infer_ctxt(self.tcx).next_ty_var()
  696      }
  697  }
  698  
  699  
  700  fn check_unused_casts(cx: &Context, e: &ast::Expr) {
  701      return match e.node {
  702          ast::ExprCast(expr, ty) => {
  703              let t_t = ast_ty_to_ty(cx, &infer::new_infer_ctxt(cx.tcx), ty);
  704              if  ty::get(ty::expr_ty(cx.tcx, expr)).sty == ty::get(t_t).sty {
  705                  cx.span_lint(UnnecessaryTypecast, ty.span,
  706                               "unnecessary type cast");
  707              }
  708          }
  709          _ => ()
  710      };
  711  }
  712  
  713  fn check_type_limits(cx: &Context, e: &ast::Expr) {
  714      return match e.node {
  715          ast::ExprUnary(ast::UnNeg, ex) => {
  716              match ex.node  {
  717                  ast::ExprLit(lit) => {
  718                      match lit.node {
  719                          ast::LitUint(..) => {
  720                              cx.span_lint(UnsignedNegate, e.span,
  721                                           "negation of unsigned int literal may be unintentional");
  722                          },
  723                          _ => ()
  724                      }
  725                  },
  726                  _ => {
  727                      let t = ty::expr_ty(cx.tcx, ex);
  728                      match ty::get(t).sty {
  729                          ty::ty_uint(_) => {
  730                              cx.span_lint(UnsignedNegate, e.span,
  731                                           "negation of unsigned int variable may be unintentional");
  732                          },
  733                          _ => ()
  734                      }
  735                  }
  736              }
  737          },
  738          ast::ExprBinary(binop, l, r) => {
  739              if is_comparison(binop) && !check_limits(cx.tcx, binop, l, r) {
  740                  cx.span_lint(TypeLimits, e.span,
  741                               "comparison is useless due to type limits");
  742              }
  743          },
  744          ast::ExprLit(lit) => {
  745              match ty::get(ty::expr_ty(cx.tcx, e)).sty {
  746                  ty::ty_int(t) => {
  747                      let int_type = if t == ast::TyI {
  748                          cx.tcx.sess.targ_cfg.int_type
  749                      } else { t };
  750                      let (min, max) = int_ty_range(int_type);
  751                      let mut lit_vali64 = match lit.node {
  752                          ast::LitInt(v, _) => v,
  753                          ast::LitUint(v, _) => v as i64,
  754                          ast::LitIntUnsuffixed(v) => v,
  755                          _ => fail!()
  756                      };
  757                      if cx.negated_expr_id == e.id {
  758                          lit_val *= -1;
  759                      }
  760                      if  lit_val < min || lit_val > max {
  761                          cx.span_lint(TypeOverflow, e.span,
  762                                       "literal out of range for its type");
  763                      }
  764                  },
  765                  ty::ty_uint(t) => {
  766                      let uint_type = if t == ast::TyU {
  767                          cx.tcx.sess.targ_cfg.uint_type
  768                      } else { t };
  769                      let (min, max) = uint_ty_range(uint_type);
  770                      let lit_valu64 = match lit.node {
  771                          ast::LitInt(v, _) => v as u64,
  772                          ast::LitUint(v, _) => v,
  773                          ast::LitIntUnsuffixed(v) => v as u64,
  774                          _ => fail!()
  775                      };
  776                      if  lit_val < min || lit_val > max {
  777                          cx.span_lint(TypeOverflow, e.span,
  778                                       "literal out of range for its type");
  779                      }
  780                  },
  781  
  782                  _ => ()
  783              };
  784          },
  785          _ => ()
  786      };
  787  
  788      fn is_valid<T:cmp::Ord>(binopast::BinOp, vT,
  789                              minT, maxT) -> bool {
  790          match binop {
  791              ast::BiLt => v >  min && v <= max,
  792              ast::BiLe => v >= min && v <  max,
  793              ast::BiGt => v >= min && v <  max,
  794              ast::BiGe => v >  min && v <= max,
  795              ast::BiEq | ast::BiNe => v >= min && v <= max,
  796              _ => fail!()
  797          }
  798      }
  799  
  800      fn rev_binop(binopast::BinOp) -> ast::BinOp {
  801          match binop {
  802              ast::BiLt => ast::BiGt,
  803              ast::BiLe => ast::BiGe,
  804              ast::BiGt => ast::BiLt,
  805              ast::BiGe => ast::BiLe,
  806              _ => binop
  807          }
  808      }
  809  
  810      // for int & uint, be conservative with the warnings, so that the
  811      // warnings are consistent between 32- and 64-bit platforms
  812      fn int_ty_range(int_tyast::IntTy) -> (i64, i64) {
  813          match int_ty {
  814              ast::TyI =>    (i64::MIN,        i64::MAX),
  815              ast::TyI8 =>   (i8::MIN  as i64, i8::MAX  as i64),
  816              ast::TyI16 =>  (i16::MIN as i64, i16::MAX as i64),
  817              ast::TyI32 =>  (i32::MIN as i64, i32::MAX as i64),
  818              ast::TyI64 =>  (i64::MIN,        i64::MAX)
  819          }
  820      }
  821  
  822      fn uint_ty_range(uint_tyast::UintTy) -> (u64, u64) {
  823          match uint_ty {
  824              ast::TyU =>   (u64::MIN,         u64::MAX),
  825              ast::TyU8 =>  (u8::MIN   as u64, u8::MAX   as u64),
  826              ast::TyU16 => (u16::MIN  as u64, u16::MAX  as u64),
  827              ast::TyU32 => (u32::MIN  as u64, u32::MAX  as u64),
  828              ast::TyU64 => (u64::MIN,         u64::MAX)
  829          }
  830      }
  831  
  832      fn check_limits(tcx&ty::ctxt, binopast::BinOp,
  833                      l&ast::Expr, r&ast::Expr) -> bool {
  834          let (lit, expr, swap) = match (&l.node, &r.node) {
  835              (&ast::ExprLit(_), _) => (l, r, true),
  836              (_, &ast::ExprLit(_)) => (r, l, false),
  837              _ => return true
  838          };
  839          // Normalize the binop so that the literal is always on the RHS in
  840          // the comparison
  841          let norm_binop = if swap { rev_binop(binop) } else { binop };
  842          match ty::get(ty::expr_ty(tcx, expr)).sty {
  843              ty::ty_int(int_ty) => {
  844                  let (min, max) = int_ty_range(int_ty);
  845                  let lit_vali64 = match lit.node {
  846                      ast::ExprLit(li) => match li.node {
  847                          ast::LitInt(v, _) => v,
  848                          ast::LitUint(v, _) => v as i64,
  849                          ast::LitIntUnsuffixed(v) => v,
  850                          _ => return true
  851                      },
  852                      _ => fail!()
  853                  };
  854                  is_valid(norm_binop, lit_val, min, max)
  855              }
  856              ty::ty_uint(uint_ty) => {
  857                  let (min, max)(u64, u64) = uint_ty_range(uint_ty);
  858                  let lit_valu64 = match lit.node {
  859                      ast::ExprLit(li) => match li.node {
  860                          ast::LitInt(v, _) => v as u64,
  861                          ast::LitUint(v, _) => v,
  862                          ast::LitIntUnsuffixed(v) => v as u64,
  863                          _ => return true
  864                      },
  865                      _ => fail!()
  866                  };
  867                  is_valid(norm_binop, lit_val, min, max)
  868              }
  869              _ => true
  870          }
  871      }
  872  
  873      fn is_comparison(binopast::BinOp) -> bool {
  874          match binop {
  875              ast::BiEq | ast::BiLt | ast::BiLe |
  876              ast::BiNe | ast::BiGe | ast::BiGt => true,
  877              _ => false
  878          }
  879      }
  880  }
  881  
  882  fn check_item_ctypes(cx: &Context, it: &ast::Item) {
  883      fn check_ty(cx&Context, ty: &ast::Ty) {
  884          match ty.node {
  885              ast::TyPath(_, _, id) => {
  886                  match cx.tcx.def_map.borrow().get_copy(&id) {
  887                      ast::DefPrimTy(ast::TyInt(ast::TyI)) => {
  888                          cx.span_lint(CTypes, ty.span,
  889                                  "found rust type `int` in foreign module, while \
  890                                  libc::c_int or libc::c_long should be used");
  891                      }
  892                      ast::DefPrimTy(ast::TyUint(ast::TyU)) => {
  893                          cx.span_lint(CTypes, ty.span,
  894                                  "found rust type `uint` in foreign module, while \
  895                                  libc::c_uint or libc::c_ulong should be used");
  896                      }
  897                      ast::DefTy(def_id) => {
  898                          if !adt::is_ffi_safe(cx.tcx, def_id) {
  899                              cx.span_lint(CTypes, ty.span,
  900                                           "found enum type without foreign-function-safe \
  901                                            representation annotation in foreign module");
  902                              // hmm... this message could be more helpful
  903                          }
  904                      }
  905                      _ => ()
  906                  }
  907              }
  908              ast::TyPtr(ref mt) => { check_ty(cx, mt.ty) }
  909              _ => {}
  910          }
  911      }
  912  
  913      fn check_foreign_fn(cx: &Context, decl&ast::FnDecl) {
  914          for input in decl.inputs.iter() {
  915              check_ty(cx, input.ty);
  916          }
  917          check_ty(cx, decl.output)
  918      }
  919  
  920      match it.node {
  921        ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => {
  922          for ni in nmod.items.iter() {
  923              match ni.node {
  924                  ast::ForeignItemFn(decl, _) => check_foreign_fn(cx, decl),
  925                  ast::ForeignItemStatic(t, _) => check_ty(cx, t)
  926              }
  927          }
  928        }
  929        _ => {/* nothing to do */ }
  930      }
  931  }
  932  
  933  fn check_heap_type(cx: &Context, spanSpan, tyty::t) {
  934      let xs = [ManagedHeapMemory, OwnedHeapMemory, HeapMemory];
  935      for &lint in xs.iter() {
  936          if cx.get_level(lint) == allow { continue }
  937  
  938          let mut n_box = 0;
  939          let mut n_uniq = 0;
  940          ty::fold_ty(cx.tcx, ty, |t| {
  941              match ty::get(t).sty {
  942                  ty::ty_box(_) => {
  943                      n_box += 1;
  944                  }
  945                  ty::ty_uniq(_) |
  946                  ty::ty_trait(box ty::TyTrait {
  947                      store: ty::UniqTraitStore, ..
  948                  }) |
  949                  ty::ty_closure(box ty::ClosureTy {
  950                      store: ty::UniqTraitStore,
  951                      ..
  952                  }) => {
  953                      n_uniq += 1;
  954                  }
  955  
  956                  _ => ()
  957              };
  958              t
  959          });
  960  
  961          if n_uniq > 0 && lint != ManagedHeapMemory {
  962              let s = ty_to_str(cx.tcx, ty);
  963              let m = format!("type uses owned (Box type) pointers: {}", s);
  964              cx.span_lint(lint, span, m);
  965          }
  966  
  967          if n_box > 0 && lint != OwnedHeapMemory {
  968              let s = ty_to_str(cx.tcx, ty);
  969              let m = format!("type uses managed (type) pointers: {}", s);
  970              cx.span_lint(lint, span, m);
  971          }
  972      }
  973  }
  974  
  975  fn check_heap_item(cx: &Context, it: &ast::Item) {
  976      match it.node {
  977          ast::ItemFn(..) |
  978          ast::ItemTy(..) |
  979          ast::ItemEnum(..) |
  980          ast::ItemStruct(..) => check_heap_type(cx, it.span,
  981                                                 ty::node_id_to_type(cx.tcx,
  982                                                                     it.id)),
  983          _ => ()
  984      }
  985  
  986      // If it's a struct, we also have to check the fields' types
  987      match it.node {
  988          ast::ItemStruct(struct_def, _) => {
  989              for struct_field in struct_def.fields.iter() {
  990                  check_heap_type(cx, struct_field.span,
  991                                  ty::node_id_to_type(cx.tcx,
  992                                                      struct_field.node.id));
  993              }
  994          }
  995          _ => ()
  996      }
  997  }
  998  
  999  struct RawPtrDerivingVisitor<'a> {
 1000      cx: &'a Context<'a>
 1001  }
 1002  
 1003  impl<'a> Visitor<()> for RawPtrDerivingVisitor<'a> {
 1004      fn visit_ty(&mut self, ty&ast::Ty, _()) {
 1005          static MSG: &'static str = "use of `#[deriving]` with a raw pointer";
 1006          match ty.node {
 1007              ast::TyPtr(..) => self.cx.span_lint(RawPointerDeriving, ty.span, MSG),
 1008              _ => {}
 1009          }
 1010          visit::walk_ty(self, ty, ());
 1011      }
 1012      // explicit override to a no-op to reduce code bloat
 1013      fn visit_expr(&mut self, _&ast::Expr, _()) {}
 1014      fn visit_block(&mut self, _&ast::Block, _()) {}
 1015  }
 1016  
 1017  fn check_raw_ptr_deriving(cx: &Context, item: &ast::Item) {
 1018      if !attr::contains_name(item.attrs.as_slice(), "deriving") {
 1019          return
 1020      }
 1021      match item.node {
 1022          ast::ItemStruct(..) | ast::ItemEnum(..) => {
 1023              let mut visitor = RawPtrDerivingVisitor { cx: cx };
 1024              visit::walk_item(&mut visitor, item, ());
 1025          }
 1026          _ => {}
 1027      }
 1028  }
 1029  
 1030  static crate_attrs: &'static [&'static str] = &[
 1031      "crate_type", "feature", "no_start", "no_main", "no_std", "crate_id",
 1032      "desc", "comment", "license", "copyright", // not used in rustc now
 1033  ];
 1034  
 1035  
 1036  static obsolete_attrs: &'static [(&'static str, &'static str)] = &[
 1037      ("abi", "Use `extern \"abi\" fn` instead"),
 1038      ("auto_encode", "Use `#[deriving(Encodable)]` instead"),
 1039      ("auto_decode", "Use `#[deriving(Decodable)]` instead"),
 1040      ("fast_ffi", "Remove it"),
 1041      ("fixed_stack_segment", "Remove it"),
 1042      ("rust_stack", "Remove it"),
 1043  ];
 1044  
 1045  static other_attrs: &'static [&'static str] = &[
 1046      // item-level
 1047      "address_insignificant", // can be crate-level too
 1048      "thread_local", // for statics
 1049      "allow", "deny", "forbid", "warn", // lint options
 1050      "deprecated", "experimental", "unstable", "stable", "locked", "frozen", //item stability
 1051      "cfg", "doc", "export_name", "link_section",
 1052      "no_mangle", "static_assert", "unsafe_no_drop_flag", "packed",
 1053      "simd", "repr", "deriving", "unsafe_destructor", "link", "phase",
 1054      "macro_export", "must_use", "automatically_derived",
 1055  
 1056      //mod-level
 1057      "path", "link_name", "link_args", "macro_escape", "no_implicit_prelude",
 1058  
 1059      // fn-level
 1060      "test", "bench", "should_fail", "ignore", "inline", "lang", "main", "start",
 1061      "no_split_stack", "cold", "macro_registrar", "linkage",
 1062  
 1063      // internal attribute: bypass privacy inside items
 1064      "!resolve_unexported",
 1065  ];
 1066  
 1067  fn check_crate_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) {
 1068  
 1069      for attr in attrs.iter() {
 1070          let name = attr.node.value.name();
 1071          let mut iter = crate_attrs.iter().chain(other_attrs.iter());
 1072          if !iter.any(|other_attr| { name.equiv(other_attr) }) {
 1073              cx.span_lint(AttributeUsage, attr.span, "unknown crate attribute");
 1074          }
 1075          if name.equiv(&("link")) {
 1076              cx.tcx.sess.span_err(attr.span,
 1077                                   "obsolete crate `link` attribute");
 1078              cx.tcx.sess.note("the link attribute has been superceded by the crate_id \
 1079                               attribute, which has the format `#[crate_id = \"name#version\"]`");
 1080          }
 1081      }
 1082  }
 1083  
 1084  fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) {
 1085      // check if element has crate-level, obsolete, or any unknown attributes.
 1086  
 1087      for attr in attrs.iter() {
 1088          let name = attr.node.value.name();
 1089          for crate_attr in crate_attrs.iter() {
 1090              if name.equiv(crate_attr) {
 1091                  let msg = match attr.node.style {
 1092                      ast::AttrOuter => "crate-level attribute should be an inner attribute: \
 1093                                         add an exclamation mark: #![foo]",
 1094                      ast::AttrInner => "crate-level attribute should be in the root module",
 1095                  };
 1096                  cx.span_lint(AttributeUsage, attr.span, msg);
 1097                  return;
 1098              }
 1099          }
 1100  
 1101          for &(obs_attr, obs_alter) in obsolete_attrs.iter() {
 1102              if name.equiv(&obs_attr) {
 1103                  cx.span_lint(AttributeUsage, attr.span,
 1104                               format!("obsolete attribute: {:s}", obs_alter));
 1105                  return;
 1106              }
 1107          }
 1108  
 1109          if !other_attrs.iter().any(|other_attr| { name.equiv(other_attr) }) {
 1110              cx.span_lint(AttributeUsage, attr.span, "unknown attribute");
 1111          }
 1112      }
 1113  }
 1114  
 1115  fn check_heap_expr(cx: &Context, e: &ast::Expr) {
 1116      let ty = ty::expr_ty(cx.tcx, e);
 1117      check_heap_type(cx, e.span, ty);
 1118  }
 1119  
 1120  fn check_path_statement(cx: &Context, s: &ast::Stmt) {
 1121      match s.node {
 1122          ast::StmtSemi(expr, _) => {
 1123              match expr.node {
 1124                  ast::ExprPath(_) => {
 1125                      cx.span_lint(PathStatement,
 1126                                   s.span,
 1127                                   "path statement with no effect");
 1128                  }
 1129                  _ => {}
 1130              }
 1131          }
 1132          _ => ()
 1133      }
 1134  }
 1135  
 1136  fn check_unused_result(cx: &Context, s: &ast::Stmt) {
 1137      let expr = match s.node {
 1138          ast::StmtSemi(expr, _) => expr,
 1139          _ => return
 1140      };
 1141      let t = ty::expr_ty(cx.tcx, expr);
 1142      match ty::get(t).sty {
 1143          ty::ty_nil | ty::ty_bot | ty::ty_bool => return,
 1144          _ => {}
 1145      }
 1146      match expr.node {
 1147          ast::ExprRet(..) => return,
 1148          _ => {}
 1149      }
 1150  
 1151      let t = ty::expr_ty(cx.tcx, expr);
 1152      let mut warned = false;
 1153      match ty::get(t).sty {
 1154          ty::ty_struct(did, _) |
 1155          ty::ty_enum(did, _) => {
 1156              if ast_util::is_local(did) {
 1157                  match cx.tcx.map.get(did.node) {
 1158                      ast_map::NodeItem(it) => {
 1159                          if attr::contains_name(it.attrs.as_slice(),
 1160                                                 "must_use") {
 1161                              cx.span_lint(UnusedMustUse, s.span,
 1162                                           "unused result which must be used");
 1163                              warned = true;
 1164                          }
 1165                      }
 1166                      _ => {}
 1167                  }
 1168              } else {
 1169                  csearch::get_item_attrs(&cx.tcx.sess.cstore, did, |attrs| {
 1170                      if attr::contains_name(attrs.as_slice(), "must_use") {
 1171                          cx.span_lint(UnusedMustUse, s.span,
 1172                                       "unused result which must be used");
 1173                          warned = true;
 1174                      }
 1175                  });
 1176              }
 1177          }
 1178          _ => {}
 1179      }
 1180      if !warned {
 1181          cx.span_lint(UnusedResult, s.span, "unused result");
 1182      }
 1183  }
 1184  
 1185  fn check_deprecated_owned_vector(cx: &Context, e: &ast::Expr) {
 1186      let t = ty::expr_ty(cx.tcx, e);
 1187      match ty::get(t).sty {
 1188          ty::ty_uniq(t) => match ty::get(t).sty {
 1189              ty::ty_vec(_, None) => {
 1190                  cx.span_lint(DeprecatedOwnedVector, e.span,
 1191                               "use of deprecated `~[]` vector; replaced by `std::vec::Vec`")
 1192              }
 1193              _ => {}
 1194          },
 1195          _ => {}
 1196      }
 1197  }
 1198  
 1199  fn check_item_non_camel_case_types(cx: &Context, it: &ast::Item) {
 1200      fn is_camel_case(identast::Ident) -> bool {
 1201          let ident = token::get_ident(ident);
 1202          assert!(!ident.get().is_empty());
 1203          let ident = ident.get().trim_chars('_');
 1204  
 1205          // start with a non-lowercase letter rather than non-uppercase
 1206          // ones (some scripts don't have a concept of upper/lowercase)
 1207          !ident.char_at(0).is_lowercase() && !ident.contains_char('_')
 1208      }
 1209  
 1210      fn check_case(cx: &Context, sort: &str, identast::Ident, spanSpan) {
 1211          if !is_camel_case(ident) {
 1212              cx.span_lint(
 1213                  NonCamelCaseTypes, span,
 1214                  format!("{} `{}` should have a camel case identifier",
 1215                      sort, token::get_ident(ident)));
 1216          }
 1217      }
 1218  
 1219      match it.node {
 1220          ast::ItemTy(..) | ast::ItemStruct(..) => {
 1221              check_case(cx, "type", it.ident, it.span)
 1222          }
 1223          ast::ItemTrait(..) => {
 1224              check_case(cx, "trait", it.ident, it.span)
 1225          }
 1226          ast::ItemEnum(ref enum_definition, _) => {
 1227              check_case(cx, "type", it.ident, it.span);
 1228              for variant in enum_definition.variants.iter() {
 1229                  check_case(cx, "variant", variant.node.name, variant.span);
 1230              }
 1231          }
 1232          _ => ()
 1233      }
 1234  }
 1235  
 1236  fn check_item_non_uppercase_statics(cx: &Context, it: &ast::Item) {
 1237      match it.node {
 1238          // only check static constants
 1239          ast::ItemStatic(_, ast::MutImmutable, _) => {
 1240              let s = token::get_ident(it.ident);
 1241              // check for lowercase letters rather than non-uppercase
 1242              // ones (some scripts don't have a concept of
 1243              // upper/lowercase)
 1244              if s.get().chars().any(|c| c.is_lowercase()) {
 1245                  cx.span_lint(NonUppercaseStatics, it.span,
 1246                               "static constant should have an uppercase identifier");
 1247              }
 1248          }
 1249          _ => {}
 1250      }
 1251  }
 1252  
 1253  fn check_pat_non_uppercase_statics(cx: &Context, p: &ast::Pat) {
 1254      // Lint for constants that look like binding identifiers (#7526)
 1255      match (&p.node, cx.tcx.def_map.borrow().find(&p.id)) {
 1256          (&ast::PatIdent(_, ref path, _), Some(&ast::DefStatic(_, false))) => {
 1257              // last identifier alone is right choice for this lint.
 1258              let ident = path.segments.last().unwrap().identifier;
 1259              let s = token::get_ident(ident);
 1260              if s.get().chars().any(|c| c.is_lowercase()) {
 1261                  cx.span_lint(NonUppercasePatternStatics, path.span,
 1262                               "static constant in pattern should be all caps");
 1263              }
 1264          }
 1265          _ => {}
 1266      }
 1267  }
 1268  
 1269  fn check_pat_uppercase_variable(cx: &Context, p: &ast::Pat) {
 1270      match &p.node {
 1271          &ast::PatIdent(_, ref path, _) => {
 1272              match cx.tcx.def_map.borrow().find(&p.id) {
 1273                  Some(&ast::DefLocal(_, _)) | Some(&ast::DefBinding(_, _)) |
 1274                          Some(&ast::DefArg(_, _)) => {
 1275                      // last identifier alone is right choice for this lint.
 1276                      let ident = path.segments.last().unwrap().identifier;
 1277                      let s = token::get_ident(ident);
 1278                      if s.get().len() > 0 && s.get().char_at(0).is_uppercase() {
 1279                          cx.span_lint(
 1280                              UppercaseVariables,
 1281                              path.span,
 1282                              "variable names should start with a lowercase character");
 1283                      }
 1284                  }
 1285                  _ => {}
 1286              }
 1287          }
 1288          _ => {}
 1289      }
 1290  }
 1291  
 1292  fn check_struct_uppercase_variable(cx: &Context, s: &ast::StructDef) {
 1293      for sf in s.fields.iter() {
 1294          match sf.node {
 1295              ast::StructField_ { kind: ast::NamedField(ident, _), .. } => {
 1296                  let s = token::get_ident(ident);
 1297                  if s.get().char_at(0).is_uppercase() {
 1298                      cx.span_lint(
 1299                          UppercaseVariables,
 1300                          sf.span,
 1301                          "structure field names should start with a lowercase character");
 1302                  }
 1303              }
 1304              _ => {}
 1305          }
 1306      }
 1307  }
 1308  
 1309  fn check_unnecessary_parens_core(cx: &Context, value: &ast::Expr, msg: &str) {
 1310      match value.node {
 1311          ast::ExprParen(_) => {
 1312              cx.span_lint(UnnecessaryParens, value.span,
 1313                           format!("unnecessary parentheses around {}", msg))
 1314          }
 1315          _ => {}
 1316      }
 1317  }
 1318  
 1319  fn check_unnecessary_parens_expr(cx: &Context, e: &ast::Expr) {
 1320      let (value, msg) = match e.node {
 1321          ast::ExprIf(cond, _, _) => (cond, "`if` condition"),
 1322          ast::ExprWhile(cond, _) => (cond, "`while` condition"),
 1323          ast::ExprMatch(head, _) => (head, "`match` head expression"),
 1324          ast::ExprRet(Some(value)) => (value, "`return` value"),
 1325          ast::ExprAssign(_, value) => (value, "assigned value"),
 1326          ast::ExprAssignOp(_, _, value) => (value, "assigned value"),
 1327          _ => return
 1328      };
 1329      check_unnecessary_parens_core(cx, value, msg);
 1330  }
 1331  
 1332  fn check_unnecessary_parens_stmt(cx: &Context, s: &ast::Stmt) {
 1333      let (value, msg) = match s.node {
 1334          ast::StmtDecl(decl, _) => match decl.node {
 1335              ast::DeclLocal(local) => match local.init {
 1336                  Some(value) => (value, "assigned value"),
 1337                  None => return
 1338              },
 1339              _ => return
 1340          },
 1341          _ => return
 1342      };
 1343      check_unnecessary_parens_core(cx, value, msg);
 1344  }
 1345  
 1346  fn check_unused_unsafe(cx: &Context, e: &ast::Expr) {
 1347      match e.node {
 1348          // Don't warn about generated blocks, that'll just pollute the output.
 1349          ast::ExprBlock(ref blk) => {
 1350              if blk.rules == ast::UnsafeBlock(ast::UserProvided) &&
 1351                  !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
 1352                  cx.span_lint(UnusedUnsafe, blk.span,
 1353                               "unnecessary `unsafe` block");
 1354              }
 1355          }
 1356          _ => ()
 1357      }
 1358  }
 1359  
 1360  fn check_unsafe_block(cx: &Context, e: &ast::Expr) {
 1361      match e.node {
 1362          // Don't warn about generated blocks, that'll just pollute the output.
 1363          ast::ExprBlock(ref blk) if blk.rules == ast::UnsafeBlock(ast::UserProvided) => {
 1364              cx.span_lint(UnsafeBlock, blk.span, "usage of an `unsafe` block");
 1365          }
 1366          _ => ()
 1367      }
 1368  }
 1369  
 1370  fn check_unused_mut_pat(cx: &Context, p: &ast::Pat) {
 1371      match p.node {
 1372          ast::PatIdent(ast::BindByValue(ast::MutMutable),
 1373                        ref path, _) if pat_util::pat_is_binding(&cx.tcx.def_map, p) => {
 1374              // `let mut _a = 1;` doesn't need a warning.
 1375              let initial_underscore = if path.segments.len() == 1 {
 1376                  token::get_ident(path.segments
 1377                                       .get(0)
 1378                                       .identifier).get().starts_with("_")
 1379              } else {
 1380                  cx.tcx.sess.span_bug(p.span,
 1381                                       "mutable binding that doesn't consist \
 1382                                        of exactly one segment")
 1383              };
 1384  
 1385              if !initial_underscore &&
 1386                 !cx.tcx.used_mut_nodes.borrow().contains(&p.id) {
 1387                  cx.span_lint(UnusedMut, p.span,
 1388                               "variable does not need to be mutable");
 1389              }
 1390          }
 1391          _ => ()
 1392      }
 1393  }
 1394  
 1395  enum Allocation {
 1396      VectorAllocation,
 1397      BoxAllocation
 1398  }
 1399  
 1400  fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
 1401      // Warn if string and vector literals with sigils, or boxing expressions,
 1402      // are immediately borrowed.
 1403      let allocation = match e.node {
 1404          ast::ExprVstore(e2, ast::ExprVstoreUniq) => {
 1405              match e2.node {
 1406                  ast::ExprLit(lit) if ast_util::lit_is_str(lit) => {
 1407                      VectorAllocation
 1408                  }
 1409                  ast::ExprVec(..) => VectorAllocation,
 1410                  _ => return
 1411              }
 1412          }
 1413          ast::ExprUnary(ast::UnUniq, _) |
 1414          ast::ExprUnary(ast::UnBox, _) => BoxAllocation,
 1415  
 1416          _ => return
 1417      };
 1418  
 1419      let report = |msg| {
 1420          cx.span_lint(UnnecessaryAllocation, e.span, msg);
 1421      };
 1422  
 1423      match cx.tcx.adjustments.borrow().find(&e.id) {
 1424          Some(adjustment) => {
 1425              match *adjustment {
 1426                  ty::AutoDerefRef(ty::AutoDerefRef { autoref, .. }) => {
 1427                      match (allocation, autoref) {
 1428                          (VectorAllocation, Some(ty::AutoBorrowVec(..))) => {
 1429                              report("unnecessary allocation, the sigil can be \
 1430                                      removed");
 1431                          }
 1432                          (BoxAllocation,
 1433                           Some(ty::AutoPtr(_, ast::MutImmutable))) => {
 1434                              report("unnecessary allocation, use & instead");
 1435                          }
 1436                          (BoxAllocation,
 1437                           Some(ty::AutoPtr(_, ast::MutMutable))) => {
 1438                              report("unnecessary allocation, use &mut \
 1439                                      instead");
 1440                          }
 1441                          _ => ()
 1442                      }
 1443                  }
 1444                  _ => {}
 1445              }
 1446          }
 1447  
 1448          _ => ()
 1449      }
 1450  }
 1451  
 1452  fn check_missing_doc_attrs(cx: &Context,
 1453                             idOption<ast::NodeId>,
 1454                             attrs: &[ast::Attribute],
 1455                             spSpan,
 1456                             desc: &'static str) {
 1457      // If we're building a test harness, then warning about
 1458      // documentation is probably not really relevant right now.
 1459      if cx.tcx.sess.opts.test { return }
 1460  
 1461      // `#[doc(hidden)]` disables missing_doc check.
 1462      if cx.is_doc_hidden { return }
 1463  
 1464      // Only check publicly-visible items, using the result from the privacy pass. It's an option so
 1465      // the crate root can also use this function (it doesn't have a NodeId).
 1466      match id {
 1467          Some(ref id) if !cx.exported_items.contains(id) => return,
 1468          _ => ()
 1469      }
 1470  
 1471      let has_doc = attrs.iter().any(|a| {
 1472          match a.node.value.node {
 1473              ast::MetaNameValue(ref name, _) if name.equiv(&("doc")) => true,
 1474              _ => false
 1475          }
 1476      });
 1477      if !has_doc {
 1478          cx.span_lint(MissingDoc, sp,
 1479                       format!("missing documentation for {}", desc));
 1480      }
 1481  }
 1482  
 1483  fn check_missing_doc_item(cx: &Context, it: &ast::Item) {
 1484      let desc = match it.node {
 1485          ast::ItemFn(..) => "a function",
 1486          ast::ItemMod(..) => "a module",
 1487          ast::ItemEnum(..) => "an enum",
 1488          ast::ItemStruct(..) => "a struct",
 1489          ast::ItemTrait(..) => "a trait",
 1490          _ => return
 1491      };
 1492      check_missing_doc_attrs(cx,
 1493                              Some(it.id),
 1494                              it.attrs.as_slice(),
 1495                              it.span,
 1496                              desc);
 1497  }
 1498  
 1499  fn check_missing_doc_method(cx: &Context, m: &ast::Method) {
 1500      let did = ast::DefId {
 1501          krate: ast::LOCAL_CRATE,
 1502          node: m.id
 1503      };
 1504  
 1505      match cx.tcx.methods.borrow().find_copy(&did) {
 1506          None => cx.tcx.sess.span_bug(m.span, "missing method descriptor?!"),
 1507          Some(md) => {
 1508              match md.container {
 1509                  // Always check default methods defined on traits.
 1510                  ty::TraitContainer(..) => {}
 1511                  // For methods defined on impls, it depends on whether
 1512                  // it is an implementation for a trait or is a plain
 1513                  // impl.
 1514                  ty::ImplContainer(cid) => {
 1515                      match ty::impl_trait_ref(cx.tcx, cid) {
 1516                          Some(..) => return, // impl for trait: don't doc
 1517                          None => {} // plain impl: doc according to privacy
 1518                      }
 1519                  }
 1520              }
 1521          }
 1522      }
 1523      check_missing_doc_attrs(cx,
 1524                              Some(m.id),
 1525                              m.attrs.as_slice(),
 1526                              m.span,
 1527                              "a method");
 1528  }
 1529  
 1530  fn check_missing_doc_ty_method(cx: &Context, tm: &ast::TypeMethod) {
 1531      check_missing_doc_attrs(cx,
 1532                              Some(tm.id),
 1533                              tm.attrs.as_slice(),
 1534                              tm.span,
 1535                              "a type method");
 1536  }
 1537  
 1538  fn check_missing_doc_struct_field(cx: &Context, sf: &ast::StructField) {
 1539      match sf.node.kind {
 1540          ast::NamedField(_, vis) if vis == ast::Public =>
 1541              check_missing_doc_attrs(cx,
 1542                                      Some(cx.cur_struct_def_id),
 1543                                      sf.node.attrs.as_slice(),
 1544                                      sf.span,
 1545                                      "a struct field"),
 1546          _ => {}
 1547      }
 1548  }
 1549  
 1550  fn check_missing_doc_variant(cx: &Context, v: &ast::Variant) {
 1551      check_missing_doc_attrs(cx,
 1552                              Some(v.node.id),
 1553                              v.node.attrs.as_slice(),
 1554                              v.span,
 1555                              "a variant");
 1556  }
 1557  
 1558  /// Checks for use of items with #[deprecated], #[experimental] and
 1559  /// #[unstable] (or none of them) attributes.
 1560  fn check_stability(cx: &Context, e: &ast::Expr) {
 1561      let id = match e.node {
 1562          ast::ExprPath(..) | ast::ExprStruct(..) => {
 1563              match cx.tcx.def_map.borrow().find(&e.id) {
 1564                  Some(&def) => ast_util::def_id_of_def(def),
 1565                  None => return
 1566              }
 1567          }
 1568          ast::ExprMethodCall(..) => {
 1569              let method_call = typeck::MethodCall::expr(e.id);
 1570              match cx.tcx.method_map.borrow().find(&method_call) {
 1571                  Some(method) => {
 1572                      match method.origin {
 1573                          typeck::MethodStatic(def_id) => {
 1574                              // If this implements a trait method, get def_id
 1575                              // of the method inside trait definition.
 1576                              // Otherwise, use the current def_id (which refers
 1577                              // to the method inside impl).
 1578                              ty::trait_method_of_method(
 1579                                  cx.tcx, def_id).unwrap_or(def_id)
 1580                          }
 1581                          typeck::MethodParam(typeck::MethodParam {
 1582                              trait_id: trait_id,
 1583                              method_num: index,
 1584                              ..
 1585                          })
 1586                          | typeck::MethodObject(typeck::MethodObject {
 1587                              trait_id: trait_id,
 1588                              method_num: index,
 1589                              ..
 1590                          }) => ty::trait_method(cx.tcx, trait_id, index).def_id
 1591                      }
 1592                  }
 1593                  None => return
 1594              }
 1595          }
 1596          _ => return
 1597      };
 1598  
 1599      let stability = if ast_util::is_local(id) {
 1600          // this crate
 1601          let s = cx.tcx.map.with_attrs(id.node, |attrs| {
 1602              attrs.map(|a| {
 1603                  attr::find_stability(a.iter().map(|a| a.meta()))
 1604              })
 1605          });
 1606          match s {
 1607              Some(s) => s,
 1608  
 1609              // no possibility of having attributes
 1610              // (e.g. it's a local variable), so just
 1611              // ignore it.
 1612              None => return
 1613          }
 1614      } else {
 1615          // cross-crate
 1616  
 1617          let mut s = None;
 1618          // run through all the attributes and take the first
 1619          // stability one.
 1620          csearch::get_item_attrs(&cx.tcx.sess.cstore, id, |meta_items| {
 1621              if s.is_none() {
 1622                  s = attr::find_stability(meta_items.move_iter())
 1623              }
 1624          });
 1625          s
 1626      };
 1627  
 1628      let (lint, label) = match stability {
 1629          // no stability attributes == Unstable
 1630          None => (Unstable, "unmarked"),
 1631          Some(attr::Stability { level: attr::Unstable, .. }) =>
 1632                  (Unstable, "unstable"),
 1633          Some(attr::Stability { level: attr::Experimental, .. }) =>
 1634                  (Experimental, "experimental"),
 1635          Some(attr::Stability { level: attr::Deprecated, .. }) =>
 1636                  (Deprecated, "deprecated"),
 1637          _ => return
 1638      };
 1639  
 1640      let msg = match stability {
 1641          Some(attr::Stability { text: Some(ref s), .. }) => {
 1642              format!("use of {} item: {}", label, *s)
 1643          }
 1644          _ => format!("use of {} item", label)
 1645      };
 1646  
 1647      cx.span_lint(lint, e.span, msg);
 1648  }
 1649  
 1650  impl<'a> Visitor<()> for Context<'a> {
 1651      fn visit_item(&mut self, it&ast::Item, _()) {
 1652          self.with_lint_attrs(it.attrs.as_slice(), |cx| {
 1653              check_item_ctypes(cx, it);
 1654              check_item_non_camel_case_types(cx, it);
 1655              check_item_non_uppercase_statics(cx, it);
 1656              check_heap_item(cx, it);
 1657              check_missing_doc_item(cx, it);
 1658              check_attrs_usage(cx, it.attrs.as_slice());
 1659              check_raw_ptr_deriving(cx, it);
 1660  
 1661              cx.visit_ids(|v| v.visit_item(it, ()));
 1662  
 1663              visit::walk_item(cx, it, ());
 1664          })
 1665      }
 1666  
 1667      fn visit_foreign_item(&mut self, it&ast::ForeignItem, _()) {
 1668          self.with_lint_attrs(it.attrs.as_slice(), |cx| {
 1669              check_attrs_usage(cx, it.attrs.as_slice());
 1670              visit::walk_foreign_item(cx, it, ());
 1671          })
 1672      }
 1673  
 1674      fn visit_view_item(&mut self, i&ast::ViewItem, _()) {
 1675          self.with_lint_attrs(i.attrs.as_slice(), |cx| {
 1676              check_attrs_usage(cx, i.attrs.as_slice());
 1677  
 1678              cx.visit_ids(|v| v.visit_view_item(i, ()));
 1679  
 1680              visit::walk_view_item(cx, i, ());
 1681          })
 1682      }
 1683  
 1684      fn visit_pat(&mut self, p&ast::Pat, _()) {
 1685          check_pat_non_uppercase_statics(self, p);
 1686          check_pat_uppercase_variable(self, p);
 1687          check_unused_mut_pat(self, p);
 1688  
 1689          visit::walk_pat(self, p, ());
 1690      }
 1691  
 1692      fn visit_expr(&mut self, e&ast::Expr, _()) {
 1693          match e.node {
 1694              ast::ExprUnary(ast::UnNeg, expr) => {
 1695                  // propagate negation, if the negation itself isn't negated
 1696                  if self.negated_expr_id != e.id {
 1697                      self.negated_expr_id = expr.id;
 1698                  }
 1699              },
 1700              ast::ExprParen(expr) => if self.negated_expr_id == e.id {
 1701                  self.negated_expr_id = expr.id
 1702              },
 1703              _ => ()
 1704          };
 1705  
 1706          check_while_true_expr(self, e);
 1707          check_stability(self, e);
 1708          check_unnecessary_parens_expr(self, e);
 1709          check_unused_unsafe(self, e);
 1710          check_unsafe_block(self, e);
 1711          check_unnecessary_allocation(self, e);
 1712          check_heap_expr(self, e);
 1713  
 1714          check_type_limits(self, e);
 1715          check_unused_casts(self, e);
 1716          check_deprecated_owned_vector(self, e);
 1717  
 1718          visit::walk_expr(self, e, ());
 1719      }
 1720  
 1721      fn visit_stmt(&mut self, s&ast::Stmt, _()) {
 1722          check_path_statement(self, s);
 1723          check_unused_result(self, s);
 1724          check_unnecessary_parens_stmt(self, s);
 1725  
 1726          visit::walk_stmt(self, s, ());
 1727      }
 1728  
 1729      fn visit_fn(&mut self, fk&visit::FnKind, decl&ast::FnDecl,
 1730                  body&ast::Block, spanSpan, idast::NodeId, _()) {
 1731          let recurse = |this&mut Context{
 1732              visit::walk_fn(this, fk, decl, body, span, id, ());
 1733          };
 1734  
 1735          match *fk {
 1736              visit::FkMethod(_, _, m) => {
 1737                  self.with_lint_attrs(m.attrs.as_slice(), |cx| {
 1738                      check_missing_doc_method(cx, m);
 1739                      check_attrs_usage(cx, m.attrs.as_slice());
 1740  
 1741                      cx.visit_ids(|v| {
 1742                          v.visit_fn(fk, decl, body, span, id, ());
 1743                      });
 1744                      recurse(cx);
 1745                  })
 1746              }
 1747              _ => recurse(self),
 1748          }
 1749      }
 1750  
 1751  
 1752      fn visit_ty_method(&mut self, t&ast::TypeMethod, _()) {
 1753          self.with_lint_attrs(t.attrs.as_slice(), |cx| {
 1754              check_missing_doc_ty_method(cx, t);
 1755              check_attrs_usage(cx, t.attrs.as_slice());
 1756  
 1757              visit::walk_ty_method(cx, t, ());
 1758          })
 1759      }
 1760  
 1761      fn visit_struct_def(&mut self,
 1762                          s&ast::StructDef,
 1763                          iast::Ident,
 1764                          g&ast::Generics,
 1765                          idast::NodeId,
 1766                          _()) {
 1767          check_struct_uppercase_variable(self, s);
 1768  
 1769          let old_id = self.cur_struct_def_id;
 1770          self.cur_struct_def_id = id;
 1771          visit::walk_struct_def(self, s, i, g, id, ());
 1772          self.cur_struct_def_id = old_id;
 1773      }
 1774  
 1775      fn visit_struct_field(&mut self, s&ast::StructField, _()) {
 1776          self.with_lint_attrs(s.node.attrs.as_slice(), |cx| {
 1777              check_missing_doc_struct_field(cx, s);
 1778              check_attrs_usage(cx, s.node.attrs.as_slice());
 1779  
 1780              visit::walk_struct_field(cx, s, ());
 1781          })
 1782      }
 1783  
 1784      fn visit_variant(&mut self, v&ast::Variant, g&ast::Generics, _()) {
 1785          self.with_lint_attrs(v.node.attrs.as_slice(), |cx| {
 1786              check_missing_doc_variant(cx, v);
 1787              check_attrs_usage(cx, v.node.attrs.as_slice());
 1788  
 1789              visit::walk_variant(cx, v, g, ());
 1790          })
 1791      }
 1792  
 1793      // FIXME(#10894) should continue recursing
 1794      fn visit_ty(&mut self, _t&ast::Ty, _()) {}
 1795  }
 1796  
 1797  impl<'a> IdVisitingOperation for Context<'a> {
 1798      fn visit_id(&self, idast::NodeId) {
 1799          match self.tcx.sess.lints.borrow_mut().pop(&id) {
 1800              None => {}
 1801              Some(l) => {
 1802                  for (lint, span, msg) in l.move_iter() {
 1803                      self.span_lint(lint, span, msg)
 1804                  }
 1805              }
 1806          }
 1807      }
 1808  }
 1809  
 1810  pub fn check_crate(tcx: &ty::ctxt,
 1811                     exported_items: &privacy::ExportedItems,
 1812                     krate: &ast::Crate) {
 1813      let mut cx = Context {
 1814          dict: get_lint_dict(),
 1815          cur: SmallIntMap::new(),
 1816          tcx: tcx,
 1817          exported_items: exported_items,
 1818          cur_struct_def_id: -1,
 1819          is_doc_hidden: false,
 1820          lint_stack: Vec::new(),
 1821          negated_expr_id: -1
 1822      };
 1823  
 1824      // Install default lint levels, followed by the command line levels, and
 1825      // then actually visit the whole crate.
 1826      for (_, spec) in cx.dict.iter() {
 1827          if spec.default != allow {
 1828              cx.cur.insert(spec.lint as uint, (spec.default, Default));
 1829          }
 1830      }
 1831      for &(lint, level) in tcx.sess.opts.lint_opts.iter() {
 1832          cx.set_level(lint, level, CommandLine);
 1833      }
 1834      cx.with_lint_attrs(krate.attrs.as_slice(), |cx| {
 1835          cx.visit_id(ast::CRATE_NODE_ID);
 1836          cx.visit_ids(|v| {
 1837              v.visited_outermost = true;
 1838              visit::walk_crate(v, krate, ());
 1839          });
 1840  
 1841          check_crate_attrs_usage(cx, krate.attrs.as_slice());
 1842          // since the root module isn't visited as an item (because it isn't an item), warn for it
 1843          // here.
 1844          check_missing_doc_attrs(cx,
 1845                                  None,
 1846                                  krate.attrs.as_slice(),
 1847                                  krate.span,
 1848                                  "crate");
 1849  
 1850          visit::walk_crate(cx, krate, ());
 1851      });
 1852  
 1853      // If we missed any lints added to the session, then there's a bug somewhere
 1854      // in the iteration code.
 1855      for (id, v) in tcx.sess.lints.borrow().iter() {
 1856          for &(lint, span, ref msg) in v.iter() {
 1857              tcx.sess.span_bug(span, format!("unprocessed lint {:?} at {}{}",
 1858                                              lint, tcx.map.node_to_str(*id), *msg))
 1859          }
 1860      }
 1861  
 1862      tcx.sess.abort_if_errors();
 1863  }


librustc/middle/lint.rs:134:47-134:47 -enum- definition:
pub enum level {
    allow, warn, deny, forbid
}
references:- 22
462: impl<'a> Context<'a> {
463:     fn get_level(&self, lint: Lint) -> level {
464:         match self.cur.find(&(lint as uint)) {
--
477:     fn set_level(&mut self, lint: Lint, level: level, src: LintSource) {
478:         if level == allow {
--
643: pub fn contains_lint(attrs: &[ast::Attribute],
644:                      level: level,
645:                      lintname: &'static str)
librustc/driver/session.rs:
132:     pub debuginfo: DebugInfoLevel,
133:     pub lint_opts: Vec<(lint::Lint, lint::level)> ,
134:     pub output_types: Vec<back::link::OutputType> ,
librustc/middle/lint.rs:
135: pub enum level {


librustc/middle/lint.rs:74:47-74:47 -enum- definition:
pub enum Lint {
    CTypes,
    UnusedImports,
references:- 23
75: pub enum Lint {
--
141:     pub default: level,
142:     pub lint: Lint,
143:     pub desc: &'static str,
--
462: impl<'a> Context<'a> {
463:     fn get_level(&self, lint: Lint) -> level {
464:         match self.cur.find(&(lint as uint)) {
--
494:     fn span_lint(&self, lint: Lint, span: Span, msg: &str) {
495:         let (level, src) = match self.cur.find(&(lint as uint)) {
librustc/driver/session.rs:
253:     pub fn add_lint(&self,
254:                     lint: lint::Lint,
255:                     id: ast::NodeId,
librustc/middle/lint.rs:
477:     fn set_level(&mut self, lint: Lint, level: level, src: LintSource) {
478:         if level == allow {


librustc/middle/lint.rs:1083:1-1083:1 -fn- definition:
fn check_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) {
    // check if element has crate-level, obsolete, or any unknown attributes.
    for attr in attrs.iter() {
references:- 7
1777:             check_missing_doc_struct_field(cx, s);
1778:             check_attrs_usage(cx, s.node.attrs.as_slice());
--
1786:             check_missing_doc_variant(cx, v);
1787:             check_attrs_usage(cx, v.node.attrs.as_slice());


librustc/middle/lint.rs:883:4-883:4 -fn- definition:
    fn check_ty(cx: &Context, ty: &ast::Ty) {
        match ty.node {
            ast::TyPath(_, _, id) => {
references:- 4
914:         for input in decl.inputs.iter() {
915:             check_ty(cx, input.ty);
916:         }
--
924:                 ast::ForeignItemFn(decl, _) => check_foreign_fn(cx, decl),
925:                 ast::ForeignItemStatic(t, _) => check_ty(cx, t)
926:             }


librustc/middle/lint.rs:145:1-145:1 -NK_AS_STR_TODO- definition:
pub type LintDict = HashMap<&'static str, LintSpec>;
enum LintSource {
    Node(Span),
references:- 2
433:  */
434: pub fn get_lint_dict() -> LintDict {
435:     lint_table.iter().map(|&(k, v)| (k, v)).collect()
--
439:     // All known lint modes (string versions)
440:     dict: LintDict,
441:     // Current levels of each lint warning


librustc/middle/lint.rs:437:1-437:1 -struct- definition:
struct Context<'a> {
    // All known lint modes (string versions)
    dict: LintDict,
references:- 44


librustc/middle/lint.rs:822:4-822:4 -fn- definition:
    fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
        match uint_ty {
            ast::TyU =>   (u64::MIN,         u64::MAX),
references:- 2
856:             ty::ty_uint(uint_ty) => {
857:                 let (min, max): (u64, u64) = uint_ty_range(uint_ty);
858:                 let lit_val: u64 = match lit.node {


librustc/middle/lint.rs:433:4-433:4 -fn- definition:
 */
pub fn get_lint_dict() -> LintDict {
    lint_table.iter().map(|&(k, v)| (k, v)).collect()
references:- 3
1813:     let mut cx = Context {
1814:         dict: get_lint_dict(),
1815:         cur: SmallIntMap::new(),
librustc/driver/driver.rs:
832:     let mut lint_opts = Vec::new();
833:     let lint_dict = lint::get_lint_dict();
834:     for level in lint_levels.iter() {
librustc/lib.rs:
170:     let lint_dict = lint::get_lint_dict();
171:     let mut lint_dict = lint_dict.move_iter()


librustc/middle/lint.rs:788:4-788:4 -fn- definition:
    fn is_valid<T:cmp::Ord>(binop: ast::BinOp, v: T,
                            min: T, max: T) -> bool {
        match binop {
references:- 2
853:                 };
854:                 is_valid(norm_binop, lit_val, min, max)
855:             }
--
866:                 };
867:                 is_valid(norm_binop, lit_val, min, max)
868:             }


librustc/middle/lint.rs:124:1-124:1 -fn- definition:
pub fn level_to_str(lv: level) -> &'static str {
    match lv {
      allow => "allow",
references:- 7
646:                      -> bool {
647:     let level_name = level_to_str(level);
648:     for attr in attrs.iter().filter(|m| m.name().equiv(&level_name)) {
librustc/driver/driver.rs:
834:     for level in lint_levels.iter() {
835:         let level_name = lint::level_to_str(*level);
librustc/lib.rs:
191:                  padded(max_key, name),
192:                  lint::level_to_str(spec.default),
193:                  spec.desc);
librustc/middle/lint.rs:
558:                         format!("{}({}) overruled by outer forbid({})",
559:                         level_to_str(level),
560:                         lintname, lintname));


librustc/middle/lint.rs:1210:4-1210:4 -fn- definition:
    fn check_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
        if !is_camel_case(ident) {
            cx.span_lint(
references:- 4
1220:         ast::ItemTy(..) | ast::ItemStruct(..) => {
1221:             check_case(cx, "type", it.ident, it.span)
1222:         }
1223:         ast::ItemTrait(..) => {
1224:             check_case(cx, "trait", it.ident, it.span)
1225:         }
--
1228:             for variant in enum_definition.variants.iter() {
1229:                 check_case(cx, "variant", variant.node.name, variant.span);
1230:             }


librustc/middle/lint.rs:998:1-998:1 -struct- definition:
struct RawPtrDerivingVisitor<'a> {
    cx: &'a Context<'a>
}
references:- 2
1003: impl<'a> Visitor<()> for RawPtrDerivingVisitor<'a> {
1004:     fn visit_ty(&mut self, ty: &ast::Ty, _: ()) {
--
1022:         ast::ItemStruct(..) | ast::ItemEnum(..) => {
1023:             let mut visitor = RawPtrDerivingVisitor { cx: cx };
1024:             visit::walk_item(&mut visitor, item, ());


librustc/middle/lint.rs:932:1-932:1 -fn- definition:
fn check_heap_type(cx: &Context, span: Span, ty: ty::t) {
    let xs = [ManagedHeapMemory, OwnedHeapMemory, HeapMemory];
    for &lint in xs.iter() {
references:- 3
1116:     let ty = ty::expr_ty(cx.tcx, e);
1117:     check_heap_type(cx, e.span, ty);
1118: }


librustc/middle/lint.rs:1451:1-1451:1 -fn- definition:
fn check_missing_doc_attrs(cx: &Context,
                           id: Option<ast::NodeId>,
                           attrs: &[ast::Attribute],
references:- 6
1540:         ast::NamedField(_, vis) if vis == ast::Public =>
1541:             check_missing_doc_attrs(cx,
1542:                                     Some(cx.cur_struct_def_id),
--
1550: fn check_missing_doc_variant(cx: &Context, v: &ast::Variant) {
1551:     check_missing_doc_attrs(cx,
1552:                             Some(v.node.id),
--
1843:         // here.
1844:         check_missing_doc_attrs(cx,
1845:                                 None,


librustc/middle/lint.rs:1308:1-1308:1 -fn- definition:
fn check_unnecessary_parens_core(cx: &Context, value: &ast::Expr, msg: &str) {
    match value.node {
        ast::ExprParen(_) => {
references:- 2
1342:     };
1343:     check_unnecessary_parens_core(cx, value, msg);
1344: }


librustc/middle/lint.rs:139:47-139:47 -struct- definition:
pub struct LintSpec {
    pub default: level,
    pub lint: Lint,
references:- 72
librustc/lib.rs:
librustc/middle/lint.rs:


librustc/middle/lint.rs:812:4-812:4 -fn- definition:
    fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
        match int_ty {
            ast::TyI =>    (i64::MIN,        i64::MAX),
references:- 2
843:             ty::ty_int(int_ty) => {
844:                 let (min, max) = int_ty_range(int_ty);
845:                 let lit_val: i64 = match lit.node {


librustc/middle/lint.rs:148:16-148:16 -enum- definition:
enum LintSource {
    Node(Span),
    Default,
references:- 7
149: enum LintSource {
--
455:     // was modified.
456:     lint_stack: Vec<(Lint, level, LintSource)> ,
--
470:     fn get_source(&self, lint: Lint) -> LintSource {
471:         match self.cur.find(&(lint as uint)) {
--
477:     fn set_level(&mut self, lint: Lint, level: level, src: LintSource) {
478:         if level == allow {