(index<- )        ./librustc/middle/typeck/check/mod.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  /*
   12  
   13  # check.rs
   14  
   15  Within the check phase of type check, we check each item one at a time
   16  (bodies of function expressions are checked as part of the containing
   17  function).  Inference is used to supply types wherever they are
   18  unknown.
   19  
   20  By far the most complex case is checking the body of a function. This
   21  can be broken down into several distinct phases:
   22  
   23  - gather: creates type variables to represent the type of each local
   24    variable and pattern binding.
   25  
   26  - main: the main pass does the lion's share of the work: it
   27    determines the types of all expressions, resolves
   28    methods, checks for most invalid conditions, and so forth.  In
   29    some cases, where a type is unknown, it may create a type or region
   30    variable and use that as the type of an expression.
   31  
   32    In the process of checking, various constraints will be placed on
   33    these type variables through the subtyping relationships requested
   34    through the `demand` module.  The `typeck::infer` module is in charge
   35    of resolving those constraints.
   36  
   37  - regionck: after main is complete, the regionck pass goes over all
   38    types looking for regions and making sure that they did not escape
   39    into places they are not in scope.  This may also influence the
   40    final assignments of the various region variables if there is some
   41    flexibility.
   42  
   43  - vtable: find and records the impls to use for each trait bound that
   44    appears on a type parameter.
   45  
   46  - writeback: writes the final types within a function body, replacing
   47    type variables with their final inferred types.  These final types
   48    are written into the `tcx.node_types` table, which should *never* contain
   49    any reference to a type variable.
   50  
   51  ## Intermediate types
   52  
   53  While type checking a function, the intermediate types for the
   54  expressions, blocks, and so forth contained within the function are
   55  stored in `fcx.node_types` and `fcx.node_type_substs`.  These types
   56  may contain unresolved type variables.  After type checking is
   57  complete, the functions in the writeback module are used to take the
   58  types from this table, resolve them, and then write them into their
   59  permanent home in the type context `ccx.tcx`.
   60  
   61  This means that during inferencing you should use `fcx.write_ty()`
   62  and `fcx.expr_ty()` / `fcx.node_ty()` to write/obtain the types of
   63  nodes within the function.
   64  
   65  The types of top-level items, which never contain unbound type
   66  variables, are stored directly into the `tcx` tables.
   67  
   68  n.b.: A type variable is not the same thing as a type parameter.  A
   69  type variable is rather an "instance" of a type parameter: that is,
   70  given a generic function `fn foo<T>(t: T)`: while checking the
   71  function `foo`, the type `ty_param(0)` refers to the type `T`, which
   72  is treated in abstract.  When `foo()` is called, however, `T` will be
   73  substituted for a fresh type variable `N`.  This variable will
   74  eventually be resolved to some concrete type (which might itself be
   75  type parameter).
   76  
   77  */
   78  
   79  
   80  use middle::const_eval;
   81  use middle::lang_items::{ExchangeHeapLangItem, GcLangItem};
   82  use middle::lang_items::{ManagedHeapLangItem};
   83  use middle::lint::UnreachableCode;
   84  use middle::pat_util::pat_id_map;
   85  use middle::pat_util;
   86  use middle::subst::Subst;
   87  use middle::ty::{FnSig, VariantInfo};
   88  use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
   89  use middle::ty::{substs, param_ty, Disr, ExprTyProvider};
   90  use middle::ty;
   91  use middle::ty_fold::TypeFolder;
   92  use middle::typeck::astconv::AstConv;
   93  use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
   94  use middle::typeck::astconv;
   95  use middle::typeck::check::_match::pat_ctxt;
   96  use middle::typeck::check::method::{AutoderefReceiver};
   97  use middle::typeck::check::method::{AutoderefReceiverFlag};
   98  use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
   99  use middle::typeck::check::method::{DontAutoderefReceiver};
  100  use middle::typeck::check::method::{IgnoreStaticMethods, ReportStaticMethods};
  101  use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
  102  use middle::typeck::check::regionmanip::relate_free_regions;
  103  use middle::typeck::check::vtable::VtableContext;
  104  use middle::typeck::CrateCtxt;
  105  use middle::typeck::infer::{resolve_type, force_tvar};
  106  use middle::typeck::infer;
  107  use middle::typeck::rscope::RegionScope;
  108  use middle::typeck::{lookup_def_ccx};
  109  use middle::typeck::no_params;
  110  use middle::typeck::{require_same_types, vtable_map};
  111  use middle::typeck::{MethodCall, MethodMap};
  112  use middle::lang_items::TypeIdLangItem;
  113  use util::common::{block_query, indenter, loop_query};
  114  use util::ppaux;
  115  use util::ppaux::{UserString, Repr};
  116  use util::nodemap::{FnvHashMap, NodeMap};
  117  
  118  use std::cell::{Cell, RefCell};
  119  use collections::HashMap;
  120  use std::mem::replace;
  121  use std::rc::Rc;
  122  use std::vec::Vec;
  123  use syntax::abi;
  124  use syntax::ast::{Provided, Required};
  125  use syntax::ast;
  126  use syntax::ast_map;
  127  use syntax::ast_util::local_def;
  128  use syntax::ast_util;
  129  use syntax::attr;
  130  use syntax::codemap::Span;
  131  use syntax::codemap;
  132  use syntax::owned_slice::OwnedSlice;
  133  use syntax::parse::token;
  134  use syntax::print::pprust;
  135  use syntax::visit;
  136  use syntax::visit::Visitor;
  137  use syntax;
  138  
  139  pub mod _match;
  140  pub mod vtable;
  141  pub mod writeback;
  142  pub mod regionmanip;
  143  pub mod regionck;
  144  pub mod demand;
  145  pub mod method;
  146  
  147  /// Fields that are part of a `FnCtxt` which are inherited by
  148  /// closures defined within the function.  For example:
  149  ///
  150  ///     fn foo() {
  151  ///         bar(proc() { ... })
  152  ///     }
  153  ///
  154  /// Here, the function `foo()` and the closure passed to
  155  /// `bar()` will each have their own `FnCtxt`, but they will
  156  /// share the inherited fields.
  157  pub struct Inherited<'a> {
  158      infcx: infer::InferCtxt<'a>,
  159      locals: RefCell<NodeMap<ty::t>>,
  160      param_env: ty::ParameterEnvironment,
  161  
  162      // Temporary tables:
  163      node_types: RefCell<NodeMap<ty::t>>,
  164      node_type_substs: RefCell<NodeMap<ty::substs>>,
  165      adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
  166      method_map: MethodMap,
  167      vtable_map: vtable_map,
  168      upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
  169  }
  170  
  171  #[deriving(Clone)]
  172  pub enum FnKind {
  173      // A do-closure.
  174      DoBlock,
  175  
  176      // A normal closure or fn item.
  177      Vanilla
  178  }
  179  
  180  #[deriving(Clone)]
  181  pub struct FnStyleState {
  182      pub def: ast::NodeId,
  183      pub fn_style: ast::FnStyle,
  184      from_fn: bool
  185  }
  186  
  187  impl FnStyleState {
  188      pub fn function(fn_styleast::FnStyle, defast::NodeId) -> FnStyleState {
  189          FnStyleState { def: def, fn_style: fn_style, from_fn: true }
  190      }
  191  
  192      pub fn recurse(&mut self, blk&ast::Block) -> FnStyleState {
  193          match self.fn_style {
  194              // If this unsafe, then if the outer function was already marked as
  195              // unsafe we shouldn't attribute the unsafe'ness to the block. This
  196              // way the block can be warned about instead of ignoring this
  197              // extraneous block (functions are never warned about).
  198              ast::UnsafeFn if self.from_fn => *self,
  199  
  200              fn_style => {
  201                  let (fn_style, def) = match blk.rules {
  202                      ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id),
  203                      ast::DefaultBlock => (fn_style, self.def),
  204                  };
  205                  FnStyleState{ def: def,
  206                               fn_style: fn_style,
  207                               from_fn: false }
  208              }
  209          }
  210      }
  211  }
  212  
  213  /// Whether `check_binop` is part of an assignment or not.
  214  /// Used to know wether we allow user overloads and to print
  215  /// better messages on error.
  216  #[deriving(Eq)]
  217  enum IsBinopAssignment{
  218      SimpleBinop,
  219      BinopAssignment,
  220  }
  221  
  222  #[deriving(Clone)]
  223  pub struct FnCtxt<'a> {
  224      // This flag is set to true if, during the writeback phase, we encounter
  225      // a type error in this function.
  226      writeback_errors: Cell<bool>,
  227  
  228      // Number of errors that had been reported when we started
  229      // checking this function. On exit, if we find that *more* errors
  230      // have been reported, we will skip regionck and other work that
  231      // expects the types within the function to be consistent.
  232      err_count_on_creation: uint,
  233  
  234      ret_ty: ty::t,
  235      ps: RefCell<FnStyleState>,
  236  
  237      // Sometimes we generate region pointers where the precise region
  238      // to use is not known. For example, an expression like `&x.f`
  239      // where `x` is of type `@T`: in this case, we will be rooting
  240      // `x` onto the stack frame, and we could choose to root it until
  241      // the end of (almost) any enclosing block or expression.  We
  242      // want to pick the narrowest block that encompasses all uses.
  243      //
  244      // What we do in such cases is to generate a region variable with
  245      // `region_lb` as a lower bound.  The regionck pass then adds
  246      // other constraints based on how the variable is used and region
  247      // inference selects the ultimate value.  Finally, borrowck is
  248      // charged with guaranteeing that the value whose address was taken
  249      // can actually be made to live as long as it needs to live.
  250      region_lb: Cell<ast::NodeId>,
  251  
  252      // Says whether we're inside a for loop, in a do block
  253      // or neither. Helps with error messages involving the
  254      // function return type.
  255      fn_kind: FnKind,
  256  
  257      inh: &'a Inherited<'a>,
  258  
  259      ccx: &'a CrateCtxt<'a>,
  260  }
  261  
  262  impl<'a> Inherited<'a> {
  263      fn new(tcx&'a ty::ctxt,
  264             param_envty::ParameterEnvironment)
  265             -> Inherited<'a> {
  266          Inherited {
  267              infcx: infer::new_infer_ctxt(tcx),
  268              locals: RefCell::new(NodeMap::new()),
  269              param_env: param_env,
  270              node_types: RefCell::new(NodeMap::new()),
  271              node_type_substs: RefCell::new(NodeMap::new()),
  272              adjustments: RefCell::new(NodeMap::new()),
  273              method_map: RefCell::new(FnvHashMap::new()),
  274              vtable_map: RefCell::new(FnvHashMap::new()),
  275              upvar_borrow_map: RefCell::new(HashMap::new()),
  276          }
  277      }
  278  }
  279  
  280  // Used by check_const and check_enum_variants
  281  fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
  282                       inh: &'a Inherited<'a>,
  283                       rtyty::t,
  284                       region_bndast::NodeId)
  285                       -> FnCtxt<'a> {
  286      FnCtxt {
  287          writeback_errors: Cell::new(false),
  288          err_count_on_creation: ccx.tcx.sess.err_count(),
  289          ret_ty: rty,
  290          ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)),
  291          region_lb: Cell::new(region_bnd),
  292          fn_kind: Vanilla,
  293          inh: inh,
  294          ccx: ccx
  295      }
  296  }
  297  
  298  fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
  299      // It's kind of a kludge to manufacture a fake function context
  300      // and statement context, but we might as well do write the code only once
  301      let param_env = ty::ParameterEnvironment { free_substs: substs::empty(),
  302                                                 self_param_bound: None,
  303                                                 type_param_bounds: Vec::new() };
  304      Inherited::new(ccx.tcx, param_env)
  305  }
  306  
  307  impl<'a> ExprTyProvider for FnCtxt<'a> {
  308      fn expr_ty(&self, ex&ast::Expr) -> ty::t {
  309          self.expr_ty(ex)
  310      }
  311  
  312      fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
  313          self.ccx.tcx
  314      }
  315  }
  316  
  317  struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
  318  
  319  impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
  320      fn visit_item(&mut self, i&ast::Item, _()) {
  321          check_item(self.ccx, i);
  322          visit::walk_item(self, i, ());
  323      }
  324  }
  325  
  326  struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
  327  
  328  impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
  329      fn visit_item(&mut self, i&ast::Item, _()) {
  330          check_item_sized(self.ccx, i);
  331          visit::walk_item(self, i, ());
  332      }
  333  }
  334  
  335  pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
  336      let mut visit = CheckItemTypesVisitor { ccx: ccx };
  337      visit::walk_crate(&mut visit, krate, ());
  338  
  339      ccx.tcx.sess.abort_if_errors();
  340  
  341      let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
  342      visit::walk_crate(&mut visit, krate, ());
  343  }
  344  
  345  fn check_bare_fn(ccx: &CrateCtxt,
  346                   decl: &ast::FnDecl,
  347                   body: &ast::Block,
  348                   idast::NodeId,
  349                   ftyty::t,
  350                   param_envty::ParameterEnvironment) {
  351      // Compute the fty from point of view of inside fn
  352      // (replace any type-scheme with a type)
  353      let fty = fty.subst(ccx.tcx, &param_env.free_substs);
  354  
  355      match ty::get(fty).sty {
  356          ty::ty_bare_fn(ref fn_ty) => {
  357              let inh = Inherited::new(ccx.tcx, param_env);
  358              let fcx = check_fn(ccx, fn_ty.fn_style, &fn_ty.sig,
  359                                 decl, id, body, Vanilla, &inh);
  360  
  361              vtable::resolve_in_block(&fcx, body);
  362              regionck::regionck_fn(&fcx, body);
  363              writeback::resolve_type_vars_in_fn(&fcx, decl, body);
  364          }
  365          _ => ccx.tcx.sess.impossible_case(body.span,
  366                                   "check_bare_fn: function type expected")
  367      }
  368  }
  369  
  370  struct GatherLocalsVisitor<'a> {
  371      fcx: &'a FnCtxt<'a>
  372  }
  373  
  374  impl<'a> GatherLocalsVisitor<'a> {
  375      fn assign(&mut self, nidast::NodeId, ty_optOption<ty::t>) {
  376              match ty_opt {
  377                  None => {
  378                      // infer the variable's type
  379                      let var_id = self.fcx.infcx().next_ty_var_id();
  380                      let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
  381                      self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
  382                  }
  383                  Some(typ) => {
  384                      // take type that the user specified
  385                      self.fcx.inh.locals.borrow_mut().insert(nid, typ);
  386                  }
  387              }
  388      }
  389  }
  390  
  391  impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
  392      // Add explicitly-declared locals.
  393      fn visit_local(&mut self, local&ast::Local, _()) {
  394          let o_ty = match local.ty.node {
  395              ast::TyInfer => None,
  396              _ => Some(self.fcx.to_ty(local.ty))
  397          };
  398          self.assign(local.id, o_ty);
  399          debug!("Local variable {} is assigned type {}",
  400                 self.fcx.pat_to_str(local.pat),
  401                 self.fcx.infcx().ty_to_str(
  402                     self.fcx.inh.locals.borrow().get_copy(&local.id)));
  403          visit::walk_local(self, local, ());
  404      }
  405  
  406      // Add pattern bindings.
  407      fn visit_pat(&mut self, p&ast::Pat, _()) {
  408              match p.node {
  409                ast::PatIdent(_, ref path, _)
  410                    if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
  411                  self.assign(p.id, None);
  412                  debug!("Pattern binding {} is assigned to {}",
  413                         token::get_ident(path.segments.get(0).identifier),
  414                         self.fcx.infcx().ty_to_str(
  415                             self.fcx.inh.locals.borrow().get_copy(&p.id)));
  416                }
  417                _ => {}
  418              }
  419              visit::walk_pat(self, p, ());
  420  
  421      }
  422  
  423      fn visit_block(&mut self, b&ast::Block, _()) {
  424          // non-obvious: the `blk` variable maps to region lb, so
  425          // we have to keep this up-to-date.  This
  426          // is... unfortunate.  It'd be nice to not need this.
  427          self.fcx.with_region_lb(b.id, || visit::walk_block(self, b, ()));
  428      }
  429  
  430      // Don't descend into fns and items
  431      fn visit_fn(&mut self, _&visit::FnKind, _&ast::FnDecl,
  432                  _&ast::Block, _Span, _ast::NodeId, _()) { }
  433      fn visit_item(&mut self, _&ast::Item, _()) { }
  434  
  435  }
  436  
  437  fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
  438                  fn_styleast::FnStyle,
  439                  fn_sig: &ty::FnSig,
  440                  decl: &ast::FnDecl,
  441                  idast::NodeId,
  442                  body: &ast::Block,
  443                  fn_kindFnKind,
  444                  inherited: &'a Inherited<'a>) -> FnCtxt<'a>
  445  {
  446      /*!
  447       * Helper used by check_bare_fn and check_expr_fn.  Does the
  448       * grungy work of checking a function body and returns the
  449       * function context used for that purpose, since in the case of a
  450       * fn item there is still a bit more to do.
  451       *
  452       * - ...
  453       * - inherited: other fields inherited from the enclosing fn (if any)
  454       */
  455  
  456      let tcx = ccx.tcx;
  457      let err_count_on_creation = tcx.sess.err_count();
  458  
  459      // First, we have to replace any bound regions in the fn type with free ones.
  460      // The free region references will be bound the node_id of the body block.
  461      let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
  462          ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
  463      });
  464  
  465      relate_free_regions(tcx, &fn_sig);
  466  
  467      let arg_tys = fn_sig.inputs.as_slice();
  468      let ret_ty = fn_sig.output;
  469  
  470      debug!("check_fn(arg_tys={:?}, ret_ty={:?})",
  471             arg_tys.iter().map(|&a| ppaux::ty_to_str(tcx, a)).collect::<Vec<~str>>(),
  472             ppaux::ty_to_str(tcx, ret_ty));
  473  
  474      // Create the function context.  This is either derived from scratch or,
  475      // in the case of function expressions, based on the outer context.
  476      let fcx = FnCtxt {
  477          writeback_errors: Cell::new(false),
  478          err_count_on_creation: err_count_on_creation,
  479          ret_ty: ret_ty,
  480          ps: RefCell::new(FnStyleState::function(fn_style, id)),
  481          region_lb: Cell::new(body.id),
  482          fn_kind: fn_kind,
  483          inh: inherited,
  484          ccx: ccx
  485      };
  486  
  487      {
  488  
  489          let mut visit = GatherLocalsVisitor { fcx: &fcx, };
  490          // Add formal parameters.
  491          for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
  492              // Create type variables for each argument.
  493              pat_util::pat_bindings(&tcx.def_map,
  494                                     input.pat,
  495                                     |_bm, pat_id, _sp, _path| {
  496                                         visit.assign(pat_id, None);
  497                                     });
  498  
  499              // Check the pattern.
  500              let pcx = pat_ctxt {
  501                  fcx: &fcx,
  502                  map: pat_id_map(&tcx.def_map, input.pat),
  503              };
  504              _match::check_pat(&pcx, input.pat, *arg_ty);
  505          }
  506  
  507          visit.visit_block(body, ());
  508      }
  509  
  510      check_block_with_expected(&fcx, body, Some(ret_ty));
  511  
  512      // We unify the tail expr's type with the
  513      // function result type, if there is a tail expr.
  514      match body.expr {
  515          Some(tail_expr) => {
  516              // Special case: we print a special error if there appears
  517              // to be do-block/for-loop confusion
  518              demand::suptype_with_fn(&fcx, tail_expr.span, false,
  519                  fcx.ret_ty, fcx.expr_ty(tail_expr),
  520                  |sp, e, a, s| {
  521                      fcx.report_mismatched_return_types(sp, e, a, s);
  522                  });
  523          }
  524          None => {}
  525      }
  526  
  527      for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
  528          fcx.write_ty(input.id, *arg);
  529      }
  530  
  531      fcx
  532  }
  533  
  534  fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_idast::DefId) -> Span {
  535      assert!(field.id.krate == ast::LOCAL_CRATE);
  536      let item = match tcx.map.find(struct_id.node) {
  537          Some(ast_map::NodeItem(item)) => item,
  538          None => fail!("node not in ast map: {}", struct_id.node),
  539          _ => fail!("expected item, found {}", tcx.map.node_to_str(struct_id.node))
  540      };
  541  
  542      match item.node {
  543          ast::ItemStruct(struct_def, _) => {
  544              match struct_def.fields.iter().find(|f| match f.node.kind {
  545                  ast::NamedField(ident, _) => ident.name == field.name,
  546                  _ => false,
  547              }) {
  548                  Some(f) => f.span,
  549                  None => tcx.sess.bug(format!("Could not find field {}",
  550                                               token::get_name(field.name))),
  551              }
  552          },
  553          _ => tcx.sess.bug("Field found outside of a struct?"),
  554      }
  555  }
  556  
  557  // Check struct fields are uniquely named wrt parents.
  558  fn check_for_field_shadowing(tcx: &ty::ctxt,
  559                               idast::DefId) {
  560      let struct_fields = tcx.struct_fields.borrow();
  561      let fields = struct_fields.get(&id);
  562  
  563      let superstructs = tcx.superstructs.borrow();
  564      let super_struct = superstructs.get(&id);
  565      match *super_struct {
  566          Some(parent_id) => {
  567              let super_fields = ty::lookup_struct_fields(tcx, parent_id);
  568              for f in fields.iter() {
  569                  match super_fields.iter().find(|sf| f.name == sf.name) {
  570                      Some(prev_field) => {
  571                          tcx.sess.span_err(span_for_field(tcx, f, id),
  572                              format!("field `{}` hides field declared in super-struct",
  573                                      token::get_name(f.name)));
  574                          tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
  575                              "previously declared here");
  576                      },
  577                      None => {}
  578                  }
  579              }
  580          },
  581          None => {}
  582      }
  583  }
  584  
  585  fn check_fields_sized(tcx: &ty::ctxt,
  586                        struct_def: &ast::StructDef) {
  587      let len = struct_def.fields.len();
  588      if len == 0 {
  589          return;
  590      }
  591      for f in struct_def.fields.slice_to(len - 1).iter() {
  592          let t = ty::node_id_to_type(tcx, f.node.id);
  593          if !ty::type_is_sized(tcx, t) {
  594              match f.node.kind {
  595                  ast::NamedField(ident, _) => {
  596                      tcx.sess.span_err(f.span, format!("type `{}` is dynamically sized. \
  597                                                         dynamically sized types may only \
  598                                                         appear as the type of the final \
  599                                                         field in a struct",
  600                                                        token::get_ident(ident)));
  601                  }
  602                  ast::UnnamedField(_) => {
  603                      tcx.sess.span_err(f.span, "dynamically sized type in field");
  604                  }
  605              }
  606          }
  607      }
  608  }
  609  
  610  pub fn check_struct(ccx: &CrateCtxt, idast::NodeId, spanSpan) {
  611      let tcx = ccx.tcx;
  612  
  613      check_representable(tcx, span, id, "struct");
  614      check_instantiable(tcx, span, id);
  615  
  616      // Check there are no overlapping fields in super-structs
  617      check_for_field_shadowing(tcx, local_def(id));
  618  
  619      if ty::lookup_simd(tcx, local_def(id)) {
  620          check_simd(tcx, span, id);
  621      }
  622  }
  623  
  624  pub fn check_item_sized(ccx: &CrateCtxt, it: &ast::Item) {
  625      debug!("check_item(it.id={}, it.ident={})",
  626             it.id,
  627             ty::item_path_str(ccx.tcx, local_def(it.id)));
  628      let _indenter = indenter();
  629  
  630      match it.node {
  631          ast::ItemEnum(ref enum_definition, _) => {
  632              check_enum_variants_sized(ccx,
  633                                        enum_definition.variants.as_slice());
  634          }
  635          ast::ItemStruct(..) => {
  636              check_fields_sized(ccx.tcx, ccx.tcx.map.expect_struct(it.id));
  637          }
  638          _ => {}
  639      }
  640  }
  641  
  642  pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
  643      debug!("check_item(it.id={}, it.ident={})",
  644             it.id,
  645             ty::item_path_str(ccx.tcx, local_def(it.id)));
  646      let _indenter = indenter();
  647  
  648      match it.node {
  649        ast::ItemStatic(_, _, e) => check_const(ccx, it.span, e, it.id),
  650        ast::ItemEnum(ref enum_definition, _) => {
  651          check_enum_variants(ccx,
  652                              it.span,
  653                              enum_definition.variants.as_slice(),
  654                              it.id);
  655        }
  656        ast::ItemFn(decl, _, _, _, body) => {
  657          let fn_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
  658  
  659          let param_env = ty::construct_parameter_environment(
  660                  ccx.tcx,
  661                  None,
  662                  fn_tpt.generics.type_param_defs(),
  663                  [],
  664                  [],
  665                  fn_tpt.generics.region_param_defs.as_slice(),
  666                  body.id);
  667  
  668          check_bare_fn(ccx, decl, body, it.id, fn_tpt.ty, param_env);
  669        }
  670        ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
  671          debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
  672  
  673          let impl_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
  674          for m in ms.iter() {
  675              check_method_body(ccx, &impl_tpt.generics, None, *m);
  676          }
  677  
  678          match *opt_trait_ref {
  679              Some(ref ast_trait_ref) => {
  680                  let impl_trait_ref =
  681                      ty::node_id_to_trait_ref(ccx.tcx, ast_trait_ref.ref_id);
  682                  check_impl_methods_against_trait(ccx,
  683                                               it.span,
  684                                               &impl_tpt.generics,
  685                                               ast_trait_ref,
  686                                               &*impl_trait_ref,
  687                                               ms.as_slice());
  688                  vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, &*impl_trait_ref);
  689              }
  690              None => { }
  691          }
  692  
  693        }
  694        ast::ItemTrait(_, _, _, ref trait_methods) => {
  695          let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
  696          for trait_method in (*trait_methods).iter() {
  697              match *trait_method {
  698                  Required(..) => {
  699                      // Nothing to do, since required methods don't have
  700                      // bodies to check.
  701                  }
  702                  Provided(m) => {
  703                      check_method_body(ccx, &trait_def.generics,
  704                                        Some(trait_def.trait_ref.clone()), m);
  705                  }
  706              }
  707          }
  708        }
  709        ast::ItemStruct(..) => {
  710          check_struct(ccx, it.id, it.span);
  711        }
  712        ast::ItemTy(ref t, ref generics) => {
  713          let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
  714          check_bounds_are_used(ccx, t.span, &generics.ty_params, tpt_ty);
  715        }
  716        ast::ItemForeignMod(ref m) => {
  717          if m.abi == abi::RustIntrinsic {
  718              for item in m.items.iter() {
  719                  check_intrinsic_type(ccx, *item);
  720              }
  721          } else {
  722              for item in m.items.iter() {
  723                  let tpt = ty::lookup_item_type(ccx.tcx, local_def(item.id));
  724                  if tpt.generics.has_type_params() {
  725                      ccx.tcx.sess.span_err(item.span, "foreign items may not have type parameters");
  726                  }
  727  
  728                  match item.node {
  729                      ast::ForeignItemFn(ref fn_decl, _) => {
  730                          if fn_decl.variadic && m.abi != abi::C {
  731                              ccx.tcx.sess.span_err(
  732                                  item.span, "variadic function must have C calling convention");
  733                          }
  734                      }
  735                      _ => {}
  736                  }
  737              }
  738          }
  739        }
  740        _ => {/* nothing to do */ }
  741      }
  742  }
  743  
  744  fn check_method_body(ccx: &CrateCtxt,
  745                       item_generics: &ty::Generics,
  746                       self_boundOption<Rc<ty::TraitRef>>,
  747                       method: &ast::Method) {
  748      /*!
  749       * Type checks a method body.
  750       *
  751       * # Parameters
  752       * - `item_generics`: generics defined on the impl/trait that contains
  753       *   the method
  754       * - `self_bound`: bound for the `Self` type parameter, if any
  755       * - `method`: the method definition
  756       */
  757  
  758      debug!("check_method_body(item_generics={}, \
  759              self_bound={}, \
  760              method.id={})",
  761              item_generics.repr(ccx.tcx),
  762              self_bound.repr(ccx.tcx),
  763              method.id);
  764      let method_def_id = local_def(method.id);
  765      let method_ty = ty::method(ccx.tcx, method_def_id);
  766      let method_generics = &method_ty.generics;
  767  
  768      let param_env =
  769          ty::construct_parameter_environment(
  770              ccx.tcx,
  771              self_bound,
  772              item_generics.type_param_defs(),
  773              method_generics.type_param_defs(),
  774              item_generics.region_param_defs(),
  775              method_generics.region_param_defs(),
  776              method.body.id);
  777  
  778      let fty = ty::node_id_to_type(ccx.tcx, method.id);
  779  
  780      check_bare_fn(ccx, method.decl, method.body, method.id, fty, param_env);
  781  }
  782  
  783  fn check_impl_methods_against_trait(ccx: &CrateCtxt,
  784                                      impl_spanSpan,
  785                                      impl_generics: &ty::Generics,
  786                                      ast_trait_ref: &ast::TraitRef,
  787                                      impl_trait_ref: &ty::TraitRef,
  788                                      impl_methods: &[@ast::Method]) {
  789      // Locate trait methods
  790      let tcx = ccx.tcx;
  791      let trait_methods = ty::trait_methods(tcx, impl_trait_ref.def_id);
  792  
  793      // Check existing impl methods to see if they are both present in trait
  794      // and compatible with trait signature
  795      for impl_method in impl_methods.iter() {
  796          let impl_method_def_id = local_def(impl_method.id);
  797          let impl_method_ty = ty::method(ccx.tcx, impl_method_def_id);
  798  
  799          // If this is an impl of a trait method, find the corresponding
  800          // method definition in the trait.
  801          let opt_trait_method_ty =
  802              trait_methods.iter().
  803              find(|tm| tm.ident.name == impl_method_ty.ident.name);
  804          match opt_trait_method_ty {
  805              Some(trait_method_ty) => {
  806                  compare_impl_method(ccx.tcx,
  807                                      impl_generics,
  808                                      &*impl_method_ty,
  809                                      impl_method.span,
  810                                      impl_method.body.id,
  811                                      &**trait_method_ty,
  812                                      &impl_trait_ref.substs);
  813              }
  814              None => {
  815                  tcx.sess.span_err(
  816                      impl_method.span,
  817                      format!("method `{}` is not a member of trait `{}`",
  818                              token::get_ident(impl_method_ty.ident),
  819                              pprust::path_to_str(&ast_trait_ref.path)));
  820              }
  821          }
  822      }
  823  
  824      // Check for missing methods from trait
  825      let provided_methods = ty::provided_trait_methods(tcx,
  826                                                        impl_trait_ref.def_id);
  827      let mut missing_methods = Vec::new();
  828      for trait_method in trait_methods.iter() {
  829          let is_implemented =
  830              impl_methods.iter().any(
  831                  |m| m.ident.name == trait_method.ident.name);
  832          let is_provided =
  833              provided_methods.iter().any(
  834                  |m| m.ident.name == trait_method.ident.name);
  835          if !is_implemented && !is_provided {
  836              missing_methods.push(
  837                  format!("`{}`", token::get_ident(trait_method.ident)));
  838          }
  839      }
  840  
  841      if !missing_methods.is_empty() {
  842          tcx.sess.span_err(
  843              impl_span,
  844              format!("not all trait methods implemented, missing: {}",
  845                      missing_methods.connect(", ")));
  846      }
  847  }
  848  
  849  /**
  850   * Checks that a method from an impl/class conforms to the signature of
  851   * the same method as declared in the trait.
  852   *
  853   * # Parameters
  854   *
  855   * - impl_generics: the generics declared on the impl itself (not the method!)
  856   * - impl_m: type of the method we are checking
  857   * - impl_m_span: span to use for reporting errors
  858   * - impl_m_body_id: id of the method body
  859   * - trait_m: the method in the trait
  860   * - trait_substs: the substitutions used on the type of the trait
  861   */
  862  fn compare_impl_method(tcx: &ty::ctxt,
  863                         impl_generics: &ty::Generics,
  864                         impl_m: &ty::Method,
  865                         impl_m_spanSpan,
  866                         impl_m_body_idast::NodeId,
  867                         trait_m: &ty::Method,
  868                         trait_substs: &ty::substs) {
  869      debug!("compare_impl_method()");
  870      let infcx = infer::new_infer_ctxt(tcx);
  871  
  872      let impl_tps = impl_generics.type_param_defs().len();
  873  
  874      // Try to give more informative error messages about self typing
  875      // mismatches.  Note that any mismatch will also be detected
  876      // below, where we construct a canonical function type that
  877      // includes the self parameter as a normal parameter.  It's just
  878      // that the error messages you get out of this code are a bit more
  879      // inscrutable, particularly for cases where one method has no
  880      // self.
  881      match (&trait_m.explicit_self, &impl_m.explicit_self) {
  882          (&ast::SelfStatic, &ast::SelfStatic) => {}
  883          (&ast::SelfStatic, _) => {
  884              tcx.sess.span_err(
  885                  impl_m_span,
  886                  format!("method `{}` has a `{}` declaration in the impl, \
  887                          but not in the trait",
  888                          token::get_ident(trait_m.ident),
  889                          pprust::explicit_self_to_str(impl_m.explicit_self)));
  890              return;
  891          }
  892          (_, &ast::SelfStatic) => {
  893              tcx.sess.span_err(
  894                  impl_m_span,
  895                  format!("method `{}` has a `{}` declaration in the trait, \
  896                          but not in the impl",
  897                          token::get_ident(trait_m.ident),
  898                          pprust::explicit_self_to_str(trait_m.explicit_self)));
  899              return;
  900          }
  901          _ => {
  902              // Let the type checker catch other errors below
  903          }
  904      }
  905  
  906      let num_impl_m_type_params = impl_m.generics.type_param_defs().len();
  907      let num_trait_m_type_params = trait_m.generics.type_param_defs().len();
  908      if num_impl_m_type_params != num_trait_m_type_params {
  909          tcx.sess.span_err(
  910              impl_m_span,
  911              format!("method `{method}` has {nimpl, plural, =1{type parameter} \
  912                                                          other{type parameters}}, \
  913                       but its trait declaration has {ntrait, plural, =1{type parameter} \
  914                                                                   other{type parameters}}",
  915                      method = token::get_ident(trait_m.ident),
  916                      nimpl = num_impl_m_type_params,
  917                      ntrait = num_trait_m_type_params));
  918          return;
  919      }
  920  
  921      if impl_m.fty.sig.inputs.len() != trait_m.fty.sig.inputs.len() {
  922          tcx.sess.span_err(
  923              impl_m_span,
  924              format!("method `{method}` has {nimpl, plural, =1{# parameter} \
  925                                                          other{# parameters}} \
  926                       but the declaration in trait `{trait}` has {ntrait}",
  927                   method = token::get_ident(trait_m.ident),
  928                   nimpl = impl_m.fty.sig.inputs.len(),
  929                   trait = ty::item_path_str(tcx, trait_m.def_id),
  930                   ntrait = trait_m.fty.sig.inputs.len()));
  931          return;
  932      }
  933  
  934      let it = trait_m.generics.type_param_defs().iter()
  935          .zip(impl_m.generics.type_param_defs().iter());
  936  
  937      for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
  938          // Check that the impl does not require any builtin-bounds
  939          // that the trait does not guarantee:
  940          let extra_bounds =
  941              impl_param_def.bounds.builtin_bounds -
  942              trait_param_def.bounds.builtin_bounds;
  943          if !extra_bounds.is_empty() {
  944             tcx.sess.span_err(
  945                 impl_m_span,
  946                 format!("in method `{}`, \
  947                         type parameter {} requires `{}`, \
  948                         which is not required by \
  949                         the corresponding type parameter \
  950                         in the trait declaration",
  951                         token::get_ident(trait_m.ident),
  952                         i,
  953                         extra_bounds.user_string(tcx)));
  954             return;
  955          }
  956  
  957          // FIXME(#2687)---we should be checking that the bounds of the
  958          // trait imply the bounds of the subtype, but it appears we
  959          // are...not checking this.
  960          if impl_param_def.bounds.trait_bounds.len() !=
  961              trait_param_def.bounds.trait_bounds.len()
  962          {
  963              tcx.sess.span_err(
  964                  impl_m_span,
  965                  format!("in method `{method}`, \
  966                          type parameter {typaram} has \
  967                          {nimpl, plural, =1{trait bound} other{trait bounds}}, \
  968                          but the corresponding type parameter in \
  969                          the trait declaration has \
  970                          {ntrait, plural, =1{trait bound} other{trait bounds}}",
  971                          method = token::get_ident(trait_m.ident),
  972                          typaram = i,
  973                          nimpl = impl_param_def.bounds.trait_bounds.len(),
  974                          ntrait = trait_param_def.bounds.trait_bounds.len()));
  975              return;
  976          }
  977      }
  978  
  979      // Create a substitution that maps the type parameters on the impl
  980      // to themselves and which replace any references to bound regions
  981      // in the self type with free regions.  So, for example, if the
  982      // impl type is "&'a str", then this would replace the self
  983      // type with a free region `self`.
  984      let dummy_impl_tpsVec<ty::t> =
  985          impl_generics.type_param_defs().iter().enumerate().
  986          map(|(i,t)| ty::mk_param(tcx, i, t.def_id)).
  987          collect();
  988      let dummy_method_tpsVec<ty::t> =
  989          impl_m.generics.type_param_defs().iter().enumerate().
  990          map(|(i,t)| ty::mk_param(tcx, i + impl_tps, t.def_id)).
  991          collect();
  992      let dummy_impl_regionsOwnedSlice<ty::Region> =
  993          impl_generics.region_param_defs().iter().
  994          map(|l| ty::ReFree(ty::FreeRegion {
  995                  scope_id: impl_m_body_id,
  996                  bound_region: ty::BrNamed(l.def_id, l.name)})).
  997          collect();
  998      let dummy_substs = ty::substs {
  999          tps: dummy_impl_tps.append(dummy_method_tps.as_slice()),
 1000          regions: ty::NonerasedRegions(dummy_impl_regions),
 1001          self_ty: None };
 1002  
 1003      // Create a bare fn type for trait/impl
 1004      // It'd be nice to refactor so as to provide the bare fn types instead.
 1005      let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
 1006      let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
 1007  
 1008      // Perform substitutions so that the trait/impl methods are expressed
 1009      // in terms of the same set of type/region parameters:
 1010      // - replace trait type parameters with those from `trait_substs`,
 1011      //   except with any reference to bound self replaced with `dummy_self_r`
 1012      // - replace method parameters on the trait with fresh, dummy parameters
 1013      //   that correspond to the parameters we will find on the impl
 1014      // - replace self region with a fresh, dummy region
 1015      let impl_fty = {
 1016          debug!("impl_fty (pre-subst){}", ppaux::ty_to_str(tcx, impl_fty));
 1017          impl_fty.subst(tcx, &dummy_substs)
 1018      };
 1019      debug!("impl_fty (post-subst){}", ppaux::ty_to_str(tcx, impl_fty));
 1020      let trait_fty = {
 1021          let substs { regions: trait_regions,
 1022                       tps: trait_tps,
 1023                       self_ty: self_ty } = trait_substs.subst(tcx, &dummy_substs);
 1024          let substs = substs {
 1025              regions: trait_regions,
 1026              tps: trait_tps.append(dummy_method_tps.as_slice()),
 1027              self_ty: self_ty,
 1028          };
 1029          debug!("trait_fty (pre-subst){} substs={}",
 1030                 trait_fty.repr(tcx), substs.repr(tcx));
 1031          trait_fty.subst(tcx, &substs)
 1032      };
 1033      debug!("trait_fty (post-subst){}", trait_fty.repr(tcx));
 1034  
 1035      match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
 1036                            impl_fty, trait_fty) {
 1037          Ok(()) => {}
 1038          Err(ref terr) => {
 1039              tcx.sess.span_err(
 1040                  impl_m_span,
 1041                  format!("method `{}` has an incompatible type for trait: {}",
 1042                          token::get_ident(trait_m.ident),
 1043                          ty::type_err_to_str(tcx, terr)));
 1044              ty::note_and_explain_type_err(tcx, terr);
 1045          }
 1046      }
 1047  }
 1048  
 1049  impl<'a> AstConv for FnCtxt<'a> {
 1050      fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
 1051  
 1052      fn get_item_ty(&self, idast::DefId) -> ty::ty_param_bounds_and_ty {
 1053          ty::lookup_item_type(self.tcx(), id)
 1054      }
 1055  
 1056      fn get_trait_def(&self, idast::DefId) -> Rc<ty::TraitDef> {
 1057          ty::lookup_trait_def(self.tcx(), id)
 1058      }
 1059  
 1060      fn ty_infer(&self, _spanSpan) -> ty::t {
 1061          self.infcx().next_ty_var()
 1062      }
 1063  }
 1064  
 1065  impl<'a> FnCtxt<'a> {
 1066      pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
 1067          &self.inh.infcx
 1068      }
 1069  
 1070      pub fn err_count_since_creation(&self) -> uint {
 1071          self.ccx.tcx.sess.err_count() - self.err_count_on_creation
 1072      }
 1073  
 1074      pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
 1075          VtableContext {
 1076              infcx: self.infcx(),
 1077              param_env: &self.inh.param_env
 1078          }
 1079      }
 1080  }
 1081  
 1082  impl<'a> RegionScope for infer::InferCtxt<'a> {
 1083      fn anon_regions(&self, spanSpan, countuint)
 1084                      -> Result<Vec<ty::Region> , ()> {
 1085          Ok(Vec::from_fn(count, |_| {
 1086              self.next_region_var(infer::MiscVariable(span))
 1087          }))
 1088      }
 1089  }
 1090  
 1091  impl<'a> FnCtxt<'a> {
 1092      pub fn tag(&self) -> ~str {
 1093          format!("{}", self as *FnCtxt)
 1094      }
 1095  
 1096      pub fn local_ty(&self, spanSpan, nidast::NodeId) -> ty::t {
 1097          match self.inh.locals.borrow().find(&nid) {
 1098              Some(&t) => t,
 1099              None => {
 1100                  self.tcx().sess.span_bug(
 1101                      span,
 1102                      format!("no type for local variable {:?}", nid));
 1103              }
 1104          }
 1105      }
 1106  
 1107      #[inline]
 1108      pub fn write_ty(&self, node_idast::NodeId, tyty::t) {
 1109          debug!("write_ty({}, {}) in fcx {}",
 1110                 node_id, ppaux::ty_to_str(self.tcx(), ty), self.tag());
 1111          self.inh.node_types.borrow_mut().insert(node_id, ty);
 1112      }
 1113  
 1114      pub fn write_substs(&self, node_idast::NodeId, subststy::substs) {
 1115          if !ty::substs_is_noop(&substs) {
 1116              debug!("write_substs({}, {}) in fcx {}",
 1117                     node_id,
 1118                     ty::substs_to_str(self.tcx(), &substs),
 1119                     self.tag());
 1120  
 1121              self.inh.node_type_substs.borrow_mut().insert(node_id, substs);
 1122          }
 1123      }
 1124  
 1125      pub fn write_ty_substs(&self,
 1126                             node_idast::NodeId,
 1127                             tyty::t,
 1128                             subststy::substs) {
 1129          let ty = ty::subst(self.tcx(), &substs, ty);
 1130          self.write_ty(node_id, ty);
 1131          self.write_substs(node_id, substs);
 1132      }
 1133  
 1134      pub fn write_autoderef_adjustment(&self,
 1135                                        node_idast::NodeId,
 1136                                        derefsuint) {
 1137          if derefs == 0 { return; }
 1138          self.write_adjustment(
 1139              node_id,
 1140              ty::AutoDerefRef(ty::AutoDerefRef {
 1141                  autoderefs: derefs,
 1142                  autoref: None })
 1143          );
 1144      }
 1145  
 1146      pub fn write_adjustment(&self,
 1147                              node_idast::NodeId,
 1148                              adjty::AutoAdjustment) {
 1149          debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
 1150          self.inh.adjustments.borrow_mut().insert(node_id, adj);
 1151      }
 1152  
 1153      pub fn write_nil(&self, node_idast::NodeId) {
 1154          self.write_ty(node_id, ty::mk_nil());
 1155      }
 1156      pub fn write_bot(&self, node_idast::NodeId) {
 1157          self.write_ty(node_id, ty::mk_bot());
 1158      }
 1159      pub fn write_error(&self, node_idast::NodeId) {
 1160          self.write_ty(node_id, ty::mk_err());
 1161      }
 1162  
 1163      pub fn to_ty(&self, ast_t&ast::Ty) -> ty::t {
 1164          ast_ty_to_ty(self, self.infcx(), ast_t)
 1165      }
 1166  
 1167      pub fn pat_to_str(&self, pat&ast::Pat) -> ~str {
 1168          pat.repr(self.tcx())
 1169      }
 1170  
 1171      pub fn expr_ty(&self, ex&ast::Expr) -> ty::t {
 1172          match self.inh.node_types.borrow().find(&ex.id) {
 1173              Some(&t) => t,
 1174              None => {
 1175                  self.tcx().sess.bug(format!("no type for expr in fcx {}",
 1176                                              self.tag()));
 1177              }
 1178          }
 1179      }
 1180  
 1181      pub fn node_ty(&self, idast::NodeId) -> ty::t {
 1182          match self.inh.node_types.borrow().find(&id) {
 1183              Some(&t) => t,
 1184              None => {
 1185                  self.tcx().sess.bug(
 1186                      format!("no type for node {}{} in fcx {}",
 1187                              id, self.tcx().map.node_to_str(id),
 1188                              self.tag()));
 1189              }
 1190          }
 1191      }
 1192  
 1193      pub fn method_ty_substs(&self, idast::NodeId) -> ty::substs {
 1194          match self.inh.method_map.borrow().find(&MethodCall::expr(id)) {
 1195              Some(method) => method.substs.clone(),
 1196              None => {
 1197                  self.tcx().sess.bug(
 1198                      format!("no method entry for node {}{} in fcx {}",
 1199                              id, self.tcx().map.node_to_str(id),
 1200                              self.tag()));
 1201              }
 1202          }
 1203      }
 1204  
 1205      pub fn opt_node_ty_substs(&self,
 1206                                idast::NodeId,
 1207                                f|&ty::substs|) {
 1208          match self.inh.node_type_substs.borrow().find(&id) {
 1209              Some(s) => { f(s) }
 1210              None => { }
 1211          }
 1212      }
 1213  
 1214      pub fn mk_subty(&self,
 1215                      a_is_expectedbool,
 1216                      origininfer::TypeOrigin,
 1217                      subty::t,
 1218                      supty::t)
 1219                      -> Result<(), ty::type_err> {
 1220          infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
 1221      }
 1222  
 1223      pub fn can_mk_subty(&self, subty::t, supty::t)
 1224                          -> Result<(), ty::type_err> {
 1225          infer::can_mk_subty(self.infcx(), sub, sup)
 1226      }
 1227  
 1228      pub fn mk_assignty(&self,
 1229                         expr&ast::Expr,
 1230                         subty::t,
 1231                         supty::t)
 1232                         -> Result<(), ty::type_err> {
 1233          match infer::mk_coercety(self.infcx(),
 1234                                   false,
 1235                                   infer::ExprAssignable(expr.span),
 1236                                   sub,
 1237                                   sup) {
 1238              Ok(None) => Ok(()),
 1239              Err(ref e) => Err((*e)),
 1240              Ok(Some(adjustment)) => {
 1241                  self.write_adjustment(expr.id, adjustment);
 1242                  Ok(())
 1243              }
 1244          }
 1245      }
 1246  
 1247      pub fn mk_eqty(&self,
 1248                     a_is_expectedbool,
 1249                     origininfer::TypeOrigin,
 1250                     subty::t,
 1251                     supty::t)
 1252                     -> Result<(), ty::type_err> {
 1253          infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
 1254      }
 1255  
 1256      pub fn mk_subr(&self,
 1257                     a_is_expectedbool,
 1258                     origininfer::SubregionOrigin,
 1259                     subty::Region,
 1260                     supty::Region) {
 1261          infer::mk_subr(self.infcx(), a_is_expected, origin, sub, sup)
 1262      }
 1263  
 1264      pub fn with_region_lb<R>(&self, lbast::NodeId, f|| -> R) -> R {
 1265          let old_region_lb = self.region_lb.get();
 1266          self.region_lb.set(lb);
 1267          let v = f();
 1268          self.region_lb.set(old_region_lb);
 1269          v
 1270      }
 1271  
 1272      pub fn type_error_message(&self,
 1273                                spSpan,
 1274                                mk_msg|~str| -> ~str,
 1275                                actual_tyty::t,
 1276                                errOption<&ty::type_err>) {
 1277          self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
 1278      }
 1279  
 1280      pub fn report_mismatched_return_types(&self,
 1281                                            spSpan,
 1282                                            ety::t,
 1283                                            aty::t,
 1284                                            err&ty::type_err) {
 1285          // Derived error
 1286          if ty::type_is_error(e) || ty::type_is_error(a) {
 1287              return;
 1288          }
 1289          self.infcx().report_mismatched_types(sp, e, a, err)
 1290      }
 1291  
 1292      pub fn report_mismatched_types(&self,
 1293                                     spSpan,
 1294                                     ety::t,
 1295                                     aty::t,
 1296                                     err&ty::type_err) {
 1297          self.infcx().report_mismatched_types(sp, e, a, err)
 1298      }
 1299  }
 1300  
 1301  pub enum LvaluePreference {
 1302      PreferMutLvalue,
 1303      NoPreference
 1304  }
 1305  
 1306  pub fn autoderef<T>(fcx: &FnCtxt, spSpan, base_tyty::t,
 1307                      expr_idOption<ast::NodeId>,
 1308                      mut lvalue_prefLvaluePreference,
 1309                      should_stop: |ty::t, uint| -> Option<T>)
 1310                      -> (ty::t, uint, Option<T>) {
 1311      /*!
 1312       * Executes an autoderef loop for the type `t`. At each step, invokes
 1313       * `should_stop` to decide whether to terminate the loop. Returns
 1314       * the final type and number of derefs that it performed.
 1315       *
 1316       * Note: this method does not modify the adjustments table. The caller is
 1317       * responsible for inserting an AutoAdjustment record into the `fcx`
 1318       * using one of the suitable methods.
 1319       */
 1320  
 1321      let mut t = base_ty;
 1322      for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
 1323          let resolved_t = structurally_resolved_type(fcx, sp, t);
 1324  
 1325          match should_stop(resolved_t, autoderefs) {
 1326              Some(x) => return (resolved_t, autoderefs, Some(x)),
 1327              None => {}
 1328          }
 1329  
 1330          // Otherwise, deref if type is derefable:
 1331          let mt = match ty::deref(resolved_t, false) {
 1332              Some(mt) => Some(mt),
 1333              None => {
 1334                  let method_call =
 1335                      expr_id.map(|id| MethodCall::autoderef(id, autoderefs as u32));
 1336                  try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
 1337              }
 1338          };
 1339          match mt {
 1340              Some(mt) => {
 1341                  t = mt.ty;
 1342                  if mt.mutbl == ast::MutImmutable {
 1343                      lvalue_pref = NoPreference;
 1344                  }
 1345              }
 1346              None => return (resolved_t, autoderefs, None)
 1347          }
 1348      }
 1349  
 1350      // We've reached the recursion limit, error gracefully.
 1351      fcx.tcx().sess.span_err(sp,
 1352          format!("reached the recursion limit while auto-dereferencing {}",
 1353                  base_ty.repr(fcx.tcx())));
 1354      (ty::mk_err(), 0, None)
 1355  }
 1356  
 1357  fn try_overloaded_deref(fcx: &FnCtxt,
 1358                          spanSpan,
 1359                          method_callOption<MethodCall>,
 1360                          base_exprOption<&ast::Expr>,
 1361                          base_tyty::t,
 1362                          lvalue_prefLvaluePreference)
 1363                          -> Option<ty::mt> {
 1364      // Try DerefMut first, if preferred.
 1365      let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
 1366          (PreferMutLvalue, Some(trait_did)) => {
 1367              method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
 1368                                      token::intern("deref_mut"), trait_did,
 1369                                      base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
 1370          }
 1371          _ => None
 1372      };
 1373  
 1374      // Otherwise, fall back to Deref.
 1375      let method = match (method, fcx.tcx().lang_items.deref_trait()) {
 1376          (None, Some(trait_did)) => {
 1377              method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
 1378                                      token::intern("deref"), trait_did,
 1379                                      base_ty, [], DontAutoderefReceiver, IgnoreStaticMethods)
 1380          }
 1381          (method, _) => method
 1382      };
 1383  
 1384      match method {
 1385          Some(method) => {
 1386              let ref_ty = ty::ty_fn_ret(method.ty);
 1387              match method_call {
 1388                  Some(method_call) => {
 1389                      fcx.inh.method_map.borrow_mut().insert(method_call, method);
 1390                  }
 1391                  None => {}
 1392              }
 1393              ty::deref(ref_ty, true)
 1394          }
 1395          None => None
 1396      }
 1397  }
 1398  
 1399  // AST fragment checking
 1400  pub fn check_lit(fcx: &FnCtxt, lit: &ast::Lit) -> ty::t {
 1401      let tcx = fcx.ccx.tcx;
 1402  
 1403      match lit.node {
 1404          ast::LitStr(..) => ty::mk_str_slice(tcx, ty::ReStatic, ast::MutImmutable),
 1405          ast::LitBinary(..) => {
 1406              ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
 1407          }
 1408          ast::LitChar(_) => ty::mk_char(),
 1409          ast::LitInt(_, t) => ty::mk_mach_int(t),
 1410          ast::LitUint(_, t) => ty::mk_mach_uint(t),
 1411          ast::LitIntUnsuffixed(_) => {
 1412              // An unsuffixed integer literal could have any integral type,
 1413              // so we create an integral type variable for it.
 1414              ty::mk_int_var(tcx, fcx.infcx().next_int_var_id())
 1415          }
 1416          ast::LitFloat(_, t) => ty::mk_mach_float(t),
 1417          ast::LitFloatUnsuffixed(_) => {
 1418              // An unsuffixed floating point literal could have any floating point
 1419              // type, so we create a floating point type variable for it.
 1420              ty::mk_float_var(tcx, fcx.infcx().next_float_var_id())
 1421          }
 1422          ast::LitNil => ty::mk_nil(),
 1423          ast::LitBool(_) => ty::mk_bool()
 1424      }
 1425  }
 1426  
 1427  pub fn valid_range_bounds(ccx: &CrateCtxt,
 1428                            from: &ast::Expr,
 1429                            to: &ast::Expr)
 1430                         -> Option<bool> {
 1431      match const_eval::compare_lit_exprs(ccx.tcx, from, to) {
 1432          Some(val) => Some(val <= 0),
 1433          None => None
 1434      }
 1435  }
 1436  
 1437  pub fn check_expr_has_type(
 1438      fcx: &FnCtxt, expr: &ast::Expr,
 1439      expectedty::t) {
 1440      check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
 1441          demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr));
 1442      });
 1443  }
 1444  
 1445  fn check_expr_coercable_to_type(fcx: &FnCtxt, expr: &ast::Expr, expectedty::t) {
 1446      check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
 1447          demand::coerce(fcx, expr.span, expected, expr)
 1448      });
 1449  }
 1450  
 1451  fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expectedty::t) {
 1452      check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || ())
 1453  }
 1454  
 1455  fn check_expr_with_opt_hint(fcx: &FnCtxt, expr: &ast::Expr,
 1456                              expectedOption<ty::t>)  {
 1457      check_expr_with_unifier(fcx, expr, expected, NoPreference, || ())
 1458  }
 1459  
 1460  fn check_expr_with_opt_hint_and_lvalue_pref(fcx: &FnCtxt,
 1461                                              expr: &ast::Expr,
 1462                                              expectedOption<ty::t>,
 1463                                              lvalue_prefLvaluePreference) {
 1464      check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
 1465  }
 1466  
 1467  fn check_expr(fcx: &FnCtxt, expr: &ast::Expr)  {
 1468      check_expr_with_unifier(fcx, expr, None, NoPreference, || ())
 1469  }
 1470  
 1471  fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
 1472                                 lvalue_prefLvaluePreference)  {
 1473      check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
 1474  }
 1475  
 1476  
 1477  // determine the `self` type, using fresh variables for all variables
 1478  // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
 1479  // would return ($0, $1) where $0 and $1 are freshly instantiated type
 1480  // variables.
 1481  pub fn impl_self_ty(vcx: &VtableContext,
 1482                      spanSpan, // (potential) receiver for this impl
 1483                      didast::DefId)
 1484                   -> ty_param_substs_and_ty {
 1485      let tcx = vcx.tcx();
 1486  
 1487      let ity = ty::lookup_item_type(tcx, did);
 1488      let (n_tps, rps, raw_ty) =
 1489          (ity.generics.type_param_defs().len(),
 1490           ity.generics.region_param_defs(),
 1491           ity.ty);
 1492  
 1493      let rps = vcx.infcx.region_vars_for_defs(span, rps);
 1494      let tps = vcx.infcx.next_ty_vars(n_tps);
 1495  
 1496      let substs = substs {
 1497          regions: ty::NonerasedRegions(rps),
 1498          self_ty: None,
 1499          tps: tps,
 1500      };
 1501      let substd_ty = ty::subst(tcx, &substs, raw_ty);
 1502  
 1503      ty_param_substs_and_ty { substs: substs, ty: substd_ty }
 1504  }
 1505  
 1506  // Only for fields! Returns <none> for methods>
 1507  // Indifferent to privacy flags
 1508  pub fn lookup_field_ty(tcx: &ty::ctxt,
 1509                         class_idast::DefId,
 1510                         items: &[ty::field_ty],
 1511                         fieldnameast::Name,
 1512                         substs: &ty::substs) -> Option<ty::t> {
 1513  
 1514      let o_field = items.iter().find(|f| f.name == fieldname);
 1515      o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
 1516  }
 1517  
 1518  // Controls whether the arguments are automatically referenced. This is useful
 1519  // for overloaded binary and unary operators.
 1520  pub enum DerefArgs {
 1521      DontDerefArgs,
 1522      DoDerefArgs
 1523  }
 1524  
 1525  // Given the provenance of a static method, returns the generics of the static
 1526  // method's container.
 1527  fn generics_of_static_method_container(type_context: &ty::ctxt,
 1528                                         provenanceast::MethodProvenance)
 1529                                         -> ty::Generics {
 1530      match provenance {
 1531          ast::FromTrait(trait_def_id) => {
 1532              ty::lookup_trait_def(type_context, trait_def_id).generics.clone()
 1533          }
 1534          ast::FromImpl(impl_def_id) => {
 1535              ty::lookup_item_type(type_context, impl_def_id).generics.clone()
 1536          }
 1537      }
 1538  }
 1539  
 1540  // Verifies that type parameters supplied in paths are in the right
 1541  // locations.
 1542  fn check_type_parameter_positions_in_path(function_context: &FnCtxt,
 1543                                            path: &ast::Path,
 1544                                            defast::Def) {
 1545      // We only care about checking the case in which the path has two or
 1546      // more segments.
 1547      if path.segments.len() < 2 {
 1548          return
 1549      }
 1550  
 1551      // Verify that no lifetimes or type parameters are present anywhere
 1552      // except the final two elements of the path.
 1553      for i in range(0, path.segments.len() - 2) {
 1554          for lifetime in path.segments.get(i).lifetimes.iter() {
 1555              function_context.tcx()
 1556                  .sess
 1557                  .span_err(lifetime.span,
 1558                            "lifetime parameters may not \
 1559                            appear here");
 1560              break;
 1561          }
 1562  
 1563          for typ in path.segments.get(i).types.iter() {
 1564              function_context.tcx()
 1565                              .sess
 1566                              .span_err(typ.span,
 1567                                        "type parameters may not appear here");
 1568              break;
 1569          }
 1570      }
 1571  
 1572      // If there are no parameters at all, there is nothing more to do; the
 1573      // rest of typechecking will (attempt to) infer everything.
 1574      if path.segments
 1575             .iter()
 1576             .all(|s| s.lifetimes.is_empty() && s.types.is_empty()) {
 1577          return
 1578      }
 1579  
 1580      match def {
 1581          // If this is a static method of a trait or implementation, then
 1582          // ensure that the segment of the path which names the trait or
 1583          // implementation (the penultimate segment) is annotated with the
 1584          // right number of type parameters.
 1585          ast::DefStaticMethod(_, provenance, _) => {
 1586              let generics =
 1587                  generics_of_static_method_container(function_context.ccx.tcx,
 1588                                                      provenance);
 1589              let name = match provenance {
 1590                  ast::FromTrait(_) => "trait",
 1591                  ast::FromImpl(_) => "impl",
 1592              };
 1593  
 1594              let trait_segment = &path.segments.get(path.segments.len() - 2);
 1595  
 1596              // Make sure lifetime parameterization agrees with the trait or
 1597              // implementation type.
 1598              let trait_region_parameter_count = generics.region_param_defs().len();
 1599              let supplied_region_parameter_count = trait_segment.lifetimes.len();
 1600              if trait_region_parameter_count != supplied_region_parameter_count
 1601                  && supplied_region_parameter_count != 0 {
 1602                  function_context.tcx()
 1603                      .sess
 1604                      .span_err(path.span,
 1605                                format!("expected {nexpected, plural, =1{# lifetime parameter} \
 1606                                                                   other{# lifetime parameters}}, \
 1607                                         found {nsupplied, plural, =1{# lifetime parameter} \
 1608                                                                other{# lifetime parameters}}",
 1609                                        nexpected = trait_region_parameter_count,
 1610                                        nsupplied = supplied_region_parameter_count));
 1611              }
 1612  
 1613              // Make sure the number of type parameters supplied on the trait
 1614              // or implementation segment equals the number of type parameters
 1615              // on the trait or implementation definition.
 1616              let formal_ty_param_count = generics.type_param_defs().len();
 1617              let required_ty_param_count = generics.type_param_defs().iter()
 1618                                                    .take_while(|x| x.default.is_none())
 1619                                                    .len();
 1620              let supplied_ty_param_count = trait_segment.types.len();
 1621              if supplied_ty_param_count < required_ty_param_count {
 1622                  let msg = if required_ty_param_count < generics.type_param_defs().len() {
 1623                      format!("the {trait_or_impl} referenced by this path needs at least \
 1624                               {nexpected, plural, =1{type parameter} \
 1625                                                other{type parameters}}, \
 1626                               but {nsupplied, plural, =1{type parameter} \
 1627                                                    other{type parameters}} were supplied",
 1628                              trait_or_impl = name,
 1629                              nexpected = required_ty_param_count,
 1630                              nsupplied = supplied_ty_param_count)
 1631                  } else {
 1632                      format!("the {trait_or_impl} referenced by this path needs \
 1633                               {nexpected, plural, =1{type parameter} \
 1634                                                other{type parameters}}, \
 1635                               but {nsupplied, plural, =1{type parameter} \
 1636                                                    other{type parameters}} were supplied",
 1637                              trait_or_impl = name,
 1638                              nexpected = required_ty_param_count,
 1639                              nsupplied = supplied_ty_param_count)
 1640                  };
 1641                  function_context.tcx().sess.span_err(path.span, msg)
 1642              } else if supplied_ty_param_count > formal_ty_param_count {
 1643                  let msg = if required_ty_param_count < generics.type_param_defs().len() {
 1644                      format!("the {trait_or_impl} referenced by this path needs at most \
 1645                               {nexpected, plural, =1{type parameter} \
 1646                                                other{type parameters}}, \
 1647                               but {nsupplied, plural, =1{type parameter} \
 1648                                                    other{type parameters}} were supplied",
 1649                              trait_or_impl = name,
 1650                              nexpected = formal_ty_param_count,
 1651                              nsupplied = supplied_ty_param_count)
 1652                  } else {
 1653                      format!("the {trait_or_impl} referenced by this path needs \
 1654                               {nexpected, plural, =1{type parameter} \
 1655                                                other{type parameters}}, \
 1656                               but {nsupplied, plural, =1{type parameter} \
 1657                                                    other{type parameters}} were supplied",
 1658                              trait_or_impl = name,
 1659                              nexpected = formal_ty_param_count,
 1660                              nsupplied = supplied_ty_param_count)
 1661                  };
 1662                  function_context.tcx().sess.span_err(path.span, msg)
 1663              }
 1664          }
 1665          _ => {
 1666              // Verify that no lifetimes or type parameters are present on
 1667              // the penultimate segment of the path.
 1668              let segment = &path.segments.get(path.segments.len() - 2);
 1669              for lifetime in segment.lifetimes.iter() {
 1670                  function_context.tcx()
 1671                      .sess
 1672                      .span_err(lifetime.span,
 1673                                "lifetime parameters may not
 1674                                appear here");
 1675                  break;
 1676              }
 1677              for typ in segment.types.iter() {
 1678                  function_context.tcx()
 1679                                  .sess
 1680                                  .span_err(typ.span,
 1681                                            "type parameters may not appear \
 1682                                             here");
 1683                  break;
 1684              }
 1685          }
 1686      }
 1687  }
 1688  
 1689  /// Invariant:
 1690  /// If an expression has any sub-expressions that result in a type error,
 1691  /// inspecting that expression's type with `ty::type_is_error` will return
 1692  /// true. Likewise, if an expression is known to diverge, inspecting its
 1693  /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
 1694  /// strict, _|_ can appear in the type of an expression that does not,
 1695  /// itself, diverge: for example, fn() -> _|_.)
 1696  /// Note that inspecting a type's structure *directly* may expose the fact
 1697  /// that there are actually multiple representations for both `ty_err` and
 1698  /// `ty_bot`, so avoid that when err and bot need to be handled differently.
 1699  fn check_expr_with_unifier(fcx: &FnCtxt,
 1700                             expr: &ast::Expr,
 1701                             expectedOption<ty::t>,
 1702                             lvalue_prefLvaluePreference,
 1703                             unifier: ||) {
 1704      debug!(">> typechecking");
 1705  
 1706      fn check_method_argument_types(
 1707          fcx: &FnCtxt,
 1708          spSpan,
 1709          method_fn_tyty::t,
 1710          callee_expr: &ast::Expr,
 1711          args: &[@ast::Expr],
 1712          deref_argsDerefArgs) -> ty::t {
 1713          // HACK(eddyb) ignore provided self (it has special typeck rules).
 1714          let args = args.slice_from(1);
 1715          if ty::type_is_error(method_fn_ty) {
 1716              let err_inputs = err_args(args.len());
 1717              check_argument_types(fcx, sp, err_inputs.as_slice(), callee_expr,
 1718                                   args, deref_args, false);
 1719              method_fn_ty
 1720          } else {
 1721              match ty::get(method_fn_ty).sty {
 1722                  ty::ty_bare_fn(ref fty) => {
 1723                      // HACK(eddyb) ignore self in the definition (see above).
 1724                      check_argument_types(fcx, sp, fty.sig.inputs.slice_from(1),
 1725                                           callee_expr, args, deref_args,
 1726                                           fty.sig.variadic);
 1727                      fty.sig.output
 1728                  }
 1729                  _ => {
 1730                      fcx.tcx().sess.span_bug(
 1731                          callee_expr.span,
 1732                          format!("method without bare fn type"));
 1733                  }
 1734              }
 1735          }
 1736      }
 1737  
 1738      fn check_argument_types(fcx: &FnCtxt,
 1739                              spSpan,
 1740                              fn_inputs: &[ty::t],
 1741                              callee_expr: &ast::Expr,
 1742                              args: &[@ast::Expr],
 1743                              deref_argsDerefArgs,
 1744                              variadic: bool) {
 1745          /*!
 1746           *
 1747           * Generic function that factors out common logic from
 1748           * function calls, method calls and overloaded operators.
 1749           */
 1750  
 1751          let tcx = fcx.ccx.tcx;
 1752  
 1753          // Grab the argument types, supplying fresh type variables
 1754          // if the wrong number of arguments were supplied
 1755          let supplied_arg_count = args.len();
 1756          let expected_arg_count = fn_inputs.len();
 1757          let formal_tys = if expected_arg_count == supplied_arg_count {
 1758              fn_inputs.iter().map(|a| *a).collect()
 1759          } else if variadic {
 1760              if supplied_arg_count >= expected_arg_count {
 1761                  fn_inputs.iter().map(|a| *a).collect()
 1762              } else {
 1763                  let msg = format!(
 1764                      "this function takes at least {nexpected, plural, =1{# parameter} \
 1765                                                                     other{# parameters}} \
 1766                       but {nsupplied, plural, =1{# parameter was} \
 1767                                            other{# parameters were}} supplied",
 1768                       nexpected = expected_arg_count,
 1769                       nsupplied = supplied_arg_count);
 1770  
 1771                  tcx.sess.span_err(sp, msg);
 1772  
 1773                  err_args(supplied_arg_count)
 1774              }
 1775          } else {
 1776              let msg = format!(
 1777                  "this function takes {nexpected, plural, =1{# parameter} \
 1778                                                        other{# parameters}} \
 1779                   but {nsupplied, plural, =1{# parameter was} \
 1780                                        other{# parameters were}} supplied",
 1781                   nexpected = expected_arg_count,
 1782                   nsupplied = supplied_arg_count);
 1783  
 1784              tcx.sess.span_err(sp, msg);
 1785  
 1786              err_args(supplied_arg_count)
 1787          };
 1788  
 1789          debug!("check_argument_types: formal_tys={:?}",
 1790                 formal_tys.iter().map(|t| fcx.infcx().ty_to_str(*t)).collect::<Vec<~str>>());
 1791  
 1792          // Check the arguments.
 1793          // We do this in a pretty awful way: first we typecheck any arguments
 1794          // that are not anonymous functions, then we typecheck the anonymous
 1795          // functions. This is so that we have more information about the types
 1796          // of arguments when we typecheck the functions. This isn't really the
 1797          // right way to do this.
 1798          let xs = [false, true];
 1799          for check_blocks in xs.iter() {
 1800              let check_blocks = *check_blocks;
 1801              debug!("check_blocks={}", check_blocks);
 1802  
 1803              // More awful hacks: before we check the blocks, try to do
 1804              // an "opportunistic" vtable resolution of any trait
 1805              // bounds on the call.
 1806              if check_blocks {
 1807                  vtable::early_resolve_expr(callee_expr, fcx, true);
 1808              }
 1809  
 1810              // For variadic functions, we don't have a declared type for all of
 1811              // the arguments hence we only do our usual type checking with
 1812              // the arguments who's types we do know.
 1813              let t = if variadic {
 1814                  expected_arg_count
 1815              } else {
 1816                  supplied_arg_count
 1817              };
 1818              for (i, arg) in args.iter().take(t).enumerate() {
 1819                  let is_block = match arg.node {
 1820                      ast::ExprFnBlock(..) |
 1821                      ast::ExprProc(..) => true,
 1822                      _ => false
 1823                  };
 1824  
 1825                  if is_block == check_blocks {
 1826                      debug!("checking the argument");
 1827                      let mut formal_ty = *formal_tys.get(i);
 1828  
 1829                      match deref_args {
 1830                          DoDerefArgs => {
 1831                              match ty::get(formal_ty).sty {
 1832                                  ty::ty_rptr(_, mt) => formal_ty = mt.ty,
 1833                                  ty::ty_err => (),
 1834                                  _ => {
 1835                                      // So we hit this case when one implements the
 1836                                      // operator traits but leaves an argument as
 1837                                      // just T instead of &T. We'll catch it in the
 1838                                      // mismatch impl/trait method phase no need to
 1839                                      // ICE here.
 1840                                      // See: #11450
 1841                                      formal_ty = ty::mk_err();
 1842                                  }
 1843                              }
 1844                          }
 1845                          DontDerefArgs => {}
 1846                      }
 1847  
 1848                      check_expr_coercable_to_type(fcx, *arg, formal_ty);
 1849  
 1850                  }
 1851              }
 1852          }
 1853  
 1854          // We also need to make sure we at least write the ty of the other
 1855          // arguments which we skipped above.
 1856          if variadic {
 1857              for arg in args.iter().skip(expected_arg_count) {
 1858                  check_expr(fcx, *arg);
 1859  
 1860                  // There are a few types which get autopromoted when passed via varargs
 1861                  // in C but we just error out instead and require explicit casts.
 1862                  let arg_ty = structurally_resolved_type(fcx, arg.span, fcx.expr_ty(*arg));
 1863                  match ty::get(arg_ty).sty {
 1864                      ty::ty_float(ast::TyF32) => {
 1865                          fcx.type_error_message(arg.span,
 1866                                  |t| format!("can't pass an {} to variadic function, \
 1867                                               cast to c_double", t), arg_ty, None);
 1868                      }
 1869                      ty::ty_int(ast::TyI8) | ty::ty_int(ast::TyI16) | ty::ty_bool => {
 1870                          fcx.type_error_message(arg.span,
 1871                                  |t| format!("can't pass {} to variadic function, cast to c_int",
 1872                                              t), arg_ty, None);
 1873                      }
 1874                      ty::ty_uint(ast::TyU8) | ty::ty_uint(ast::TyU16) => {
 1875                          fcx.type_error_message(arg.span,
 1876                                  |t| format!("can't pass {} to variadic function, cast to c_uint",
 1877                                              t), arg_ty, None);
 1878                      }
 1879                      _ => {}
 1880                  }
 1881              }
 1882          }
 1883      }
 1884  
 1885      fn err_args(lenuint) -> Vec<ty::t> {
 1886          Vec::from_fn(len, |_| ty::mk_err())
 1887      }
 1888  
 1889      fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, outputty::t) {
 1890          fcx.write_ty(call_expr.id, output);
 1891      }
 1892  
 1893      // A generic function for doing all of the checking for call expressions
 1894      fn check_call(fcx&FnCtxt,
 1895                    call_expr&ast::Expr,
 1896                    f&ast::Expr,
 1897                    args: &[@ast::Expr]) {
 1898          // Index expressions need to be handled separately, to inform them
 1899          // that they appear in call position.
 1900          check_expr(fcx, f);
 1901  
 1902          // Store the type of `f` as the type of the callee
 1903          let fn_ty = fcx.expr_ty(f);
 1904  
 1905          // Extract the function signature from `in_fty`.
 1906          let fn_sty = structure_of(fcx, f.span, fn_ty);
 1907  
 1908          // This is the "default" function signature, used in case of error.
 1909          // In that case, we check each argument against "error" in order to
 1910          // set up all the node type bindings.
 1911          let error_fn_sig = FnSig {
 1912              binder_id: ast::CRATE_NODE_ID,
 1913              inputs: err_args(args.len()),
 1914              output: ty::mk_err(),
 1915              variadic: false
 1916          };
 1917  
 1918          let fn_sig = match *fn_sty {
 1919              ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, ..}) |
 1920              ty::ty_closure(box ty::ClosureTy {sig: ref sig, ..}) => sig,
 1921              _ => {
 1922                  fcx.type_error_message(call_expr.span, |actual| {
 1923                      format!("expected function but \
 1924                            found `{}`", actual) }, fn_ty, None);
 1925                  &error_fn_sig
 1926              }
 1927          };
 1928  
 1929          // Replace any bound regions that appear in the function
 1930          // signature with region variables
 1931          let (_, fn_sig) = replace_late_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
 1932              fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
 1933          });
 1934  
 1935          // Call the generic checker.
 1936          check_argument_types(fcx, call_expr.span, fn_sig.inputs.as_slice(), f,
 1937                               args, DontDerefArgs, fn_sig.variadic);
 1938  
 1939          write_call(fcx, call_expr, fn_sig.output);
 1940      }
 1941  
 1942      // Checks a method call.
 1943      fn check_method_call(fcx&FnCtxt,
 1944                           expr&ast::Expr,
 1945                           method_nameast::SpannedIdent,
 1946                           args&[@ast::Expr],
 1947                           tps&[ast::P<ast::Ty>]) {
 1948          let rcvr = args[0];
 1949          // We can't know if we need &mut self before we look up the method,
 1950          // so treat the receiver as mutable just in case - only explicit
 1951          // overloaded dereferences care about the distinction.
 1952          check_expr_with_lvalue_pref(fcx, rcvr, PreferMutLvalue);
 1953  
 1954          // no need to check for bot/err -- callee does that
 1955          let expr_t = structurally_resolved_type(fcx,
 1956                                                  expr.span,
 1957                                                  fcx.expr_ty(rcvr));
 1958  
 1959          let tps = tps.iter().map(|&ast_ty| fcx.to_ty(ast_ty)).collect::<Vec<_>>();
 1960          let fn_ty = match method::lookup(fcx, expr, rcvr,
 1961                                           method_name.node.name,
 1962                                           expr_t, tps.as_slice(),
 1963                                           DontDerefArgs,
 1964                                           CheckTraitsAndInherentMethods,
 1965                                           AutoderefReceiver, IgnoreStaticMethods) {
 1966              Some(method) => {
 1967                  let method_ty = method.ty;
 1968                  let method_call = MethodCall::expr(expr.id);
 1969                  fcx.inh.method_map.borrow_mut().insert(method_call, method);
 1970                  method_ty
 1971              }
 1972              None => {
 1973                  debug!("(checking method call) failing expr is {}", expr.id);
 1974  
 1975                  fcx.type_error_message(method_name.span,
 1976                    |actual| {
 1977                        format!("type `{}` does not implement any method in scope named `{}`",
 1978                                actual, token::get_ident(method_name.node))
 1979                    },
 1980                    expr_t,
 1981                    None);
 1982  
 1983                  // Add error type for the result
 1984                  fcx.write_error(expr.id);
 1985  
 1986                  // Check for potential static matches (missing self parameters)
 1987                  method::lookup(fcx, expr, rcvr,
 1988                                      method_name.node.name,
 1989                                      expr_t, tps.as_slice(),
 1990                                      DontDerefArgs,
 1991                                      CheckTraitsAndInherentMethods,
 1992                                      DontAutoderefReceiver, ReportStaticMethods);
 1993  
 1994                  ty::mk_err()
 1995              }
 1996          };
 1997  
 1998          // Call the generic checker.
 1999          let ret_ty = check_method_argument_types(fcx, method_name.span,
 2000                                                   fn_ty, expr, args,
 2001                                                   DontDerefArgs);
 2002  
 2003          write_call(fcx, expr, ret_ty);
 2004      }
 2005  
 2006      // A generic function for checking the then and else in an if
 2007      // or if-check
 2008      fn check_then_else(fcx: &FnCtxt,
 2009                         cond_expr: &ast::Expr,
 2010                         then_blk: &ast::Block,
 2011                         opt_else_exprOption<@ast::Expr>,
 2012                         idast::NodeId,
 2013                         spSpan,
 2014                         expectedOption<ty::t>) {
 2015          check_expr_has_type(fcx, cond_expr, ty::mk_bool());
 2016  
 2017          let branches_ty = match opt_else_expr {
 2018              Some(else_expr) => {
 2019                  check_block_with_expected(fcx, then_blk, expected);
 2020                  let then_ty = fcx.node_ty(then_blk.id);
 2021                  check_expr_with_opt_hint(fcx, else_expr, expected);
 2022                  let else_ty = fcx.expr_ty(else_expr);
 2023                  infer::common_supertype(fcx.infcx(),
 2024                                          infer::IfExpression(sp),
 2025                                          true,
 2026                                          then_ty,
 2027                                          else_ty)
 2028              }
 2029              None => {
 2030                  check_block_no_value(fcx, then_blk);
 2031                  ty::mk_nil()
 2032              }
 2033          };
 2034  
 2035          let cond_ty = fcx.expr_ty(cond_expr);
 2036          let if_ty = if ty::type_is_error(cond_ty) {
 2037              ty::mk_err()
 2038          } else if ty::type_is_bot(cond_ty) {
 2039              ty::mk_bot()
 2040          } else {
 2041              branches_ty
 2042          };
 2043  
 2044          fcx.write_ty(id, if_ty);
 2045      }
 2046  
 2047      fn lookup_op_method(fcx: &FnCtxt,
 2048                          op_ex: &ast::Expr,
 2049                          self_tty::t,
 2050                          opnameast::Name,
 2051                          trait_didOption<ast::DefId>,
 2052                          args: &[@ast::Expr],
 2053                          autoderef_receiverAutoderefReceiverFlag,
 2054                          unbound_method: ||) -> ty::t {
 2055          let method = match trait_did {
 2056              Some(trait_did) => {
 2057                  method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
 2058                                          trait_did, self_t, [], autoderef_receiver,
 2059                                          IgnoreStaticMethods)
 2060              }
 2061              None => None
 2062          };
 2063          match method {
 2064              Some(method) => {
 2065                  let method_ty = method.ty;
 2066                  // HACK(eddyb) Fully qualified path to work around a resolve bug.
 2067                  let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
 2068                  fcx.inh.method_map.borrow_mut().insert(method_call, method);
 2069                  check_method_argument_types(fcx, op_ex.span,
 2070                                              method_ty, op_ex,
 2071                                              args, DoDerefArgs)
 2072              }
 2073              None => {
 2074                  unbound_method();
 2075                  // Check the args anyway
 2076                  // so we get all the error messages
 2077                  let expected_ty = ty::mk_err();
 2078                  check_method_argument_types(fcx, op_ex.span,
 2079                                              expected_ty, op_ex,
 2080                                              args, DoDerefArgs);
 2081                  ty::mk_err()
 2082              }
 2083          }
 2084      }
 2085  
 2086      // could be either an expr_binop or an expr_assign_binop
 2087      fn check_binop(fcx&FnCtxt,
 2088                     expr&ast::Expr,
 2089                     opast::BinOp,
 2090                     lhs@ast::Expr,
 2091                     rhs@ast::Expr,
 2092                     is_binop_assignmentIsBinopAssignment) {
 2093          let tcx = fcx.ccx.tcx;
 2094  
 2095          let lvalue_pref = match is_binop_assignment {
 2096              BinopAssignment => PreferMutLvalue,
 2097              SimpleBinop => NoPreference
 2098          };
 2099          check_expr_with_lvalue_pref(fcx, lhs, lvalue_pref);
 2100  
 2101          // Callee does bot / err checking
 2102          let lhs_t = structurally_resolved_type(fcx, lhs.span,
 2103                                                 fcx.expr_ty(lhs));
 2104  
 2105          if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
 2106              // Shift is a special case: rhs can be any integral type
 2107              check_expr(fcx, rhs);
 2108              let rhs_t = fcx.expr_ty(rhs);
 2109              require_integral(fcx, rhs.span, rhs_t);
 2110              fcx.write_ty(expr.id, lhs_t);
 2111              return;
 2112          }
 2113  
 2114          if ty::is_binopable(tcx, lhs_t, op) {
 2115              let tvar = fcx.infcx().next_ty_var();
 2116              demand::suptype(fcx, expr.span, tvar, lhs_t);
 2117              check_expr_has_type(fcx, rhs, tvar);
 2118  
 2119              let result_t = match op {
 2120                  ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
 2121                  ast::BiGt => {
 2122                      if ty::type_is_simd(tcx, lhs_t) {
 2123                          if ty::type_is_fp(ty::simd_type(tcx, lhs_t)) {
 2124                              fcx.type_error_message(expr.span,
 2125                                  |actual| {
 2126                                      format!("binary comparison operation `{}` not supported \
 2127                                              for floating point SIMD vector `{}`",
 2128                                              ast_util::binop_to_str(op), actual)
 2129                                  },
 2130                                  lhs_t,
 2131                                  None
 2132                              );
 2133                              ty::mk_err()
 2134                          } else {
 2135                              lhs_t
 2136                          }
 2137                      } else {
 2138                          ty::mk_bool()
 2139                      }
 2140                  },
 2141                  _ => lhs_t,
 2142              };
 2143  
 2144              fcx.write_ty(expr.id, result_t);
 2145              return;
 2146          }
 2147  
 2148          if op == ast::BiOr || op == ast::BiAnd {
 2149              // This is an error; one of the operands must have the wrong
 2150              // type
 2151              fcx.write_error(expr.id);
 2152              fcx.write_error(rhs.id);
 2153              fcx.type_error_message(expr.span, |actual| {
 2154                  format!("binary operation `{}` cannot be applied \
 2155                        to type `{}`",
 2156                       ast_util::binop_to_str(op), actual)},
 2157                                     lhs_t, None)
 2158  
 2159          }
 2160  
 2161          // Check for overloaded operators if not an assignment.
 2162          let result_t = if is_binop_assignment == SimpleBinop {
 2163              check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
 2164          } else {
 2165              fcx.type_error_message(expr.span,
 2166                                     |actual| {
 2167                                          format!("binary assignment operation \
 2168                                                  `{}=` cannot be applied to type `{}`",
 2169                                                  ast_util::binop_to_str(op),
 2170                                                  actual)
 2171                                     },
 2172                                     lhs_t,
 2173                                     None);
 2174              check_expr(fcx, rhs);
 2175              ty::mk_err()
 2176          };
 2177  
 2178          fcx.write_ty(expr.id, result_t);
 2179          if ty::type_is_error(result_t) {
 2180              fcx.write_ty(rhs.id, result_t);
 2181          }
 2182      }
 2183  
 2184      fn check_user_binop(fcx&FnCtxt,
 2185                          ex&ast::Expr,
 2186                          lhs_expr@ast::Expr,
 2187                          lhs_resolved_tty::t,
 2188                          opast::BinOp,
 2189                          rhs@ast::Expr) -> ty::t {
 2190          let tcx = fcx.ccx.tcx;
 2191          let lang = &tcx.lang_items;
 2192          let (name, trait_did) = match op {
 2193              ast::BiAdd => ("add", lang.add_trait()),
 2194              ast::BiSub => ("sub", lang.sub_trait()),
 2195              ast::BiMul => ("mul", lang.mul_trait()),
 2196              ast::BiDiv => ("div", lang.div_trait()),
 2197              ast::BiRem => ("rem", lang.rem_trait()),
 2198              ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
 2199              ast::BiBitAnd => ("bitand", lang.bitand_trait()),
 2200              ast::BiBitOr => ("bitor", lang.bitor_trait()),
 2201              ast::BiShl => ("shl", lang.shl_trait()),
 2202              ast::BiShr => ("shr", lang.shr_trait()),
 2203              ast::BiLt => ("lt", lang.ord_trait()),
 2204              ast::BiLe => ("le", lang.ord_trait()),
 2205              ast::BiGe => ("ge", lang.ord_trait()),
 2206              ast::BiGt => ("gt", lang.ord_trait()),
 2207              ast::BiEq => ("eq", lang.eq_trait()),
 2208              ast::BiNe => ("ne", lang.eq_trait()),
 2209              ast::BiAnd | ast::BiOr => {
 2210                  check_expr(fcx, rhs);
 2211                  return ty::mk_err();
 2212              }
 2213          };
 2214          lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
 2215                           trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
 2216              fcx.type_error_message(ex.span, |actual| {
 2217                  format!("binary operation `{}` cannot be applied to type `{}`",
 2218                      ast_util::binop_to_str(op), actual)
 2219              }, lhs_resolved_t, None)
 2220          })
 2221      }
 2222  
 2223      fn check_user_unop(fcx&FnCtxt,
 2224                         op_str&str,
 2225                         mname&str,
 2226                         trait_didOption<ast::DefId>,
 2227                         ex&ast::Expr,
 2228                         rhs_expr@ast::Expr,
 2229                         rhs_tty::t) -> ty::t {
 2230         lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
 2231                          trait_did, [rhs_expr], DontAutoderefReceiver, || {
 2232              fcx.type_error_message(ex.span, |actual| {
 2233                  format!("cannot apply unary operator `{}` to type `{}`", op_str, actual)
 2234              }, rhs_t, None);
 2235          })
 2236      }
 2237  
 2238      // Resolves `expected` by a single level if it is a variable and passes it
 2239      // through the `unpack` function.  It there is no expected type or
 2240      // resolution is not possible (e.g., no constraints yet present), just
 2241      // returns `none`.
 2242      fn unpack_expected<O>(
 2243                         fcx: &FnCtxt,
 2244                         expectedOption<ty::t>,
 2245                         unpack: |&ty::sty-> Option<O>)
 2246                         -> Option<O> {
 2247          match expected {
 2248              Some(t) => {
 2249                  match resolve_type(fcx.infcx(), t, force_tvar) {
 2250                      Ok(t) => unpack(&ty::get(t).sty),
 2251                      _ => None
 2252                  }
 2253              }
 2254              _ => None
 2255          }
 2256      }
 2257  
 2258      fn check_expr_fn(fcx: &FnCtxt,
 2259                       expr: &ast::Expr,
 2260                       storety::TraitStore,
 2261                       decl: &ast::FnDecl,
 2262                       bodyast::P<ast::Block>,
 2263                       fn_kindFnKind,
 2264                       expectedOption<ty::t>) {
 2265          let tcx = fcx.ccx.tcx;
 2266  
 2267          // Find the expected input/output types (if any). Substitute
 2268          // fresh bound regions for any bound regions we find in the
 2269          // expected types so as to avoid capture.
 2270          let expected_sty = unpack_expected(fcx,
 2271                                             expected,
 2272                                             |x| Some((*x).clone()));
 2273          let (expected_sig,
 2274               expected_onceness,
 2275               expected_bounds) = {
 2276              match expected_sty {
 2277                  Some(ty::ty_closure(ref cenv)) => {
 2278                      let (_, sig) =
 2279                          replace_late_bound_regions_in_fn_sig(
 2280                              tcx, &cenv.sig,
 2281                              |_| fcx.inh.infcx.fresh_bound_region(expr.id));
 2282                      let onceness = match (&store, &cenv.store) {
 2283                          // As the closure type and onceness go, only three
 2284                          // combinations are legit:
 2285                          //      once closure
 2286                          //      many closure
 2287                          //      once proc
 2288                          // If the actual and expected closure type disagree with
 2289                          // each other, set expected onceness to be always Once or
 2290                          // Many according to the actual type. Otherwise, it will
 2291                          // yield either an illegal "many proc" or a less known
 2292                          // "once closure" in the error message.
 2293                          (&ty::UniqTraitStore, &ty::UniqTraitStore) |
 2294                          (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
 2295                              cenv.onceness,
 2296                          (&ty::UniqTraitStore, _) => ast::Once,
 2297                          (&ty::RegionTraitStore(..), _) => ast::Many,
 2298                      };
 2299                      (Some(sig), onceness, cenv.bounds)
 2300                  }
 2301                  _ => {
 2302                      // Not an error! Means we're inferring the closure type
 2303                      let mut bounds = ty::EmptyBuiltinBounds();
 2304                      let onceness = match expr.node {
 2305                          ast::ExprProc(..) => {
 2306                              bounds.add(ty::BoundSend);
 2307                              ast::Once
 2308                          }
 2309                          _ => ast::Many
 2310                      };
 2311                      (None, onceness, bounds)
 2312                  }
 2313              }
 2314          };
 2315  
 2316          // construct the function type
 2317          let fn_ty = astconv::ty_of_closure(fcx,
 2318                                             expr.id,
 2319                                             ast::NormalFn,
 2320                                             expected_onceness,
 2321                                             expected_bounds,
 2322                                             store,
 2323                                             decl,
 2324                                             expected_sig);
 2325          let fty_sig = fn_ty.sig.clone();
 2326          let fty = ty::mk_closure(tcx, fn_ty);
 2327          debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
 2328  
 2329          fcx.write_ty(expr.id, fty);
 2330  
 2331          // If the closure is a stack closure and hasn't had some non-standard
 2332          // style inferred for it, then check it under its parent's style.
 2333          // Otherwise, use its own
 2334          let (inherited_style, id) = match store {
 2335              ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
 2336                                           fcx.ps.borrow().def),
 2337              ty::UniqTraitStore => (ast::NormalFn, expr.id)
 2338          };
 2339  
 2340          check_fn(fcx.ccx, inherited_style, &fty_sig,
 2341                   decl, id, body, fn_kind, fcx.inh);
 2342      }
 2343  
 2344  
 2345      // Check field access expressions
 2346      fn check_field(fcx&FnCtxt,
 2347                     expr&ast::Expr,
 2348                     lvalue_prefLvaluePreference,
 2349                     base&ast::Expr,
 2350                     fieldast::Name,
 2351                     tys&[ast::P<ast::Ty>]) {
 2352          let tcx = fcx.ccx.tcx;
 2353          check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
 2354          let expr_t = structurally_resolved_type(fcx, expr.span,
 2355                                                  fcx.expr_ty(base));
 2356          // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
 2357          let (_, autoderefs, field_ty) =
 2358              autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
 2359                  match ty::get(base_t).sty {
 2360                      ty::ty_struct(base_id, ref substs) => {
 2361                          debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
 2362                          let fields = ty::lookup_struct_fields(tcx, base_id);
 2363                          lookup_field_ty(tcx, base_id, fields.as_slice(), field, &(*substs))
 2364                      }
 2365                      _ => None
 2366                  }
 2367              });
 2368          match field_ty {
 2369              Some(field_ty) => {
 2370                  fcx.write_ty(expr.id, field_ty);
 2371                  fcx.write_autoderef_adjustment(base.id, autoderefs);
 2372                  return;
 2373              }
 2374              None => {}
 2375          }
 2376  
 2377          let tpsVec<ty::t> = tys.iter().map(|&ty| fcx.to_ty(ty)).collect();
 2378          match method::lookup(fcx,
 2379                               expr,
 2380                               base,
 2381                               field,
 2382                               expr_t,
 2383                               tps.as_slice(),
 2384                               DontDerefArgs,
 2385                               CheckTraitsAndInherentMethods,
 2386                               AutoderefReceiver,
 2387                               IgnoreStaticMethods) {
 2388              Some(_) => {
 2389                  fcx.type_error_message(
 2390                      expr.span,
 2391                      |actual| {
 2392                          format!("attempted to take value of method `{}` on type `{}`",
 2393                                  token::get_name(field), actual)
 2394                      },
 2395                      expr_t, None);
 2396  
 2397                  tcx.sess.span_note(expr.span,
 2398                      "maybe a missing `()` to call it? If not, try an anonymous function.");
 2399              }
 2400  
 2401              None => {
 2402                  fcx.type_error_message(
 2403                      expr.span,
 2404                      |actual| {
 2405                          format!("attempted access of field `{}` on type `{}`, \
 2406                                   but no field with that name was found",
 2407                                  token::get_name(field), actual)
 2408                      },
 2409                      expr_t, None);
 2410              }
 2411          }
 2412  
 2413          fcx.write_error(expr.id);
 2414      }
 2415  
 2416      fn check_struct_or_variant_fields(fcx&FnCtxt,
 2417                                        struct_tyty::t,
 2418                                        spanSpan,
 2419                                        class_idast::DefId,
 2420                                        node_idast::NodeId,
 2421                                        substitutionsty::substs,
 2422                                        field_types&[ty::field_ty],
 2423                                        ast_fields&[ast::Field],
 2424                                        check_completenessbool)  {
 2425          let tcx = fcx.ccx.tcx;
 2426  
 2427          let mut class_field_map = HashMap::new();
 2428          let mut fields_found = 0;
 2429          for field in field_types.iter() {
 2430              class_field_map.insert(field.name, (field.id, false));
 2431          }
 2432  
 2433          let mut error_happened = false;
 2434  
 2435          // Typecheck each field.
 2436          for field in ast_fields.iter() {
 2437              let mut expected_field_type = ty::mk_err();
 2438  
 2439              let pair = class_field_map.find(&field.ident.node.name).map(|x| *x);
 2440              match pair {
 2441                  None => {
 2442                      fcx.type_error_message(
 2443                        field.ident.span,
 2444                        |actual| {
 2445                            format!("structure `{}` has no field named `{}`",
 2446                                    actual, token::get_ident(field.ident.node))
 2447                      }, struct_ty, None);
 2448                      error_happened = true;
 2449                  }
 2450                  Some((_, true)) => {
 2451                      tcx.sess.span_err(
 2452                          field.ident.span,
 2453                          format!("field `{}` specified more than once",
 2454                              token::get_ident(field.ident.node)));
 2455                      error_happened = true;
 2456                  }
 2457                  Some((field_id, false)) => {
 2458                      expected_field_type =
 2459                          ty::lookup_field_type(
 2460                              tcx, class_id, field_id, &substitutions);
 2461                      class_field_map.insert(
 2462                          field.ident.node.name, (field_id, true));
 2463                      fields_found += 1;
 2464                  }
 2465              }
 2466              // Make sure to give a type to the field even if there's
 2467              // an error, so we can continue typechecking
 2468              check_expr_coercable_to_type(
 2469                      fcx,
 2470                      field.expr,
 2471                      expected_field_type);
 2472          }
 2473  
 2474          if error_happened {
 2475              fcx.write_error(node_id);
 2476          }
 2477  
 2478          if check_completeness && !error_happened {
 2479              // Make sure the programmer specified all the fields.
 2480              assert!(fields_found <= field_types.len());
 2481              if fields_found < field_types.len() {
 2482                  let mut missing_fields = Vec::new();
 2483                  for class_field in field_types.iter() {
 2484                      let name = class_field.name;
 2485                      let (_, seen) = *class_field_map.get(&name);
 2486                      if !seen {
 2487                          missing_fields.push("`".to_owned() + token::get_name(name).get() + "`");
 2488                      }
 2489                  }
 2490  
 2491                  tcx.sess.span_err(span,
 2492                      format!("missing {nfields, plural, =1{field} other{fields}}{fields}",
 2493                              nfields = missing_fields.len(),
 2494                              fields = missing_fields.connect(", ")));
 2495               }
 2496          }
 2497  
 2498          if !error_happened {
 2499              fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
 2500                                  class_id, substitutions));
 2501          }
 2502      }
 2503  
 2504      fn check_struct_constructor(fcx: &FnCtxt,
 2505                                  idast::NodeId,
 2506                                  spancodemap::Span,
 2507                                  class_idast::DefId,
 2508                                  fields: &[ast::Field],
 2509                                  base_exprOption<@ast::Expr>) {
 2510          let tcx = fcx.ccx.tcx;
 2511  
 2512          // Look up the number of type parameters and the raw type, and
 2513          // determine whether the class is region-parameterized.
 2514          let item_type = ty::lookup_item_type(tcx, class_id);
 2515          let type_parameter_count = item_type.generics.type_param_defs().len();
 2516          let region_param_defs = item_type.generics.region_param_defs();
 2517          let raw_type = item_type.ty;
 2518  
 2519          // Generate the struct type.
 2520          let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs);
 2521          let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
 2522          let substitutions = substs {
 2523              regions: ty::NonerasedRegions(regions),
 2524              self_ty: None,
 2525              tps: type_parameters
 2526          };
 2527  
 2528          let mut struct_type = ty::subst(tcx, &substitutions, raw_type);
 2529  
 2530          // Look up and check the fields.
 2531          let class_fields = ty::lookup_struct_fields(tcx, class_id);
 2532          check_struct_or_variant_fields(fcx,
 2533                                         struct_type,
 2534                                         span,
 2535                                         class_id,
 2536                                         id,
 2537                                         substitutions,
 2538                                         class_fields.as_slice(),
 2539                                         fields,
 2540                                         base_expr.is_none());
 2541          if ty::type_is_error(fcx.node_ty(id)) {
 2542              struct_type = ty::mk_err();
 2543          }
 2544  
 2545          // Check the base expression if necessary.
 2546          match base_expr {
 2547              None => {}
 2548              Some(base_expr) => {
 2549                  check_expr_has_type(fcx, base_expr, struct_type);
 2550                  if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
 2551                      struct_type = ty::mk_bot();
 2552                  }
 2553              }
 2554          }
 2555  
 2556          // Write in the resulting type.
 2557          fcx.write_ty(id, struct_type);
 2558      }
 2559  
 2560      fn check_struct_enum_variant(fcx&FnCtxt,
 2561                                   idast::NodeId,
 2562                                   spancodemap::Span,
 2563                                   enum_idast::DefId,
 2564                                   variant_idast::DefId,
 2565                                   fields&[ast::Field]) {
 2566          let tcx = fcx.ccx.tcx;
 2567  
 2568          // Look up the number of type parameters and the raw type, and
 2569          // determine whether the enum is region-parameterized.
 2570          let item_type = ty::lookup_item_type(tcx, enum_id);
 2571          let type_parameter_count = item_type.generics.type_param_defs().len();
 2572          let region_param_defs = item_type.generics.region_param_defs();
 2573          let raw_type = item_type.ty;
 2574  
 2575          // Generate the enum type.
 2576          let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs);
 2577          let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
 2578          let substitutions = substs {
 2579              regions: ty::NonerasedRegions(regions),
 2580              self_ty: None,
 2581              tps: type_parameters
 2582          };
 2583  
 2584          let enum_type = ty::subst(tcx, &substitutions, raw_type);
 2585  
 2586          // Look up and check the enum variant fields.
 2587          let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
 2588          check_struct_or_variant_fields(fcx,
 2589                                         enum_type,
 2590                                         span,
 2591                                         variant_id,
 2592                                         id,
 2593                                         substitutions,
 2594                                         variant_fields.as_slice(),
 2595                                         fields,
 2596                                         true);
 2597          fcx.write_ty(id, enum_type);
 2598      }
 2599  
 2600      let tcx = fcx.ccx.tcx;
 2601      let id = expr.id;
 2602      match expr.node {
 2603          ast::ExprVstore(ev, vst) => {
 2604              let typ = match ev.node {
 2605                  ast::ExprVec(ref args) => {
 2606                      let mutability = match vst {
 2607                          ast::ExprVstoreMutSlice => ast::MutMutable,
 2608                          _ => ast::MutImmutable,
 2609                      };
 2610                      let mut any_error = false;
 2611                      let mut any_bot = false;
 2612                      let tty::t = fcx.infcx().next_ty_var();
 2613                      for e in args.iter() {
 2614                          check_expr_has_type(fcx, *e, t);
 2615                          let arg_t = fcx.expr_ty(*e);
 2616                          if ty::type_is_error(arg_t) {
 2617                              any_error = true;
 2618                          }
 2619                          else if ty::type_is_bot(arg_t) {
 2620                              any_bot = true;
 2621                          }
 2622                      }
 2623                      if any_error {
 2624                          ty::mk_err()
 2625                      } else if any_bot {
 2626                          ty::mk_bot()
 2627                      } else {
 2628                          ast_expr_vstore_to_ty(fcx, ev, vst, ||
 2629                              ty::mt{ ty: ty::mk_vec(tcx,
 2630                                                     ty::mt {ty: t, mutbl: mutability},
 2631                                                     None),
 2632                                                     mutbl: mutability })
 2633                      }
 2634                  }
 2635                  ast::ExprRepeat(element, count_expr) => {
 2636                      check_expr_with_hint(fcx, count_expr, ty::mk_uint());
 2637                      let _ = ty::eval_repeat_count(fcx, count_expr);
 2638                      let mutability = match vst {
 2639                          ast::ExprVstoreMutSlice => ast::MutMutable,
 2640                          _ => ast::MutImmutable,
 2641                      };
 2642                      let t = fcx.infcx().next_ty_var();
 2643                      check_expr_has_type(fcx, element, t);
 2644                      let arg_t = fcx.expr_ty(element);
 2645                      if ty::type_is_error(arg_t) {
 2646                          ty::mk_err()
 2647                      } else if ty::type_is_bot(arg_t) {
 2648                          ty::mk_bot()
 2649                      } else {
 2650                          ast_expr_vstore_to_ty(fcx, ev, vst, ||
 2651                              ty::mt{ ty: ty::mk_vec(tcx,
 2652                                                     ty::mt {ty: t, mutbl: mutability},
 2653                                                     None),
 2654                                                     mutbl: mutability})
 2655                      }
 2656                  }
 2657                  ast::ExprLit(_) => {
 2658                      let error = if vst == ast::ExprVstoreSlice {
 2659                          "`&\"string\"` has been removed; use `\"string\"` instead"
 2660                      } else {
 2661                          "`~\"string\"` has been removed; use `\"string\".to_owned()` instead"
 2662                      };
 2663                      tcx.sess.span_err(expr.span, error);
 2664                      ty::mk_err()
 2665                  }
 2666                  _ => tcx.sess.span_bug(expr.span, "vstore modifier on non-sequence"),
 2667              };
 2668              fcx.write_ty(ev.id, typ);
 2669              fcx.write_ty(id, typ);
 2670          }
 2671  
 2672        ast::ExprBox(place, subexpr) => {
 2673            check_expr(fcx, place);
 2674            check_expr(fcx, subexpr);
 2675  
 2676            let mut checked = false;
 2677            match place.node {
 2678                ast::ExprPath(ref path) => {
 2679                    // FIXME(pcwalton): For now we hardcode the two permissible
 2680                    // places: the exchange heap and the managed heap.
 2681                    let definition = lookup_def(fcx, path.span, place.id);
 2682                    let def_id = ast_util::def_id_of_def(definition);
 2683                    match tcx.lang_items
 2684                             .items
 2685                             .get(ExchangeHeapLangItem as uint) {
 2686                        &Some(item_def_id) if def_id == item_def_id => {
 2687                            fcx.write_ty(id, ty::mk_uniq(tcx,
 2688                                                         fcx.expr_ty(subexpr)));
 2689                            checked = true
 2690                        }
 2691                        &Some(_) | &None => {}
 2692                    }
 2693                    if !checked {
 2694                        match tcx.lang_items
 2695                                 .items
 2696                                 .get(ManagedHeapLangItem as uint) {
 2697                            &Some(item_def_id) if def_id == item_def_id => {
 2698                                // Assign the magic `Gc<T>` struct.
 2699                                let gc_struct_id =
 2700                                    match tcx.lang_items
 2701                                             .require(GcLangItem) {
 2702                                        Ok(id) => id,
 2703                                        Err(msg) => {
 2704                                            tcx.sess.span_err(expr.span, msg);
 2705                                            ast::DefId {
 2706                                                krate: ast::CRATE_NODE_ID,
 2707                                                node: ast::DUMMY_NODE_ID,
 2708                                            }
 2709                                        }
 2710                                    };
 2711                                let regions =
 2712                                    ty::NonerasedRegions(OwnedSlice::empty());
 2713                                let sty = ty::mk_struct(tcx,
 2714                                                        gc_struct_id,
 2715                                                        substs {
 2716                                                          self_ty: None,
 2717                                                          tps: vec!(
 2718                                                              fcx.expr_ty(
 2719                                                                  subexpr)
 2720                                                          ),
 2721                                                          regions: regions,
 2722                                                        });
 2723                                fcx.write_ty(id, sty);
 2724                                checked = true
 2725                            }
 2726                            &Some(_) | &None => {}
 2727                        }
 2728                    }
 2729                }
 2730                _ => {}
 2731            }
 2732  
 2733            if !checked {
 2734                tcx.sess.span_err(expr.span,
 2735                                  "only the managed heap and exchange heap are \
 2736                                   currently supported")
 2737            }
 2738        }
 2739  
 2740        ast::ExprLit(lit) => {
 2741          let typ = check_lit(fcx, lit);
 2742          fcx.write_ty(id, typ);
 2743        }
 2744        ast::ExprBinary(op, lhs, rhs) => {
 2745          check_binop(fcx, expr, op, lhs, rhs, SimpleBinop);
 2746  
 2747          let lhs_ty = fcx.expr_ty(lhs);
 2748          let rhs_ty = fcx.expr_ty(rhs);
 2749          if ty::type_is_error(lhs_ty) ||
 2750              ty::type_is_error(rhs_ty) {
 2751              fcx.write_error(id);
 2752          }
 2753          else if ty::type_is_bot(lhs_ty) ||
 2754            (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
 2755              fcx.write_bot(id);
 2756          }
 2757        }
 2758        ast::ExprAssignOp(op, lhs, rhs) => {
 2759          check_binop(fcx, expr, op, lhs, rhs, BinopAssignment);
 2760  
 2761          let lhs_t = fcx.expr_ty(lhs);
 2762          let result_t = fcx.expr_ty(expr);
 2763          demand::suptype(fcx, expr.span, result_t, lhs_t);
 2764  
 2765          let tcx = fcx.tcx();
 2766          if !ty::expr_is_lval(tcx, lhs) {
 2767              tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
 2768          }
 2769  
 2770          // Overwrite result of check_binop...this preserves existing behavior
 2771          // but seems quite dubious with regard to user-defined methods
 2772          // and so forth. - Niko
 2773          if !ty::type_is_error(result_t)
 2774              && !ty::type_is_bot(result_t) {
 2775              fcx.write_nil(expr.id);
 2776          }
 2777        }
 2778        ast::ExprUnary(unop, oprnd) => {
 2779          let exp_inner = unpack_expected(fcx, expected, |sty| {
 2780              match unop {
 2781                  ast::UnBox | ast::UnUniq => match *sty {
 2782                      ty::ty_box(ty) | ty::ty_uniq(ty) => Some(ty),
 2783                      _ => None
 2784                  },
 2785                  ast::UnNot | ast::UnNeg => expected,
 2786                  ast::UnDeref => None
 2787              }
 2788          });
 2789          let lvalue_pref = match unop {
 2790              ast::UnDeref => lvalue_pref,
 2791              _ => NoPreference
 2792          };
 2793          check_expr_with_opt_hint_and_lvalue_pref(fcx, oprnd, exp_inner, lvalue_pref);
 2794          let mut oprnd_t = fcx.expr_ty(oprnd);
 2795          if !ty::type_is_error(oprnd_t) && !ty::type_is_bot(oprnd_t) {
 2796              match unop {
 2797                  ast::UnBox => {
 2798                      oprnd_t = ty::mk_box(tcx, oprnd_t)
 2799                  }
 2800                  ast::UnUniq => {
 2801                      oprnd_t = ty::mk_uniq(tcx, oprnd_t);
 2802                  }
 2803                  ast::UnDeref => {
 2804                      oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
 2805                      oprnd_t = match ty::deref(oprnd_t, true) {
 2806                          Some(mt) => mt.ty,
 2807                          None => match try_overloaded_deref(fcx, expr.span,
 2808                                                             Some(MethodCall::expr(expr.id)),
 2809                                                             Some(&*oprnd), oprnd_t, lvalue_pref) {
 2810                              Some(mt) => mt.ty,
 2811                              None => {
 2812                                  let is_newtype = match ty::get(oprnd_t).sty {
 2813                                      ty::ty_struct(did, ref substs) => {
 2814                                          let fields = ty::struct_fields(fcx.tcx(), did, substs);
 2815                                          fields.len() == 1
 2816                                          && fields.get(0).ident ==
 2817                                          token::special_idents::unnamed_field
 2818                                      }
 2819                                      _ => false
 2820                                  };
 2821                                  if is_newtype {
 2822                                      // This is an obsolete struct deref
 2823                                      tcx.sess.span_err(expr.span,
 2824                                          "single-field tuple-structs can \
 2825                                           no longer be dereferenced");
 2826                                  } else {
 2827                                      fcx.type_error_message(expr.span, |actual| {
 2828                                          format!("type `{}` cannot be dereferenced", actual)
 2829                                      }, oprnd_t, None);
 2830                                  }
 2831                                  ty::mk_err()
 2832                              }
 2833                          }
 2834                      };
 2835                  }
 2836                  ast::UnNot => {
 2837                      oprnd_t = structurally_resolved_type(fcx, oprnd.span,
 2838                                                           oprnd_t);
 2839                      if !(ty::type_is_integral(oprnd_t) ||
 2840                           ty::get(oprnd_t).sty == ty::ty_bool) {
 2841                          oprnd_t = check_user_unop(fcx, "!", "not",
 2842                                                    tcx.lang_items.not_trait(),
 2843                                                    expr, oprnd, oprnd_t);
 2844                      }
 2845                  }
 2846                  ast::UnNeg => {
 2847                      oprnd_t = structurally_resolved_type(fcx, oprnd.span,
 2848                                                           oprnd_t);
 2849                      if !(ty::type_is_integral(oprnd_t) ||
 2850                           ty::type_is_fp(oprnd_t)) {
 2851                          oprnd_t = check_user_unop(fcx, "-", "neg",
 2852                                                    tcx.lang_items.neg_trait(),
 2853                                                    expr, oprnd, oprnd_t);
 2854                      }
 2855                  }
 2856              }
 2857          }
 2858          fcx.write_ty(id, oprnd_t);
 2859        }
 2860        ast::ExprAddrOf(mutbl, oprnd) => {
 2861            let hint = unpack_expected(
 2862                fcx, expected,
 2863                |sty| match *sty { ty::ty_rptr(_, ref mt) => Some(mt.ty),
 2864                                   _ => None });
 2865          let lvalue_pref = match mutbl {
 2866              ast::MutMutable => PreferMutLvalue,
 2867              ast::MutImmutable => NoPreference
 2868          };
 2869          check_expr_with_opt_hint_and_lvalue_pref(fcx, oprnd, hint, lvalue_pref);
 2870  
 2871          // Note: at this point, we cannot say what the best lifetime
 2872          // is to use for resulting pointer.  We want to use the
 2873          // shortest lifetime possible so as to avoid spurious borrowck
 2874          // errors.  Moreover, the longest lifetime will depend on the
 2875          // precise details of the value whose address is being taken
 2876          // (and how long it is valid), which we don't know yet until type
 2877          // inference is complete.
 2878          //
 2879          // Therefore, here we simply generate a region variable.  The
 2880          // region inferencer will then select the ultimate value.
 2881          // Finally, borrowck is charged with guaranteeing that the
 2882          // value whose address was taken can actually be made to live
 2883          // as long as it needs to live.
 2884          let region = fcx.infcx().next_region_var(
 2885              infer::AddrOfRegion(expr.span));
 2886  
 2887          let tm = ty::mt { ty: fcx.expr_ty(oprnd), mutbl: mutbl };
 2888          let oprnd_t = if ty::type_is_error(tm.ty) {
 2889              ty::mk_err()
 2890          } else if ty::type_is_bot(tm.ty) {
 2891              ty::mk_bot()
 2892          }
 2893          else {
 2894              ty::mk_rptr(tcx, region, tm)
 2895          };
 2896          fcx.write_ty(id, oprnd_t);
 2897        }
 2898        ast::ExprPath(ref pth) => {
 2899          let defn = lookup_def(fcx, pth.span, id);
 2900  
 2901          check_type_parameter_positions_in_path(fcx, pth, defn);
 2902          let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
 2903          instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
 2904        }
 2905        ast::ExprInlineAsm(ref ia) => {
 2906            for &(_, input) in ia.inputs.iter() {
 2907                check_expr(fcx, input);
 2908            }
 2909            for &(_, out) in ia.outputs.iter() {
 2910                check_expr(fcx, out);
 2911            }
 2912            fcx.write_nil(id);
 2913        }
 2914        ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
 2915        ast::ExprBreak(_) => { fcx.write_bot(id); }
 2916        ast::ExprAgain(_) => { fcx.write_bot(id); }
 2917        ast::ExprRet(expr_opt) => {
 2918          let ret_ty = fcx.ret_ty;
 2919          match expr_opt {
 2920            None => match fcx.mk_eqty(false, infer::Misc(expr.span),
 2921                                      ret_ty, ty::mk_nil()) {
 2922              Ok(_) => { /* fall through */ }
 2923              Err(_) => {
 2924                  tcx.sess.span_err(
 2925                      expr.span,
 2926                      "`return;in function returning non-nil");
 2927              }
 2928            },
 2929            Some(e) => {
 2930                check_expr_has_type(fcx, e, ret_ty);
 2931            }
 2932          }
 2933          fcx.write_bot(id);
 2934        }
 2935        ast::ExprParen(a) => {
 2936          check_expr_with_opt_hint_and_lvalue_pref(fcx, a, expected, lvalue_pref);
 2937          fcx.write_ty(id, fcx.expr_ty(a));
 2938        }
 2939        ast::ExprAssign(lhs, rhs) => {
 2940          check_expr_with_lvalue_pref(fcx, lhs, PreferMutLvalue);
 2941  
 2942          let tcx = fcx.tcx();
 2943          if !ty::expr_is_lval(tcx, lhs) {
 2944              tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
 2945          }
 2946  
 2947          let lhs_ty = fcx.expr_ty(lhs);
 2948          check_expr_has_type(fcx, rhs, lhs_ty);
 2949          let rhs_ty = fcx.expr_ty(rhs);
 2950  
 2951          if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
 2952              fcx.write_error(id);
 2953          } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
 2954              fcx.write_bot(id);
 2955          } else {
 2956              fcx.write_nil(id);
 2957          }
 2958        }
 2959        ast::ExprIf(cond, then_blk, opt_else_expr) => {
 2960          check_then_else(fcx, cond, then_blk, opt_else_expr,
 2961                          id, expr.span, expected);
 2962        }
 2963        ast::ExprWhile(cond, body) => {
 2964          check_expr_has_type(fcx, cond, ty::mk_bool());
 2965          check_block_no_value(fcx, body);
 2966          let cond_ty = fcx.expr_ty(cond);
 2967          let body_ty = fcx.node_ty(body.id);
 2968          if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
 2969              fcx.write_error(id);
 2970          }
 2971          else if ty::type_is_bot(cond_ty) {
 2972              fcx.write_bot(id);
 2973          }
 2974          else {
 2975              fcx.write_nil(id);
 2976          }
 2977        }
 2978        ast::ExprForLoop(..) =>
 2979            fail!("non-desugared expr_for_loop"),
 2980        ast::ExprLoop(body, _) => {
 2981          check_block_no_value(fcx, (body));
 2982          if !may_break(tcx, expr.id, body) {
 2983              fcx.write_bot(id);
 2984          }
 2985          else {
 2986              fcx.write_nil(id);
 2987          }
 2988        }
 2989        ast::ExprMatch(discrim, ref arms) => {
 2990          _match::check_match(fcx, expr, discrim, arms.as_slice());
 2991        }
 2992        ast::ExprFnBlock(decl, body) => {
 2993          let region = astconv::opt_ast_region_to_region(fcx,
 2994                                                         fcx.infcx(),
 2995                                                         expr.span,
 2996                                                         &None);
 2997          check_expr_fn(fcx,
 2998                        expr,
 2999                        ty::RegionTraitStore(region, ast::MutMutable),
 3000                        decl,
 3001                        body,
 3002                        Vanilla,
 3003                        expected);
 3004        }
 3005        ast::ExprProc(decl, body) => {
 3006          check_expr_fn(fcx,
 3007                        expr,
 3008                        ty::UniqTraitStore,
 3009                        decl,
 3010                        body,
 3011                        Vanilla,
 3012                        expected);
 3013        }
 3014        ast::ExprBlock(b) => {
 3015          check_block_with_expected(fcx, b, expected);
 3016          fcx.write_ty(id, fcx.node_ty(b.id));
 3017        }
 3018        ast::ExprCall(f, ref args) => {
 3019            check_call(fcx, expr, f, args.as_slice());
 3020            let f_ty = fcx.expr_ty(f);
 3021            let (args_bot, args_err) = args.iter().fold((false, false),
 3022               |(rest_bot, rest_err), a| {
 3023                   // is this not working?
 3024                   let a_ty = fcx.expr_ty(*a);
 3025                   (rest_bot || ty::type_is_bot(a_ty),
 3026                    rest_err || ty::type_is_error(a_ty))});
 3027            if ty::type_is_error(f_ty) || args_err {
 3028                fcx.write_error(id);
 3029            }
 3030            else if ty::type_is_bot(f_ty) || args_bot {
 3031                fcx.write_bot(id);
 3032            }
 3033        }
 3034        ast::ExprMethodCall(ident, ref tps, ref args) => {
 3035          check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice());
 3036          let mut arg_tys = args.iter().map(|a| fcx.expr_ty(*a));
 3037          let (args_bot, args_err) = arg_tys.fold((false, false),
 3038               |(rest_bot, rest_err), a| {
 3039                (rest_bot || ty::type_is_bot(a),
 3040                 rest_err || ty::type_is_error(a))});
 3041          if args_err {
 3042              fcx.write_error(id);
 3043          } else if args_bot {
 3044              fcx.write_bot(id);
 3045          }
 3046        }
 3047        ast::ExprCast(e, t) => {
 3048          check_expr(fcx, e);
 3049          let t_1 = fcx.to_ty(t);
 3050          let t_e = fcx.expr_ty(e);
 3051  
 3052          debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
 3053          debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
 3054  
 3055          if ty::type_is_error(t_e) {
 3056              fcx.write_error(id);
 3057          }
 3058          else if ty::type_is_bot(t_e) {
 3059              fcx.write_bot(id);
 3060          }
 3061          else {
 3062              match ty::get(t_1).sty {
 3063                  // This will be looked up later on
 3064                  ty::ty_trait(..) => (),
 3065  
 3066                  _ => {
 3067                      if ty::type_is_nil(t_e) {
 3068                          fcx.type_error_message(expr.span, |actual| {
 3069                              format!("cast from nil: `{}` as `{}`", actual,
 3070                                   fcx.infcx().ty_to_str(t_1))
 3071                          }, t_e, None);
 3072                      } else if ty::type_is_nil(t_1) {
 3073                          fcx.type_error_message(expr.span, |actual| {
 3074                              format!("cast to nil: `{}` as `{}`", actual,
 3075                                   fcx.infcx().ty_to_str(t_1))
 3076                          }, t_e, None);
 3077                      }
 3078  
 3079                      let t1 = structurally_resolved_type(fcx, e.span, t_1);
 3080                      let te = structurally_resolved_type(fcx, e.span, t_e);
 3081                      let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
 3082                      let t_1_is_char = type_is_char(fcx, expr.span, t_1);
 3083                      let t_1_is_bare_fn = type_is_bare_fn(fcx, expr.span, t_1);
 3084  
 3085                      // casts to scalars other than `char` and `bare fn` are trivial
 3086                      let t_1_is_trivial = t_1_is_scalar &&
 3087                          !t_1_is_char && !t_1_is_bare_fn;
 3088  
 3089                      if type_is_c_like_enum(fcx, expr.span, t_e) && t_1_is_trivial {
 3090                          // casts from C-like enums are allowed
 3091                      } else if t_1_is_char {
 3092                          let te = fcx.infcx().resolve_type_vars_if_possible(te);
 3093                          if ty::get(te).sty != ty::ty_uint(ast::TyU8) {
 3094                              fcx.type_error_message(expr.span, |actual| {
 3095                                  format!("only `u8` can be cast as `char`, not `{}`", actual)
 3096                              }, t_e, None);
 3097                          }
 3098                      } else if ty::get(t1).sty == ty::ty_bool {
 3099                          fcx.tcx().sess.span_err(expr.span,
 3100                                                  "cannot cast as `bool`, compare with zero instead");
 3101                      } else if type_is_region_ptr(fcx, expr.span, t_e) &&
 3102                          type_is_unsafe_ptr(fcx, expr.span, t_1) {
 3103  
 3104                          fn is_vec(tty::t) -> bool {
 3105                              match ty::get(t).sty {
 3106                                  ty::ty_vec(..) => true,
 3107                                  ty::ty_ptr(ty::mt{ty: t, ..}) | ty::ty_rptr(_, ty::mt{ty: t, ..}) |
 3108                                  ty::ty_box(t) | ty::ty_uniq(t) => match ty::get(t).sty {
 3109                                      ty::ty_vec(_, None) => true,
 3110                                      _ => false,
 3111                                  },
 3112                                  _ => false
 3113                              }
 3114                          }
 3115                          fn types_compatible(fcx&FnCtxt, spSpan,
 3116                                              t1ty::t, t2ty::t) -> bool {
 3117                              if !is_vec(t1) {
 3118                                  false
 3119                              } else {
 3120                                  let el = ty::sequence_element_type(fcx.tcx(),
 3121                                                                     t1);
 3122                                  infer::mk_eqty(fcx.infcx(), false,
 3123                                                 infer::Misc(sp), el, t2).is_ok()
 3124                              }
 3125                          }
 3126  
 3127                          // Due to the limitations of LLVM global constants,
 3128                          // region pointers end up pointing at copies of
 3129                          // vector elements instead of the original values.
 3130                          // To allow unsafe pointers to work correctly, we
 3131                          // need to special-case obtaining an unsafe pointer
 3132                          // from a region pointer to a vector.
 3133  
 3134                          /* this cast is only allowed from &[T] to *T or
 3135                          &T to *T. */
 3136                          match (&ty::get(te).sty, &ty::get(t_1).sty) {
 3137                              (&ty::ty_rptr(_, mt1), &ty::ty_ptr(mt2))
 3138                              if types_compatible(fcx, e.span,
 3139                                                  mt1.ty, mt2.ty) => {
 3140                                  /* this case is allowed */
 3141                              }
 3142                              _ => {
 3143                                  demand::coerce(fcx, e.span, t_1, e);
 3144                              }
 3145                          }
 3146                      } else if !(type_is_scalar(fcx,expr.span,t_e)
 3147                                  && t_1_is_trivial) {
 3148                          /*
 3149                          If more type combinations should be supported than are
 3150                          supported here, then file an enhancement issue and
 3151                          record the issue number in this comment.
 3152                          */
 3153                          fcx.type_error_message(expr.span, |actual| {
 3154                              format!("non-scalar cast: `{}` as `{}`", actual,
 3155                                   fcx.infcx().ty_to_str(t_1))
 3156                          }, t_e, None);
 3157                      }
 3158                  }
 3159              }
 3160              fcx.write_ty(id, t_1);
 3161          }
 3162        }
 3163        ast::ExprVec(ref args) => {
 3164          let tty::t = fcx.infcx().next_ty_var();
 3165          for e in args.iter() {
 3166              check_expr_has_type(fcx, *e, t);
 3167          }
 3168          let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
 3169                               Some(args.len()));
 3170          fcx.write_ty(id, typ);
 3171        }
 3172        ast::ExprRepeat(element, count_expr) => {
 3173          check_expr_with_hint(fcx, count_expr, ty::mk_uint());
 3174          let count = ty::eval_repeat_count(fcx, count_expr);
 3175          let tty::t = fcx.infcx().next_ty_var();
 3176          check_expr_has_type(fcx, element, t);
 3177          let element_ty = fcx.expr_ty(element);
 3178          if ty::type_is_error(element_ty) {
 3179              fcx.write_error(id);
 3180          }
 3181          else if ty::type_is_bot(element_ty) {
 3182              fcx.write_bot(id);
 3183          }
 3184          else {
 3185              let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
 3186                                 Some(count));
 3187              fcx.write_ty(id, t);
 3188          }
 3189        }
 3190        ast::ExprTup(ref elts) => {
 3191          let flds = unpack_expected(fcx, expected, |sty| {
 3192              match *sty {
 3193                  ty::ty_tup(ref flds) => Some((*flds).clone()),
 3194                  _ => None
 3195              }
 3196          });
 3197          let mut bot_field = false;
 3198          let mut err_field = false;
 3199  
 3200          let elt_ts = elts.iter().enumerate().map(|(i, e)| {
 3201              let opt_hint = match flds {
 3202                  Some(ref fs) if i < fs.len() => Some(*fs.get(i)),
 3203                  _ => None
 3204              };
 3205              check_expr_with_opt_hint(fcx, *e, opt_hint);
 3206              let t = fcx.expr_ty(*e);
 3207              err_field = err_field || ty::type_is_error(t);
 3208              bot_field = bot_field || ty::type_is_bot(t);
 3209              t
 3210          }).collect();
 3211          if bot_field {
 3212              fcx.write_bot(id);
 3213          } else if err_field {
 3214              fcx.write_error(id);
 3215          } else {
 3216              let typ = ty::mk_tup(tcx, elt_ts);
 3217              fcx.write_ty(id, typ);
 3218          }
 3219        }
 3220        ast::ExprStruct(ref path, ref fields, base_expr) => {
 3221          // Resolve the path.
 3222          let def = tcx.def_map.borrow().find(&id).map(|i| *i);
 3223          match def {
 3224              Some(ast::DefStruct(type_def_id)) => {
 3225                  check_struct_constructor(fcx, id, expr.span, type_def_id,
 3226                                           fields.as_slice(), base_expr);
 3227              }
 3228              Some(ast::DefVariant(enum_id, variant_id, _)) => {
 3229                  check_struct_enum_variant(fcx, id, expr.span, enum_id,
 3230                                            variant_id, fields.as_slice());
 3231              }
 3232              _ => {
 3233                  tcx.sess.span_bug(path.span,
 3234                                    "structure constructor does not name a structure type");
 3235              }
 3236          }
 3237        }
 3238        ast::ExprField(base, field, ref tys) => {
 3239          check_field(fcx, expr, lvalue_pref, base, field.name, tys.as_slice());
 3240        }
 3241        ast::ExprIndex(base, idx) => {
 3242            check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
 3243            check_expr(fcx, idx);
 3244            let raw_base_t = fcx.expr_ty(base);
 3245            let idx_t = fcx.expr_ty(idx);
 3246            if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
 3247                fcx.write_ty(id, raw_base_t);
 3248            } else if ty::type_is_error(idx_t) || ty::type_is_bot(idx_t) {
 3249                fcx.write_ty(id, idx_t);
 3250            } else {
 3251                let (base_t, autoderefs, field_ty) =
 3252                  autoderef(fcx, expr.span, raw_base_t, Some(base.id),
 3253                            lvalue_pref, |base_t, _| ty::index(base_t));
 3254                match field_ty {
 3255                    Some(mt) => {
 3256                        check_expr_has_type(fcx, idx, ty::mk_uint());
 3257                        fcx.write_ty(id, mt.ty);
 3258                        fcx.write_autoderef_adjustment(base.id, autoderefs);
 3259                    }
 3260                    None => {
 3261                        let resolved = structurally_resolved_type(fcx,
 3262                                                                  expr.span,
 3263                                                                  raw_base_t);
 3264                        let ret_ty = lookup_op_method(fcx,
 3265                                                      expr,
 3266                                                      resolved,
 3267                                                      token::intern("index"),
 3268                                                      tcx.lang_items.index_trait(),
 3269                                                      [base, idx],
 3270                                                      AutoderefReceiver,
 3271                                                      || {
 3272                          fcx.type_error_message(expr.span,
 3273                                                 |actual| {
 3274                                                  format!("cannot index a value \
 3275                                                        of type `{}`",
 3276                                                       actual)
 3277                                                 },
 3278                                                 base_t,
 3279                                                 None);
 3280                        });
 3281                        fcx.write_ty(id, ret_ty);
 3282                    }
 3283                }
 3284            }
 3285         }
 3286      }
 3287  
 3288      debug!("type of expr({}) {} is...", expr.id,
 3289             syntax::print::pprust::expr_to_str(expr));
 3290      debug!("... {}, expected is {}",
 3291             ppaux::ty_to_str(tcx, fcx.expr_ty(expr)),
 3292             match expected {
 3293                 Some(t) => ppaux::ty_to_str(tcx, t),
 3294                 _ => "empty".to_owned()
 3295             });
 3296  
 3297      unifier();
 3298  }
 3299  
 3300  pub fn require_uint(fcx: &FnCtxt, spSpan, tty::t) {
 3301      if !type_is_uint(fcx, sp, t) {
 3302          fcx.type_error_message(sp, |actual| {
 3303              format!("mismatched types: expected `uint` type but found `{}`",
 3304                   actual)
 3305          }, t, None);
 3306      }
 3307  }
 3308  
 3309  pub fn require_integral(fcx: &FnCtxt, spSpan, tty::t) {
 3310      if !type_is_integral(fcx, sp, t) {
 3311          fcx.type_error_message(sp, |actual| {
 3312              format!("mismatched types: expected integral type but found `{}`",
 3313                   actual)
 3314          }, t, None);
 3315      }
 3316  }
 3317  
 3318  pub fn check_decl_initializer(fcx: &FnCtxt,
 3319                                nidast::NodeId,
 3320                                init: &ast::Expr)
 3321                              {
 3322      let local_ty = fcx.local_ty(init.span, nid);
 3323      check_expr_coercable_to_type(fcx, init, local_ty)
 3324  }
 3325  
 3326  pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
 3327      let tcx = fcx.ccx.tcx;
 3328  
 3329      let t = fcx.local_ty(local.span, local.id);
 3330      fcx.write_ty(local.id, t);
 3331  
 3332      match local.init {
 3333          Some(init) => {
 3334              check_decl_initializer(fcx, local.id, init);
 3335              let init_ty = fcx.expr_ty(init);
 3336              if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
 3337                  fcx.write_ty(local.id, init_ty);
 3338              }
 3339          }
 3340          _ => {}
 3341      }
 3342  
 3343      let pcx = pat_ctxt {
 3344          fcx: fcx,
 3345          map: pat_id_map(&tcx.def_map, local.pat),
 3346      };
 3347      _match::check_pat(&pcx, local.pat, t);
 3348      let pat_ty = fcx.node_ty(local.pat.id);
 3349      if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
 3350          fcx.write_ty(local.id, pat_ty);
 3351      }
 3352  }
 3353  
 3354  pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
 3355      let node_id;
 3356      let mut saw_bot = false;
 3357      let mut saw_err = false;
 3358      match stmt.node {
 3359        ast::StmtDecl(decl, id) => {
 3360          node_id = id;
 3361          match decl.node {
 3362            ast::DeclLocal(ref l) => {
 3363                check_decl_local(fcx, *l);
 3364                let l_t = fcx.node_ty(l.id);
 3365                saw_bot = saw_bot || ty::type_is_bot(l_t);
 3366                saw_err = saw_err || ty::type_is_error(l_t);
 3367            }
 3368            ast::DeclItem(_) => {/* ignore for now */ }
 3369          }
 3370        }
 3371        ast::StmtExpr(expr, id) => {
 3372          node_id = id;
 3373          // Check with expected type of ()
 3374          check_expr_has_type(fcx, expr, ty::mk_nil());
 3375          let expr_ty = fcx.expr_ty(expr);
 3376          saw_bot = saw_bot || ty::type_is_bot(expr_ty);
 3377          saw_err = saw_err || ty::type_is_error(expr_ty);
 3378        }
 3379        ast::StmtSemi(expr, id) => {
 3380          node_id = id;
 3381          check_expr(fcx, expr);
 3382          let expr_ty = fcx.expr_ty(expr);
 3383          saw_bot |= ty::type_is_bot(expr_ty);
 3384          saw_err |= ty::type_is_error(expr_ty);
 3385        }
 3386        ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
 3387      }
 3388      if saw_bot {
 3389          fcx.write_bot(node_id);
 3390      }
 3391      else if saw_err {
 3392          fcx.write_error(node_id);
 3393      }
 3394      else {
 3395          fcx.write_nil(node_id)
 3396      }
 3397  }
 3398  
 3399  pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
 3400      check_block_with_expected(fcx, blk, Some(ty::mk_nil()));
 3401      let blkty = fcx.node_ty(blk.id);
 3402      if ty::type_is_error(blkty) {
 3403          fcx.write_error(blk.id);
 3404      }
 3405      else if ty::type_is_bot(blkty) {
 3406          fcx.write_bot(blk.id);
 3407      }
 3408      else {
 3409          let nilty = ty::mk_nil();
 3410          demand::suptype(fcx, blk.span, nilty, blkty);
 3411      }
 3412  }
 3413  
 3414  pub fn check_block_with_expected(fcx: &FnCtxt,
 3415                                   blk: &ast::Block,
 3416                                   expectedOption<ty::t>) {
 3417      let prev = {
 3418          let mut fcx_ps = fcx.ps.borrow_mut();
 3419          let fn_style_state = fcx_ps.recurse(blk);
 3420          replace(&mut *fcx_ps, fn_style_state)
 3421      };
 3422  
 3423      fcx.with_region_lb(blk.id, || {
 3424          let mut warned = false;
 3425          let mut last_was_bot = false;
 3426          let mut any_bot = false;
 3427          let mut any_err = false;
 3428          for s in blk.stmts.iter() {
 3429              check_stmt(fcx, *s);
 3430              let s_id = ast_util::stmt_id(*s);
 3431              let s_ty = fcx.node_ty(s_id);
 3432              if last_was_bot && !warned && match s.node {
 3433                    ast::StmtDecl(decl, _) => {
 3434                        match decl.node {
 3435                            ast::DeclLocal(_) => true,
 3436                            _ => false,
 3437                        }
 3438                    }
 3439                    ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
 3440                    _ => false
 3441                  } {
 3442                  fcx.ccx.tcx.sess.add_lint(UnreachableCode, s_id, s.span,
 3443                                            "unreachable statement".to_owned());
 3444                  warned = true;
 3445              }
 3446              if ty::type_is_bot(s_ty) {
 3447                  last_was_bot = true;
 3448              }
 3449              any_bot = any_bot || ty::type_is_bot(s_ty);
 3450              any_err = any_err || ty::type_is_error(s_ty);
 3451          }
 3452          match blk.expr {
 3453              None => if any_err {
 3454                  fcx.write_error(blk.id);
 3455              }
 3456              else if any_bot {
 3457                  fcx.write_bot(blk.id);
 3458              }
 3459              else  {
 3460                  fcx.write_nil(blk.id);
 3461              },
 3462            Some(e) => {
 3463              if any_bot && !warned {
 3464                  fcx.ccx.tcx.sess.add_lint(UnreachableCode, e.id, e.span,
 3465                                            "unreachable expression".to_owned());
 3466              }
 3467              check_expr_with_opt_hint(fcx, e, expected);
 3468                let ety = fcx.expr_ty(e);
 3469                fcx.write_ty(blk.id, ety);
 3470                if any_err {
 3471                    fcx.write_error(blk.id);
 3472                }
 3473                else if any_bot {
 3474                    fcx.write_bot(blk.id);
 3475                }
 3476            }
 3477          };
 3478      });
 3479  
 3480      *fcx.ps.borrow_mut() = prev;
 3481  }
 3482  
 3483  pub fn check_const(ccx: &CrateCtxt,
 3484                     spSpan,
 3485                     e: &ast::Expr,
 3486                     idast::NodeId) {
 3487      let inh = blank_inherited_fields(ccx);
 3488      let rty = ty::node_id_to_type(ccx.tcx, id);
 3489      let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
 3490      let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
 3491      check_const_with_ty(&fcx, sp, e, declty);
 3492  }
 3493  
 3494  pub fn check_const_with_ty(fcx: &FnCtxt,
 3495                             _Span,
 3496                             e: &ast::Expr,
 3497                             decltyty::t) {
 3498      check_expr(fcx, e);
 3499      let cty = fcx.expr_ty(e);
 3500      demand::suptype(fcx, e.span, declty, cty);
 3501      regionck::regionck_expr(fcx, e);
 3502      writeback::resolve_type_vars_in_expr(fcx, e);
 3503  }
 3504  
 3505  /// Checks whether a type can be represented in memory. In particular, it
 3506  /// identifies types that contain themselves without indirection through a
 3507  /// pointer, which would mean their size is unbounded. This is different from
 3508  /// the question of whether a type can be instantiated. See the definition of
 3509  /// `check_instantiable`.
 3510  pub fn check_representable(tcx: &ty::ctxt,
 3511                             spSpan,
 3512                             item_idast::NodeId,
 3513                             designation: &str) -> bool {
 3514      let rty = ty::node_id_to_type(tcx, item_id);
 3515  
 3516      // Check that it is possible to represent this type. This call identifies
 3517      // (1) types that contain themselves and (2) types that contain a different
 3518      // recursive type. It is only necessary to throw an error on those that
 3519      // contain themselves. For case 2, there must be an inner type that will be
 3520      // caught by case 1.
 3521      match ty::is_type_representable(tcx, sp, rty) {
 3522        ty::SelfRecursive => {
 3523          tcx.sess.span_err(
 3524            sp, format!("illegal recursive {} type; \
 3525                         wrap the inner value in a box to make it representable",
 3526                        designation));
 3527          return false
 3528        }
 3529        ty::Representable | ty::ContainsRecursive => (),
 3530      }
 3531      return true
 3532  }
 3533  
 3534  /// Checks whether a type can be created without an instance of itself.
 3535  /// This is similar but different from the question of whether a type
 3536  /// can be represented.  For example, the following type:
 3537  ///
 3538  ///     enum foo { None, Some(foo) }
 3539  ///
 3540  /// is instantiable but is not representable.  Similarly, the type
 3541  ///
 3542  ///     enum foo { Some(@foo) }
 3543  ///
 3544  /// is representable, but not instantiable.
 3545  pub fn check_instantiable(tcx: &ty::ctxt,
 3546                            spSpan,
 3547                            item_idast::NodeId)
 3548                            -> bool {
 3549      let item_ty = ty::node_id_to_type(tcx, item_id);
 3550      if !ty::is_instantiable(tcx, item_ty) {
 3551          tcx.sess.span_err(sp, format!("this type cannot be instantiated \
 3552                    without an instance of itself; \
 3553                    consider using `Option<{}>`",
 3554                                     ppaux::ty_to_str(tcx, item_ty)));
 3555          false
 3556      } else {
 3557          true
 3558      }
 3559  }
 3560  
 3561  pub fn check_simd(tcx: &ty::ctxt, spSpan, idast::NodeId) {
 3562      let t = ty::node_id_to_type(tcx, id);
 3563      if ty::type_needs_subst(t) {
 3564          tcx.sess.span_err(sp, "SIMD vector cannot be generic");
 3565          return;
 3566      }
 3567      match ty::get(t).sty {
 3568          ty::ty_struct(did, ref substs) => {
 3569              let fields = ty::lookup_struct_fields(tcx, did);
 3570              if fields.is_empty() {
 3571                  tcx.sess.span_err(sp, "SIMD vector cannot be empty");
 3572                  return;
 3573              }
 3574              let e = ty::lookup_field_type(tcx, did, fields.get(0).id, substs);
 3575              if !fields.iter().all(
 3576                           |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
 3577                  tcx.sess.span_err(sp, "SIMD vector should be homogeneous");
 3578                  return;
 3579              }
 3580              if !ty::type_is_machine(e) {
 3581                  tcx.sess.span_err(sp, "SIMD vector element type should be \
 3582                                         machine type");
 3583                  return;
 3584              }
 3585          }
 3586          _ => ()
 3587      }
 3588  }
 3589  
 3590  pub fn check_enum_variants_sized(ccx: &CrateCtxt,
 3591                                   vs: &[ast::P<ast::Variant>]) {
 3592      for &v in vs.iter() {
 3593          match v.node.kind {
 3594              ast::TupleVariantKind(ref args) if args.len() > 0 => {
 3595                  let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
 3596                  let arg_tysVec<ty::t> = ty::ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
 3597                  let len = arg_tys.len();
 3598                  if len == 0 {
 3599                      return;
 3600                  }
 3601                  for (i, t) in arg_tys.slice_to(len - 1).iter().enumerate() {
 3602                      // Allow the last field in an enum to be unsized.
 3603                      // We want to do this so that we can support smart pointers.
 3604                      // A struct value with an unsized final field is itself
 3605                      // unsized and we must track this in the type system.
 3606                      if !ty::type_is_sized(ccx.tcx, *t) {
 3607                          ccx.tcx.sess.span_err(args.get(i).ty.span,
 3608                                                format!("type `{}` is dynamically sized. \
 3609                                                         dynamically sized types may only \
 3610                                                         appear as the final type in a variant",
 3611                                                        ppaux::ty_to_str(ccx.tcx, *t)));
 3612                      }
 3613                  }
 3614              },
 3615              ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, struct_def),
 3616              _ => {}
 3617          }
 3618      }
 3619  }
 3620  
 3621  pub fn check_enum_variants(ccx: &CrateCtxt,
 3622                             spSpan,
 3623                             vs: &[ast::P<ast::Variant>],
 3624                             idast::NodeId) {
 3625  
 3626      fn disr_in_range(ccx&CrateCtxt,
 3627                       tyattr::IntType,
 3628                       disrty::Disr) -> bool {
 3629          fn uint_in_range(ccx&CrateCtxt, tyast::UintTy, disrty::Disr) -> bool {
 3630              match ty {
 3631                  ast::TyU8 => disr as u8 as Disr == disr,
 3632                  ast::TyU16 => disr as u16 as Disr == disr,
 3633                  ast::TyU32 => disr as u32 as Disr == disr,
 3634                  ast::TyU64 => disr as u64 as Disr == disr,
 3635                  ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
 3636              }
 3637          }
 3638          fn int_in_range(ccx&CrateCtxt, tyast::IntTy, disrty::Disr) -> bool {
 3639              match ty {
 3640                  ast::TyI8 => disr as i8 as Disr == disr,
 3641                  ast::TyI16 => disr as i16 as Disr == disr,
 3642                  ast::TyI32 => disr as i32 as Disr == disr,
 3643                  ast::TyI64 => disr as i64 as Disr == disr,
 3644                  ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
 3645              }
 3646          }
 3647          match ty {
 3648              attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
 3649              attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
 3650          }
 3651      }
 3652  
 3653      fn do_check(ccx: &CrateCtxt,
 3654                  vs: &[ast::P<ast::Variant>],
 3655                  idast::NodeId,
 3656                  hintattr::ReprAttr)
 3657                  -> Vec<Rc<ty::VariantInfo>> {
 3658  
 3659          let rty = ty::node_id_to_type(ccx.tcx, id);
 3660          let mut variantsVec<Rc<ty::VariantInfo>> = Vec::new();
 3661          let mut disr_valsVec<ty::Disr> = Vec::new();
 3662          let mut prev_disr_valOption<ty::Disr> = None;
 3663  
 3664          for &v in vs.iter() {
 3665  
 3666              // If the discriminant value is specified explicitly in the enum check whether the
 3667              // initialization expression is valid, otherwise use the last value plus one.
 3668              let mut current_disr_val = match prev_disr_val {
 3669                  Some(prev_disr_val) => prev_disr_val + 1,
 3670                  None => ty::INITIAL_DISCRIMINANT_VALUE
 3671              };
 3672  
 3673              match v.node.disr_expr {
 3674                  Some(e) => {
 3675                      debug!("disr expr, checking {}", pprust::expr_to_str(e));
 3676  
 3677                      let inh = blank_inherited_fields(ccx);
 3678                      let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
 3679                      let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id());
 3680                      check_const_with_ty(&fcx, e.span, e, declty);
 3681                      // check_expr (from check_const pass) doesn't guarantee
 3682                      // that the expression is in a form that eval_const_expr can
 3683                      // handle, so we may still get an internal compiler error
 3684  
 3685                      match const_eval::eval_const_expr_partial(ccx.tcx, e) {
 3686                          Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
 3687                          Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
 3688                          Ok(_) => {
 3689                              ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
 3690                          }
 3691                          Err(ref err) => {
 3692                              ccx.tcx.sess.span_err(e.span, format!("expected constant: {}", *err));
 3693                          }
 3694                      }
 3695                  },
 3696                  None => ()
 3697              };
 3698  
 3699              // Check for duplicate discriminant values
 3700              if disr_vals.contains(&current_disr_val) {
 3701                  ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
 3702              }
 3703              // Check for unrepresentable discriminant values
 3704              match hint {
 3705                  attr::ReprAny | attr::ReprExtern => (),
 3706                  attr::ReprInt(sp, ity) => {
 3707                      if !disr_in_range(ccx, ity, current_disr_val) {
 3708                          ccx.tcx.sess.span_err(v.span,
 3709                                                "discriminant value outside specified type");
 3710                          ccx.tcx.sess.span_note(sp, "discriminant type specified here");
 3711                      }
 3712                  }
 3713              }
 3714              disr_vals.push(current_disr_val);
 3715  
 3716              let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, v,
 3717                                                                       current_disr_val));
 3718              prev_disr_val = Some(current_disr_val);
 3719  
 3720              variants.push(variant_info);
 3721          }
 3722  
 3723          return variants;
 3724      }
 3725  
 3726      let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id });
 3727      if hint != attr::ReprAny && vs.len() <= 1 {
 3728          let msg = if vs.len() == 1 {
 3729              "unsupported representation for univariant enum"
 3730          } else {
 3731              "unsupported representation for zero-variant enum"
 3732          };
 3733          ccx.tcx.sess.span_err(sp, msg)
 3734      }
 3735  
 3736      let variants = do_check(ccx, vs, id, hint);
 3737  
 3738      // cache so that ty::enum_variants won't repeat this work
 3739      ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
 3740  
 3741      check_representable(ccx.tcx, sp, id, "enum");
 3742  
 3743      // Check that it is possible to instantiate this enum:
 3744      //
 3745      // This *sounds* like the same that as representable, but it's
 3746      // not.  See def'n of `check_instantiable()` for details.
 3747      check_instantiable(ccx.tcx, sp, id);
 3748  }
 3749  
 3750  pub fn lookup_def(fcx: &FnCtxt, spSpan, idast::NodeId) -> ast::Def {
 3751      lookup_def_ccx(fcx.ccx, sp, id)
 3752  }
 3753  
 3754  // Returns the type parameter count and the type for the given definition.
 3755  pub fn ty_param_bounds_and_ty_for_def(fcx: &FnCtxt,
 3756                                        spSpan,
 3757                                        defnast::Def)
 3758                                     -> ty_param_bounds_and_ty {
 3759      match defn {
 3760        ast::DefArg(nid, _) | ast::DefLocal(nid, _) |
 3761        ast::DefBinding(nid, _) => {
 3762            let typ = fcx.local_ty(sp, nid);
 3763            return no_params(typ);
 3764        }
 3765        ast::DefFn(id, _) | ast::DefStaticMethod(id, _, _) |
 3766        ast::DefStatic(id, _) | ast::DefVariant(_, id, _) |
 3767        ast::DefStruct(id) => {
 3768          return ty::lookup_item_type(fcx.ccx.tcx, id);
 3769        }
 3770        ast::DefUpvar(_, inner, _, _) => {
 3771          return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
 3772        }
 3773        ast::DefTrait(_) |
 3774        ast::DefTy(_) |
 3775        ast::DefPrimTy(_) |
 3776        ast::DefTyParam(..)=> {
 3777          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type");
 3778        }
 3779        ast::DefMod(..) | ast::DefForeignMod(..) => {
 3780          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found module");
 3781        }
 3782        ast::DefUse(..) => {
 3783          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found use");
 3784        }
 3785        ast::DefRegion(..) => {
 3786          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found region");
 3787        }
 3788        ast::DefTyParamBinder(..) => {
 3789          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found type parameter");
 3790        }
 3791        ast::DefLabel(..) => {
 3792          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found label");
 3793        }
 3794        ast::DefSelfTy(..) => {
 3795          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found self ty");
 3796        }
 3797        ast::DefMethod(..) => {
 3798          fcx.ccx.tcx.sess.span_bug(sp, "expected value but found method");
 3799        }
 3800      }
 3801  }
 3802  
 3803  // Instantiates the given path, which must refer to an item with the given
 3804  // number of type parameters and type.
 3805  pub fn instantiate_path(fcx: &FnCtxt,
 3806                          pth: &ast::Path,
 3807                          tptty_param_bounds_and_ty,
 3808                          defast::Def,
 3809                          spanSpan,
 3810                          node_idast::NodeId) {
 3811      debug!(">>> instantiate_path");
 3812  
 3813      let ty_param_count = tpt.generics.type_param_defs().len();
 3814      let ty_param_req = tpt.generics.type_param_defs().iter()
 3815                                                     .take_while(|x| x.default.is_none())
 3816                                                     .len();
 3817      let mut ty_substs_len = 0;
 3818      for segment in pth.segments.iter() {
 3819          ty_substs_len += segment.types.len()
 3820      }
 3821  
 3822      debug!("tpt={} ty_param_count={:?} ty_substs_len={:?}",
 3823             tpt.repr(fcx.tcx()),
 3824             ty_param_count,
 3825             ty_substs_len);
 3826  
 3827      // determine the region parameters, using the value given by the user
 3828      // (if any) and otherwise using a fresh region variable
 3829      let num_expected_regions = tpt.generics.region_param_defs().len();
 3830      let num_supplied_regions = pth.segments.last().unwrap().lifetimes.len();
 3831      let regions = if num_expected_regions == num_supplied_regions {
 3832          OwnedSlice::from_vec(pth.segments.last().unwrap().lifetimes.iter().map(
 3833              |l| ast_region_to_region(fcx.tcx(), l)).collect())
 3834      } else {
 3835          if num_supplied_regions != 0 {
 3836              fcx.ccx.tcx.sess.span_err(
 3837                  span,
 3838                  format!("expected {nexpected, plural, =1{# lifetime parameter} \
 3839                                                     other{# lifetime parameters}}, \
 3840                           found {nsupplied, plural, =1{# lifetime parameter} \
 3841                                                  other{# lifetime parameters}}",
 3842                          nexpected = num_expected_regions,
 3843                          nsupplied = num_supplied_regions));
 3844          }
 3845  
 3846          fcx.infcx().region_vars_for_defs(span, tpt.generics.region_param_defs.as_slice())
 3847      };
 3848      let regions = ty::NonerasedRegions(regions);
 3849  
 3850      // Special case: If there is a self parameter, omit it from the list of
 3851      // type parameters.
 3852      //
 3853      // Here we calculate the "user type parameter count", which is the number
 3854      // of type parameters actually manifest in the AST. This will differ from
 3855      // the internal type parameter count when there are self types involved.
 3856      let (user_ty_param_count, user_ty_param_req, self_parameter_index) = match def {
 3857          ast::DefStaticMethod(_, provenance @ ast::FromTrait(_), _) => {
 3858              let generics = generics_of_static_method_container(fcx.ccx.tcx,
 3859                                                                 provenance);
 3860              (ty_param_count - 1, ty_param_req - 1, Some(generics.type_param_defs().len()))
 3861          }
 3862          _ => (ty_param_count, ty_param_req, None),
 3863      };
 3864  
 3865      // determine values for type parameters, using the values given by
 3866      // the user (if any) and otherwise using fresh type variables
 3867      let (tps, regions) = if ty_substs_len == 0 {
 3868          (fcx.infcx().next_ty_vars(ty_param_count), regions)
 3869      } else if ty_param_count == 0 {
 3870          fcx.ccx.tcx.sess.span_err
 3871              (span, "this item does not take type parameters");
 3872          (fcx.infcx().next_ty_vars(ty_param_count), regions)
 3873      } else if ty_substs_len > user_ty_param_count {
 3874          let expected = if user_ty_param_req < user_ty_param_count {
 3875              "expected at most"
 3876          } else {
 3877              "expected"
 3878          };
 3879          fcx.ccx.tcx.sess.span_err
 3880              (span,
 3881               format!("too many type parameters provided: {} {}, found {}",
 3882                    expected, user_ty_param_count, ty_substs_len));
 3883          (fcx.infcx().next_ty_vars(ty_param_count), regions)
 3884      } else if ty_substs_len < user_ty_param_req {
 3885          let expected = if user_ty_param_req < user_ty_param_count {
 3886              "expected at least"
 3887          } else {
 3888              "expected"
 3889          };
 3890          fcx.ccx.tcx.sess.span_err
 3891              (span,
 3892               format!("not enough type parameters provided: {} {}, found {}",
 3893                    expected, user_ty_param_req, ty_substs_len));
 3894          (fcx.infcx().next_ty_vars(ty_param_count), regions)
 3895      } else {
 3896          if ty_substs_len > user_ty_param_req
 3897              && !fcx.tcx().sess.features.default_type_params.get() {
 3898              fcx.tcx().sess.span_err(pth.span, "default type parameters are \
 3899                                                 experimental and possibly buggy");
 3900              fcx.tcx().sess.span_note(pth.span, "add #![feature(default_type_params)] \
 3901                                                  to the crate attributes to enable");
 3902          }
 3903  
 3904          // Build up the list of type parameters, inserting the self parameter
 3905          // at the appropriate position.
 3906          let mut tps = Vec::new();
 3907          let mut pushed = false;
 3908          for (i, ty) in pth.segments.iter()
 3909                                     .flat_map(|segment| segment.types.iter())
 3910                                     .map(|&ast_type| fcx.to_ty(ast_type))
 3911                                     .enumerate() {
 3912              match self_parameter_index {
 3913                  Some(index) if index == i => {
 3914                      tps.push(*fcx.infcx().next_ty_vars(1).get(0));
 3915                      pushed = true;
 3916                  }
 3917                  _ => {}
 3918              }
 3919              tps.push(ty)
 3920          }
 3921  
 3922          let mut substs = substs {
 3923              regions: regions,
 3924              self_ty: None,
 3925              tps: tps
 3926          };
 3927  
 3928          let defaults = tpt.generics.type_param_defs().iter()
 3929                            .enumerate().filter_map(|(i, x)| {
 3930              match self_parameter_index {
 3931                  Some(index) if index == i => None,
 3932                  _ => Some(x.default)
 3933              }
 3934          });
 3935          for (i, default) in defaults.skip(ty_substs_len).enumerate() {
 3936              match self_parameter_index {
 3937                  Some(index) if index == i + ty_substs_len => {
 3938                      substs.tps.push(*fcx.infcx().next_ty_vars(1).get(0));
 3939                      pushed = true;
 3940                  }
 3941                  _ => {}
 3942              }
 3943              match default {
 3944                  Some(default) => {
 3945                      let ty = default.subst_spanned(fcx.tcx(), &substs, Some(span));
 3946                      substs.tps.push(ty);
 3947                  }
 3948                  None => {
 3949                      fcx.tcx().sess.span_bug(span,
 3950                          "missing default for a not explicitely provided type param")
 3951                  }
 3952              }
 3953          }
 3954  
 3955          // If the self parameter goes at the end, insert it there.
 3956          if !pushed && self_parameter_index.is_some() {
 3957              substs.tps.push(*fcx.infcx().next_ty_vars(1).get(0))
 3958          }
 3959  
 3960          assert_eq!(substs.tps.len(), ty_param_count)
 3961  
 3962          let substs {tps, regions, ..} = substs;
 3963          (tps, regions)
 3964      };
 3965  
 3966      fcx.write_ty_substs(node_id, tpt.ty, substs {
 3967          regions: regions,
 3968          self_ty: None,
 3969          tps: tps
 3970      });
 3971  
 3972      debug!("<<<");
 3973  }
 3974  
 3975  // Resolves `typ` by a single level if `typ` is a type variable.  If no
 3976  // resolution is possible, then an error is reported.
 3977  pub fn structurally_resolved_type(fcx: &FnCtxt, spSpan, tpty::t) -> ty::t {
 3978      match infer::resolve_type(fcx.infcx(), tp, force_tvar) {
 3979          Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
 3980          _ => {
 3981              fcx.type_error_message(sp, |_actual| {
 3982                  "the type of this value must be known in this context".to_owned()
 3983              }, tp, None);
 3984              demand::suptype(fcx, sp, ty::mk_err(), tp);
 3985              tp
 3986          }
 3987      }
 3988  }
 3989  
 3990  // Returns the one-level-deep structure of the given type.
 3991  pub fn structure_of<'a>(fcx: &FnCtxt, spSpan, typty::t)
 3992                          -> &'a ty::sty {
 3993      &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
 3994  }
 3995  
 3996  pub fn type_is_integral(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 3997      let typ_s = structurally_resolved_type(fcx, sp, typ);
 3998      return ty::type_is_integral(typ_s);
 3999  }
 4000  
 4001  pub fn type_is_uint(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 4002      let typ_s = structurally_resolved_type(fcx, sp, typ);
 4003      return ty::type_is_uint(typ_s);
 4004  }
 4005  
 4006  pub fn type_is_scalar(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 4007      let typ_s = structurally_resolved_type(fcx, sp, typ);
 4008      return ty::type_is_scalar(typ_s);
 4009  }
 4010  
 4011  pub fn type_is_char(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 4012      let typ_s = structurally_resolved_type(fcx, sp, typ);
 4013      return ty::type_is_char(typ_s);
 4014  }
 4015  
 4016  pub fn type_is_bare_fn(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 4017      let typ_s = structurally_resolved_type(fcx, sp, typ);
 4018      return ty::type_is_bare_fn(typ_s);
 4019  }
 4020  
 4021  pub fn type_is_unsafe_ptr(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 4022      let typ_s = structurally_resolved_type(fcx, sp, typ);
 4023      return ty::type_is_unsafe_ptr(typ_s);
 4024  }
 4025  
 4026  pub fn type_is_region_ptr(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 4027      let typ_s = structurally_resolved_type(fcx, sp, typ);
 4028      return ty::type_is_region_ptr(typ_s);
 4029  }
 4030  
 4031  pub fn type_is_c_like_enum(fcx: &FnCtxt, spSpan, typty::t) -> bool {
 4032      let typ_s = structurally_resolved_type(fcx, sp, typ);
 4033      return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
 4034  }
 4035  
 4036  pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
 4037                               e: &ast::Expr,
 4038                               vast::ExprVstore,
 4039                               mk_inner: || -> ty::mt)
 4040                               -> ty::t {
 4041      match v {
 4042          ast::ExprVstoreUniq => ty::mk_uniq(fcx.ccx.tcx, mk_inner().ty),
 4043          ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
 4044              match e.node {
 4045                  ast::ExprLit(..) => {
 4046                      // string literals and *empty slices* live in static memory
 4047                      ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
 4048                  }
 4049                  ast::ExprVec(ref elements) if elements.len() == 0 => {
 4050                      // string literals and *empty slices* live in static memory
 4051                      ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner())
 4052                  }
 4053                  ast::ExprRepeat(..) |
 4054                  ast::ExprVec(..) => {
 4055                      // vector literals are temporaries on the stack
 4056                      match fcx.tcx().region_maps.temporary_scope(e.id) {
 4057                          Some(scope) => ty::mk_rptr(fcx.ccx.tcx, ty::ReScope(scope), mk_inner()),
 4058                          None => ty::mk_rptr(fcx.ccx.tcx, ty::ReStatic, mk_inner()),
 4059                      }
 4060                  }
 4061                  _ => {
 4062                      fcx.ccx.tcx.sess.span_bug(
 4063                          e.span, format!("vstore with unexpected contents"))
 4064                  }
 4065              }
 4066          }
 4067      }
 4068  }
 4069  
 4070  // Returns true if b contains a break that can exit from b
 4071  pub fn may_break(cx: &ty::ctxt, idast::NodeId, bast::P<ast::Block>) -> bool {
 4072      // First: is there an unlabeled break immediately
 4073      // inside the loop?
 4074      (loop_query(b, |e| {
 4075          match *e {
 4076              ast::ExprBreak(_) => true,
 4077              _ => false
 4078          }
 4079      })) ||
 4080     // Second: is there a labeled break with label
 4081     // <id> nested anywhere inside the loop?
 4082      (block_query(b, |e| {
 4083          match e.node {
 4084              ast::ExprBreak(Some(_)) => {
 4085                  match cx.def_map.borrow().find(&e.id) {
 4086                      Some(&ast::DefLabel(loop_id)) if id == loop_id => true,
 4087                      _ => false,
 4088                  }
 4089              }
 4090              _ => false
 4091          }}))
 4092  }
 4093  
 4094  pub fn check_bounds_are_used(ccx: &CrateCtxt,
 4095                               spanSpan,
 4096                               tps: &OwnedSlice<ast::TyParam>,
 4097                               tyty::t) {
 4098      debug!("check_bounds_are_used(n_tps={}, ty={})",
 4099             tps.len(), ppaux::ty_to_str(ccx.tcx, ty));
 4100  
 4101      // make a vector of booleans initially false, set to true when used
 4102      if tps.len() == 0u { return; }
 4103      let mut tps_used = Vec::from_elem(tps.len(), false);
 4104  
 4105      ty::walk_ty(ty, |t| {
 4106              match ty::get(t).sty {
 4107                  ty::ty_param(param_ty {idx, ..}) => {
 4108                      debug!("Found use of ty param \\#{}", idx);
 4109                      *tps_used.get_mut(idx) = true;
 4110                  }
 4111                  _ => ()
 4112              }
 4113          });
 4114  
 4115      for (i, b) in tps_used.iter().enumerate() {
 4116          if !*b {
 4117              ccx.tcx.sess.span_err(
 4118                  span, format!("type parameter `{}` is unused",
 4119                                token::get_ident(tps.get(i).ident)));
 4120          }
 4121      }
 4122  }
 4123  
 4124  pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
 4125      fn param(ccx&CrateCtxt, nuint) -> ty::t {
 4126          ty::mk_param(ccx.tcx, n, local_def(0))
 4127      }
 4128  
 4129      let tcx = ccx.tcx;
 4130      let name = token::get_ident(it.ident);
 4131      let (n_tps, inputs, output) = if name.get().starts_with("atomic_") {
 4132          let split : Vec<&str> = name.get().split('_').collect();
 4133          assert!(split.len() >= 2, "Atomic intrinsic not correct format");
 4134  
 4135          //We only care about the operation here
 4136          match *split.get(1) {
 4137              "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
 4138                                  param(ccx, 0),
 4139                                  param(ccx, 0)),
 4140                          param(ccx, 0)),
 4141              "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
 4142                         param(ccx, 0)),
 4143              "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
 4144                          ty::mk_nil()),
 4145  
 4146              "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
 4147              "min"  | "umax" | "umin" => {
 4148                  (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
 4149                   param(ccx, 0))
 4150              }
 4151              "fence" => {
 4152                  (0, Vec::new(), ty::mk_nil())
 4153              }
 4154              op => {
 4155                  tcx.sess.span_err(it.span,
 4156                                    format!("unrecognized atomic operation function: `{}`",
 4157                                         op));
 4158                  return;
 4159              }
 4160          }
 4161  
 4162      } else {
 4163          match name.get() {
 4164              "abort" => (0, Vec::new(), ty::mk_bot()),
 4165              "breakpoint" => (0, Vec::new(), ty::mk_nil()),
 4166              "size_of" |
 4167              "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
 4168              "init" => (1u, Vec::new(), param(ccx, 0u)),
 4169              "uninit" => (1u, Vec::new(), param(ccx, 0u)),
 4170              "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
 4171              "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
 4172              "move_val_init" => {
 4173                  (1u,
 4174                   vec!(
 4175                      ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
 4176                      param(ccx, 0u)
 4177                    ),
 4178                 ty::mk_nil())
 4179              }
 4180              "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
 4181              "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
 4182  
 4183              "get_tydesc" => {
 4184                let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
 4185                    Ok(t) => t,
 4186                    Err(s) => { tcx.sess.span_fatal(it.span, s); }
 4187                };
 4188                let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
 4189                    ty: tydesc_ty,
 4190                    mutbl: ast::MutImmutable
 4191                });
 4192                (1u, Vec::new(), td_ptr)
 4193              }
 4194              "type_id" => {
 4195                  let langid = ccx.tcx.lang_items.require(TypeIdLangItem);
 4196                  match langid {
 4197                      Ok(did) => (1u, Vec::new(), ty::mk_struct(ccx.tcx, did, substs {
 4198                                                   self_ty: None,
 4199                                                   tps: Vec::new(),
 4200                                                   regions: ty::NonerasedRegions(OwnedSlice::empty())
 4201                                                   }) ),
 4202                      Err(msg) => { tcx.sess.span_fatal(it.span, msg); }
 4203                  }
 4204              },
 4205              "visit_tydesc" => {
 4206                let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
 4207                    Ok(t) => t,
 4208                    Err(s) => { tcx.sess.span_fatal(it.span, s); }
 4209                };
 4210                let region = ty::ReLateBound(it.id, ty::BrAnon(0));
 4211                let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
 4212                    Ok((_, vot)) => vot,
 4213                    Err(s) => { tcx.sess.span_fatal(it.span, s); }
 4214                };
 4215  
 4216                let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
 4217                    ty: tydesc_ty,
 4218                    mutbl: ast::MutImmutable
 4219                });
 4220                (0, vec!( td_ptr, visitor_object_ty ), ty::mk_nil())
 4221              }
 4222              "offset" => {
 4223                (1,
 4224                 vec!(
 4225                    ty::mk_ptr(tcx, ty::mt {
 4226                        ty: param(ccx, 0),
 4227                        mutbl: ast::MutImmutable
 4228                    }),
 4229                    ty::mk_int()
 4230                 ),
 4231                 ty::mk_ptr(tcx, ty::mt {
 4232                     ty: param(ccx, 0),
 4233                     mutbl: ast::MutImmutable
 4234                 }))
 4235              }
 4236              "copy_memory" | "copy_nonoverlapping_memory" |
 4237              "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
 4238                (1,
 4239                 vec!(
 4240                    ty::mk_ptr(tcx, ty::mt {
 4241                        ty: param(ccx, 0),
 4242                        mutbl: ast::MutMutable
 4243                    }),
 4244                    ty::mk_ptr(tcx, ty::mt {
 4245                        ty: param(ccx, 0),
 4246                        mutbl: ast::MutImmutable
 4247                    }),
 4248                    ty::mk_uint()
 4249                 ),
 4250                 ty::mk_nil())
 4251              }
 4252              "set_memory" | "volatile_set_memory" => {
 4253                (1,
 4254                 vec!(
 4255                    ty::mk_ptr(tcx, ty::mt {
 4256                        ty: param(ccx, 0),
 4257                        mutbl: ast::MutMutable
 4258                    }),
 4259                    ty::mk_u8(),
 4260                    ty::mk_uint()
 4261                 ),
 4262                 ty::mk_nil())
 4263              }
 4264              "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4265              "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4266              "powif32" => {
 4267                 (0,
 4268                  vec!( ty::mk_f32(), ty::mk_i32() ),
 4269                  ty::mk_f32())
 4270              }
 4271              "powif64" => {
 4272                 (0,
 4273                  vec!( ty::mk_f64(), ty::mk_i32() ),
 4274                  ty::mk_f64())
 4275              }
 4276              "sinf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4277              "sinf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4278              "cosf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4279              "cosf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4280              "powf32" => {
 4281                 (0,
 4282                  vec!( ty::mk_f32(), ty::mk_f32() ),
 4283                  ty::mk_f32())
 4284              }
 4285              "powf64" => {
 4286                 (0,
 4287                  vec!( ty::mk_f64(), ty::mk_f64() ),
 4288                  ty::mk_f64())
 4289              }
 4290              "expf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4291              "expf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4292              "exp2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4293              "exp2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4294              "logf32"   => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4295              "logf64"   => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4296              "log10f32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4297              "log10f64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4298              "log2f32"  => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4299              "log2f64"  => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4300              "fmaf32" => {
 4301                  (0,
 4302                   vec!( ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ),
 4303                   ty::mk_f32())
 4304              }
 4305              "fmaf64" => {
 4306                  (0,
 4307                   vec!( ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ),
 4308                   ty::mk_f64())
 4309              }
 4310              "fabsf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4311              "fabsf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4312              "copysignf32"  => (0, vec!( ty::mk_f32(), ty::mk_f32() ), ty::mk_f32()),
 4313              "copysignf64"  => (0, vec!( ty::mk_f64(), ty::mk_f64() ), ty::mk_f64()),
 4314              "floorf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4315              "floorf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4316              "ceilf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4317              "ceilf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4318              "truncf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4319              "truncf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4320              "rintf32"      => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4321              "rintf64"      => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4322              "nearbyintf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4323              "nearbyintf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4324              "roundf32"     => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
 4325              "roundf64"     => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
 4326              "ctpop8"       => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
 4327              "ctpop16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
 4328              "ctpop32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
 4329              "ctpop64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
 4330              "ctlz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
 4331              "ctlz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
 4332              "ctlz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
 4333              "ctlz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
 4334              "cttz8"        => (0, vec!( ty::mk_u8()  ), ty::mk_u8()),
 4335              "cttz16"       => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
 4336              "cttz32"       => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
 4337              "cttz64"       => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
 4338              "bswap16"      => (0, vec!( ty::mk_u16() ), ty::mk_u16()),
 4339              "bswap32"      => (0, vec!( ty::mk_u32() ), ty::mk_u32()),
 4340              "bswap64"      => (0, vec!( ty::mk_u64() ), ty::mk_u64()),
 4341  
 4342              "volatile_load" =>
 4343                  (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
 4344              "volatile_store" =>
 4345                  (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
 4346  
 4347              "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
 4348                  (0, vec!(ty::mk_i8(), ty::mk_i8()),
 4349                  ty::mk_tup(tcx, vec!(ty::mk_i8(), ty::mk_bool()))),
 4350  
 4351              "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
 4352                  (0, vec!(ty::mk_i16(), ty::mk_i16()),
 4353                  ty::mk_tup(tcx, vec!(ty::mk_i16(), ty::mk_bool()))),
 4354  
 4355              "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
 4356                  (0, vec!(ty::mk_i32(), ty::mk_i32()),
 4357                  ty::mk_tup(tcx, vec!(ty::mk_i32(), ty::mk_bool()))),
 4358  
 4359              "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
 4360                  (0, vec!(ty::mk_i64(), ty::mk_i64()),
 4361                  ty::mk_tup(tcx, vec!(ty::mk_i64(), ty::mk_bool()))),
 4362  
 4363              "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
 4364                  (0, vec!(ty::mk_u8(), ty::mk_u8()),
 4365                  ty::mk_tup(tcx, vec!(ty::mk_u8(), ty::mk_bool()))),
 4366  
 4367              "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
 4368                  (0, vec!(ty::mk_u16(), ty::mk_u16()),
 4369                  ty::mk_tup(tcx, vec!(ty::mk_u16(), ty::mk_bool()))),
 4370  
 4371              "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
 4372                  (0, vec!(ty::mk_u32(), ty::mk_u32()),
 4373                  ty::mk_tup(tcx, vec!(ty::mk_u32(), ty::mk_bool()))),
 4374  
 4375              "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
 4376                  (0, vec!(ty::mk_u64(), ty::mk_u64()),
 4377                  ty::mk_tup(tcx, vec!(ty::mk_u64(), ty::mk_bool()))),
 4378  
 4379              ref other => {
 4380                  tcx.sess.span_err(it.span,
 4381                                    format!("unrecognized intrinsic function: `{}`",
 4382                                         *other));
 4383                  return;
 4384              }
 4385          }
 4386      };
 4387      let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
 4388          fn_style: ast::UnsafeFn,
 4389          abi: abi::RustIntrinsic,
 4390          sig: FnSig {binder_id: it.id,
 4391                      inputs: inputs,
 4392                      output: output,
 4393                      variadic: false}
 4394      });
 4395      let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
 4396      let i_n_tps = i_ty.generics.type_param_defs().len();
 4397      if i_n_tps != n_tps {
 4398          tcx.sess.span_err(it.span, format!("intrinsic has wrong number \
 4399                                           of type parameters: found {}, \
 4400                                           expected {}", i_n_tps, n_tps));
 4401      } else {
 4402          require_same_types(
 4403              tcx, None, false, it.span, i_ty.ty, fty,
 4404              || format!("intrinsic has wrong type: \
 4405                        expected `{}`",
 4406                       ppaux::ty_to_str(ccx.tcx, fty)));
 4407      }
 4408  }


librustc/middle/typeck/check/mod.rs:1466:1-1466:1 -fn- definition:
fn check_expr(fcx: &FnCtxt, expr: &ast::Expr)  {
    check_expr_with_unifier(fcx, expr, None, NoPreference, || ())
}
references:- 14
1899:         // that they appear in call position.
1900:         check_expr(fcx, f);
--
3497:                            declty: ty::t) {
3498:     check_expr(fcx, e);
3499:     let cty = fcx.expr_ty(e);
librustc/middle/typeck/check/_match.rs:
75:         }
76:         check_expr(fcx, arm.body);
77:         let bty = fcx.node_ty(arm.body.id);
librustc/middle/typeck/check/mod.rs:
1857:             for arg in args.iter().skip(expected_arg_count) {
1858:                 check_expr(fcx, *arg);


librustc/middle/typeck/check/mod.rs:2416:4-2416:4 -fn- definition:
    fn check_struct_or_variant_fields(fcx: &FnCtxt,
                                      struct_ty: ty::t,
                                      span: Span,
references:- 2
2587:         let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
2588:         check_struct_or_variant_fields(fcx,
2589:                                        enum_type,


librustc/middle/typeck/check/mod.rs:1470:1-1470:1 -fn- definition:
fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
                               lvalue_pref: LvaluePreference)  {
    check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
references:- 5
2939:       ast::ExprAssign(lhs, rhs) => {
2940:         check_expr_with_lvalue_pref(fcx, lhs, PreferMutLvalue);
--
3241:       ast::ExprIndex(base, idx) => {
3242:           check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
3243:           check_expr(fcx, idx);


librustc/middle/typeck/check/mod.rs:1356:1-1356:1 -fn- definition:
fn try_overloaded_deref(fcx: &FnCtxt,
                        span: Span,
                        method_call: Option<MethodCall>,
references:- 2
1335:                     expr_id.map(|id| MethodCall::autoderef(id, autoderefs as u32));
1336:                 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
1337:             }
--
2806:                         Some(mt) => mt.ty,
2807:                         None => match try_overloaded_deref(fcx, expr.span,
2808:                                                            Some(MethodCall::expr(expr.id)),


librustc/middle/typeck/check/mod.rs:344:1-344:1 -fn- definition:
fn check_bare_fn(ccx: &CrateCtxt,
                 decl: &ast::FnDecl,
                 body: &ast::Block,
references:- 2
668:         check_bare_fn(ccx, decl, body, it.id, fn_tpt.ty, param_env);
669:       }
--
780:     check_bare_fn(ccx, method.decl, method.body, method.id, fty, param_env);
781: }


librustc/middle/typeck/check/mod.rs:3976:54-3976:54 -fn- definition:
// resolution is possible, then an error is reported.
pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
    match infer::resolve_type(fcx.infcx(), tp, force_tvar) {
references:- 21
2101:         // Callee does bot / err checking
2102:         let lhs_t = structurally_resolved_type(fcx, lhs.span,
2103:                                                fcx.expr_ty(lhs));
--
4011: pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4012:     let typ_s = structurally_resolved_type(fcx, sp, typ);
4013:     return ty::type_is_char(typ_s);
--
4016: pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4017:     let typ_s = structurally_resolved_type(fcx, sp, typ);
4018:     return ty::type_is_bare_fn(typ_s);
--
4026: pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4027:     let typ_s = structurally_resolved_type(fcx, sp, typ);
4028:     return ty::type_is_region_ptr(typ_s);
--
4031: pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
4032:     let typ_s = structurally_resolved_type(fcx, sp, typ);
4033:     return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
librustc/middle/typeck/check/vtable.rs:
546:               // e.g.: `&x as &Trait` or `box x as Box<Trait>`
547:               let ty = structurally_resolved_type(fcx, ex.span,
548:                                                   fcx.expr_ty(src));
librustc/middle/typeck/check/mod.rs:
3079:                     let t1 = structurally_resolved_type(fcx, e.span, t_1);
3080:                     let te = structurally_resolved_type(fcx, e.span, t_e);
3081:                     let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);


librustc/middle/typeck/check/mod.rs:2223:4-2223:4 -fn- definition:
    fn check_user_unop(fcx: &FnCtxt,
                       op_str: &str,
                       mname: &str,
references:- 2
2850:                          ty::type_is_fp(oprnd_t)) {
2851:                         oprnd_t = check_user_unop(fcx, "-", "neg",
2852:                                                   tcx.lang_items.neg_trait(),


librustc/middle/typeck/check/mod.rs:171:19-171:19 -enum- definition:
pub enum FnKind {
    // A do-closure.
    DoBlock,
references:- 5
172: pub enum FnKind {
--
254:     // function return type.
255:     fn_kind: FnKind,
--
2262:                      body: ast::P<ast::Block>,
2263:                      fn_kind: FnKind,
2264:                      expected: Option<ty::t>) {


librustc/middle/typeck/check/mod.rs:2047:4-2047:4 -fn- definition:
    fn lookup_op_method(fcx: &FnCtxt,
                        op_ex: &ast::Expr,
                        self_t: ty::t,
references:- 3
2229:                        rhs_t: ty::t) -> ty::t {
2230:        lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
2231:                         trait_did, [rhs_expr], DontAutoderefReceiver, || {
--
3263:                                                                 raw_base_t);
3264:                       let ret_ty = lookup_op_method(fcx,
3265:                                                     expr,


librustc/middle/typeck/check/mod.rs:584:1-584:1 -fn- definition:
fn check_fields_sized(tcx: &ty::ctxt,
                      struct_def: &ast::StructDef) {
    let len = struct_def.fields.len();
references:- 2
635:         ast::ItemStruct(..) => {
636:             check_fields_sized(ccx.tcx, ccx.tcx.map.expect_struct(it.id));
637:         }
--
3614:             },
3615:             ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, struct_def),
3616:             _ => {}


librustc/middle/typeck/check/mod.rs:1300:1-1300:1 -enum- definition:
pub enum LvaluePreference {
    PreferMutLvalue,
    NoPreference
references:- 6
1307:                     expr_id: Option<ast::NodeId>,
1308:                     mut lvalue_pref: LvaluePreference,
1309:                     should_stop: |ty::t, uint| -> Option<T>)
--
1471: fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
1472:                                lvalue_pref: LvaluePreference)  {
1473:     check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
--
1701:                            expected: Option<ty::t>,
1702:                            lvalue_pref: LvaluePreference,
1703:                            unifier: ||) {
--
2347:                    expr: &ast::Expr,
2348:                    lvalue_pref: LvaluePreference,
2349:                    base: &ast::Expr,


librustc/middle/typeck/check/mod.rs:1526:23-1526:23 -fn- definition:
// method's container.
fn generics_of_static_method_container(type_context: &ty::ctxt,
                                       provenance: ast::MethodProvenance)
references:- 2
1586:             let generics =
1587:                 generics_of_static_method_container(function_context.ccx.tcx,
1588:                                                     provenance);
--
3857:         ast::DefStaticMethod(_, provenance @ ast::FromTrait(_), _) => {
3858:             let generics = generics_of_static_method_container(fcx.ccx.tcx,
3859:                                                                provenance);


librustc/middle/typeck/check/mod.rs:1706:4-1706:4 -fn- definition:
    fn check_method_argument_types(
        fcx: &FnCtxt,
        sp: Span,
references:- 3
2077:                 let expected_ty = ty::mk_err();
2078:                 check_method_argument_types(fcx, op_ex.span,
2079:                                             expected_ty, op_ex,


librustc/middle/typeck/check/mod.rs:4035:1-4035:1 -fn- definition:
pub fn ast_expr_vstore_to_ty(fcx: &FnCtxt,
                             e: &ast::Expr,
                             v: ast::ExprVstore,
references:- 2
2649:                     } else {
2650:                         ast_expr_vstore_to_ty(fcx, ev, vst, ||
2651:                             ty::mt{ ty: ty::mk_vec(tcx,


librustc/middle/typeck/check/mod.rs:1454:1-1454:1 -fn- definition:
fn check_expr_with_opt_hint(fcx: &FnCtxt, expr: &ast::Expr,
                            expected: Option<ty::t>)  {
    check_expr_with_unifier(fcx, expr, expected, NoPreference, || ())
references:- 3
2020:                 let then_ty = fcx.node_ty(then_blk.id);
2021:                 check_expr_with_opt_hint(fcx, else_expr, expected);
2022:                 let else_ty = fcx.expr_ty(else_expr);
--
3204:             };
3205:             check_expr_with_opt_hint(fcx, *e, opt_hint);
3206:             let t = fcx.expr_ty(*e);
--
3466:             }
3467:             check_expr_with_opt_hint(fcx, e, expected);
3468:               let ety = fcx.expr_ty(e);


librustc/middle/typeck/check/mod.rs:743:1-743:1 -fn- definition:
fn check_method_body(ccx: &CrateCtxt,
                     item_generics: &ty::Generics,
                     self_bound: Option<Rc<ty::TraitRef>>,
references:- 2
702:                 Provided(m) => {
703:                     check_method_body(ccx, &trait_def.generics,
704:                                       Some(trait_def.trait_ref.clone()), m);


librustc/middle/typeck/check/mod.rs:1738:4-1738:4 -fn- definition:
    fn check_argument_types(fcx: &FnCtxt,
                            sp: Span,
                            fn_inputs: &[ty::t],
references:- 3
1935:         // Call the generic checker.
1936:         check_argument_types(fcx, call_expr.span, fn_sig.inputs.as_slice(), f,
1937:                              args, DontDerefArgs, fn_sig.variadic);


librustc/middle/typeck/check/mod.rs:3749:1-3749:1 -fn- definition:
pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> ast::Def {
    lookup_def_ccx(fcx.ccx, sp, id)
}
references:- 4
2680:                   // places: the exchange heap and the managed heap.
2681:                   let definition = lookup_def(fcx, path.span, place.id);
2682:                   let def_id = ast_util::def_id_of_def(definition);
--
2898:       ast::ExprPath(ref pth) => {
2899:         let defn = lookup_def(fcx, pth.span, id);
librustc/middle/typeck/check/_match.rs:
185:             // Lookup the struct ctor def id
186:             let s_def = lookup_def(pcx.fcx, pat.span, pat.id);
187:             let s_def_id = ast_util::def_id_of_def(s_def);


librustc/middle/typeck/check/mod.rs:3509:26-3509:26 -fn- definition:
/// `check_instantiable`.
pub fn check_representable(tcx: &ty::ctxt,
                           sp: Span,
references:- 2
613:     check_representable(tcx, span, id, "struct");
614:     check_instantiable(tcx, span, id);
--
3741:     check_representable(ccx.tcx, sp, id, "enum");


librustc/middle/typeck/check/mod.rs:1889:4-1889:4 -fn- definition:
    fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
        fcx.write_ty(call_expr.id, output);
    }
references:- 2
2003:         write_call(fcx, expr, ret_ty);
2004:     }


librustc/middle/typeck/check/mod.rs:2258:4-2258:4 -fn- definition:
    fn check_expr_fn(fcx: &FnCtxt,
                     expr: &ast::Expr,
                     store: ty::TraitStore,
references:- 2
3005:       ast::ExprProc(decl, body) => {
3006:         check_expr_fn(fcx,
3007:                       expr,


librustc/middle/typeck/check/mod.rs:3990:59-3990:59 -fn- definition:
// Returns the one-level-deep structure of the given type.
pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
                        -> &'a ty::sty {
references:- 6
1905:         // Extract the function signature from `in_fty`.
1906:         let fn_sty = structure_of(fcx, f.span, fn_ty);
librustc/middle/typeck/check/_match.rs:
520:         // Grab the class data that we care about.
521:         let structure = structure_of(fcx, pat.span, expected);
522:         let mut error_happened = false;
--
642:         let (elt_type, region_var, mutbl) = match *structure_of(fcx,
643:                                                                 pat.span,
--
705:     };
706:     match *structure_of(fcx, span, expected) {
707:         ty::ty_uniq(e_inner) if pointer_kind == Send => {


librustc/middle/typeck/check/mod.rs:1885:4-1885:4 -fn- definition:
    fn err_args(len: uint) -> Vec<ty::t> {
        Vec::from_fn(len, |_| ty::mk_err())
    }
references:- 4
1786:             err_args(supplied_arg_count)
1787:         };
--
1912:             binder_id: ast::CRATE_NODE_ID,
1913:             inputs: err_args(args.len()),
1914:             output: ty::mk_err(),


librustc/middle/typeck/check/mod.rs:1450:1-1450:1 -fn- definition:
fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
    check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || ())
}
references:- 2
3172:       ast::ExprRepeat(element, count_expr) => {
3173:         check_expr_with_hint(fcx, count_expr, ty::mk_uint());
3174:         let count = ty::eval_repeat_count(fcx, count_expr);


librustc/middle/typeck/check/mod.rs:2087:4-2087:4 -fn- definition:
    fn check_binop(fcx: &FnCtxt,
                   expr: &ast::Expr,
                   op: ast::BinOp,
references:- 2
2744:       ast::ExprBinary(op, lhs, rhs) => {
2745:         check_binop(fcx, expr, op, lhs, rhs, SimpleBinop);
--
2758:       ast::ExprAssignOp(op, lhs, rhs) => {
2759:         check_binop(fcx, expr, op, lhs, rhs, BinopAssignment);


librustc/middle/typeck/check/mod.rs:180:19-180:19 -struct- definition:
pub struct FnStyleState {
    pub def: ast::NodeId,
    pub fn_style: ast::FnStyle,
references:- 10
204:                 };
205:                 FnStyleState{ def: def,
206:                              fn_style: fn_style,
--
234:     ret_ty: ty::t,
235:     ps: RefCell<FnStyleState>,


librustc/middle/typeck/check/mod.rs:3544:44-3544:44 -fn- definition:
/// is representable, but not instantiable.
pub fn check_instantiable(tcx: &ty::ctxt,
                          sp: Span,
references:- 2
3746:     // not.  See def'n of `check_instantiable()` for details.
3747:     check_instantiable(ccx.tcx, sp, id);
3748: }


librustc/middle/typeck/check/mod.rs:156:32-156:32 -struct- definition:
/// share the inherited fields.
pub struct Inherited<'a> {
    infcx: infer::InferCtxt<'a>,
references:- 7
265:            -> Inherited<'a> {
266:         Inherited {
267:             infcx: infer::new_infer_ctxt(tcx),
--
443:                 fn_kind: FnKind,
444:                 inherited: &'a Inherited<'a>) -> FnCtxt<'a>
445: {


librustc/middle/typeck/check/mod.rs:1459:1-1459:1 -fn- definition:
fn check_expr_with_opt_hint_and_lvalue_pref(fcx: &FnCtxt,
                                            expr: &ast::Expr,
                                            expected: Option<ty::t>,
references:- 3
2792:         };
2793:         check_expr_with_opt_hint_and_lvalue_pref(fcx, oprnd, exp_inner, lvalue_pref);
2794:         let mut oprnd_t = fcx.expr_ty(oprnd);
--
2935:       ast::ExprParen(a) => {
2936:         check_expr_with_opt_hint_and_lvalue_pref(fcx, a, expected, lvalue_pref);
2937:         fcx.write_ty(id, fcx.expr_ty(a));


librustc/middle/typeck/check/mod.rs:3638:8-3638:8 -fn- definition:
        fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
            match ty {
                ast::TyI8 => disr as i8 as Disr == disr,
references:- 2
3648:             attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3649:             attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3650:         }


librustc/middle/typeck/check/mod.rs:316:1-316:1 -struct- definition:
struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
    fn visit_item(&mut self, i: &ast::Item, _: ()) {
references:- 2
335: pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
336:     let mut visit = CheckItemTypesVisitor { ccx: ccx };
337:     visit::walk_crate(&mut visit, krate, ());


librustc/middle/typeck/check/mod.rs:1480:14-1480:14 -fn- definition:
// variables.
pub fn impl_self_ty(vcx: &VtableContext,
                    span: Span, // (potential) receiver for this impl
references:- 2
librustc/middle/typeck/check/method.rs:
705:             ty: impl_ty
706:         } = impl_self_ty(&vcx, span, impl_did);
librustc/middle/typeck/check/vtable.rs:
365:             ty: for_ty
366:         } = impl_self_ty(vcx, span, impl_did);
367:         match infer::mk_subty(vcx.infcx,


librustc/middle/typeck/check/mod.rs:2242:4-2242:4 -fn- definition:
    fn unpack_expected<O>(
                       fcx: &FnCtxt,
                       expected: Option<ty::t>,
references:- 4
2269:         // expected types so as to avoid capture.
2270:         let expected_sty = unpack_expected(fcx,
2271:                                            expected,
--
2860:       ast::ExprAddrOf(mutbl, oprnd) => {
2861:           let hint = unpack_expected(
2862:               fcx, expected,
--
3190:       ast::ExprTup(ref elts) => {
3191:         let flds = unpack_expected(fcx, expected, |sty| {
3192:             match *sty {


librustc/middle/typeck/check/mod.rs:1444:1-1444:1 -fn- definition:
fn check_expr_coercable_to_type(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
    check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
        demand::coerce(fcx, expr.span, expected, expr)
references:- 3
3322:     let local_ty = fcx.local_ty(init.span, nid);
3323:     check_expr_coercable_to_type(fcx, init, local_ty)
3324: }


librustc/middle/typeck/check/mod.rs:297:1-297:1 -fn- definition:
fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
    // It's kind of a kludge to manufacture a fake function context
    // and statement context, but we might as well do write the code only once
references:- 2
3486:                    id: ast::NodeId) {
3487:     let inh = blank_inherited_fields(ccx);
3488:     let rty = ty::node_id_to_type(ccx.tcx, id);
--
3677:                     let inh = blank_inherited_fields(ccx);
3678:                     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);


librustc/middle/typeck/check/mod.rs:1436:1-1436:1 -fn- definition:
pub fn check_expr_has_type(
    fcx: &FnCtxt, expr: &ast::Expr,
    expected: ty::t) {
references:- 17
3165:         for e in args.iter() {
3166:             check_expr_has_type(fcx, *e, t);
3167:         }
--
3175:         let t: ty::t = fcx.infcx().next_ty_var();
3176:         check_expr_has_type(fcx, element, t);
3177:         let element_ty = fcx.expr_ty(element);
--
3373:         // Check with expected type of ()
3374:         check_expr_has_type(fcx, expr, ty::mk_nil());
3375:         let expr_ty = fcx.expr_ty(expr);
librustc/middle/typeck/check/_match.rs:
438:       ast::PatRange(begin, end) => {
439:         check_expr_has_type(fcx, begin, expected);
440:         check_expr_has_type(fcx, end, expected);
441:         let b_ty =
librustc/middle/typeck/check/mod.rs:
2613:                     for e in args.iter() {
2614:                         check_expr_has_type(fcx, *e, t);
2615:                         let arg_t = fcx.expr_ty(*e);


librustc/middle/typeck/check/mod.rs:3804:39-3804:39 -fn- definition:
// number of type parameters and type.
pub fn instantiate_path(fcx: &FnCtxt,
                        pth: &ast::Path,
references:- 3
2902:         let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
2903:         instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
2904:       }
librustc/middle/typeck/check/_match.rs:
196:             };
197:             instantiate_path(pcx.fcx,
198:                              path,


librustc/middle/typeck/check/mod.rs:216:16-216:16 -enum- definition:
enum IsBinopAssignment{
    SimpleBinop,
    BinopAssignment,
references:- 4
215: /// better messages on error.
217: enum IsBinopAssignment{
--
2091:                    rhs: @ast::Expr,
2092:                    is_binop_assignment: IsBinopAssignment) {
2093:         let tcx = fcx.ccx.tcx;


librustc/middle/typeck/check/mod.rs:3398:1-3398:1 -fn- definition:
pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
    check_block_with_expected(fcx, blk, Some(ty::mk_nil()));
    let blkty = fcx.node_ty(blk.id);
references:- 3
2029:             None => {
2030:                 check_block_no_value(fcx, then_blk);
2031:                 ty::mk_nil()
--
2964:         check_expr_has_type(fcx, cond, ty::mk_bool());
2965:         check_block_no_value(fcx, body);
2966:         let cond_ty = fcx.expr_ty(cond);
--
2980:       ast::ExprLoop(body, _) => {
2981:         check_block_no_value(fcx, (body));
2982:         if !may_break(tcx, expr.id, body) {


librustc/middle/typeck/check/mod.rs:4005:1-4005:1 -fn- definition:
pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
    let typ_s = structurally_resolved_type(fcx, sp, typ);
    return ty::type_is_scalar(typ_s);
references:- 2
3145:                         }
3146:                     } else if !(type_is_scalar(fcx,expr.span,t_e)
3147:                                 && t_1_is_trivial) {


librustc/middle/typeck/check/mod.rs:3493:1-3493:1 -fn- definition:
pub fn check_const_with_ty(fcx: &FnCtxt,
                           _: Span,
                           e: &ast::Expr,
references:- 2
3490:     let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).ty;
3491:     check_const_with_ty(&fcx, sp, e, declty);
3492: }
--
3679:                     let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id());
3680:                     check_const_with_ty(&fcx, e.span, e, declty);
3681:                     // check_expr (from check_const pass) doesn't guarantee


librustc/middle/typeck/check/mod.rs:1698:77-1698:77 -fn- definition:
/// `ty_bot`, so avoid that when err and bot need to be handled differently.
fn check_expr_with_unifier(fcx: &FnCtxt,
                           expr: &ast::Expr,
references:- 7
1463:                                             lvalue_pref: LvaluePreference) {
1464:     check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
1465: }
--
1472:                                lvalue_pref: LvaluePreference)  {
1473:     check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
1474: }


librustc/middle/typeck/check/mod.rs:369:1-369:1 -struct- definition:
struct GatherLocalsVisitor<'a> {
    fcx: &'a FnCtxt<'a>
}
references:- 3
374: impl<'a> GatherLocalsVisitor<'a> {
375:     fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
--
391: impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
392:     // Add explicitly-declared locals.
--
489:         let mut visit = GatherLocalsVisitor { fcx: &fcx, };
490:         // Add formal parameters.


librustc/middle/typeck/check/mod.rs:1519:46-1519:46 -enum- definition:
// for overloaded binary and unary operators.
pub enum DerefArgs {
    DontDerefArgs,
references:- 4
1711:         args: &[@ast::Expr],
1712:         deref_args: DerefArgs) -> ty::t {
1713:         // HACK(eddyb) ignore provided self (it has special typeck rules).
librustc/middle/typeck/check/method.rs:
135:         supplied_tps: &'a [ty::t],          // The list of types X, Y, ... .
136:         deref_args: check::DerefArgs,       // Whether we autopointer first.
137:         check_traits: CheckTraitsFlag,      // Whether we check traits only.
--
308:     extension_candidates: Vec<Candidate>,
309:     deref_args: check::DerefArgs,
310:     check_traits: CheckTraitsFlag,
librustc/middle/typeck/check/mod.rs:
1742:                             args: &[@ast::Expr],
1743:                             deref_args: DerefArgs,
1744:                             variadic: bool) {


librustc/middle/typeck/check/mod.rs:436:1-436:1 -fn- definition:
fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
                fn_style: ast::FnStyle,
                fn_sig: &ty::FnSig,
references:- 2
2340:         check_fn(fcx.ccx, inherited_style, &fty_sig,
2341:                  decl, id, body, fn_kind, fcx.inh);


librustc/middle/typeck/check/mod.rs:280:47-280:47 -fn- definition:
// Used by check_const and check_enum_variants
fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
                     inh: &'a Inherited<'a>,
references:- 2
3677:                     let inh = blank_inherited_fields(ccx);
3678:                     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
3679:                     let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id());


librustc/middle/typeck/check/mod.rs:325:1-325:1 -struct- definition:
struct CheckItemSizedTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
    fn visit_item(&mut self, i: &ast::Item, _: ()) {
references:- 2
328: impl<'a> Visitor<()> for CheckItemSizedTypesVisitor<'a> {
329:     fn visit_item(&mut self, i: &ast::Item, _: ()) {
--
341:     let mut visit = CheckItemSizedTypesVisitor { ccx: ccx };
342:     visit::walk_crate(&mut visit, krate, ());


librustc/middle/typeck/check/mod.rs:3629:8-3629:8 -fn- definition:
        fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
            match ty {
                ast::TyU8 => disr as u8 as Disr == disr,
references:- 2
3634:                 ast::TyU64 => disr as u64 as Disr == disr,
3635:                 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3636:             }
--
3647:         match ty {
3648:             attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3649:             attr::SignedInt(ty) => int_in_range(ccx, ty, disr)


librustc/middle/typeck/check/mod.rs:533:1-533:1 -fn- definition:
fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -> Span {
    assert!(field.id.krate == ast::LOCAL_CRATE);
    let item = match tcx.map.find(struct_id.node) {
references:- 2
570:                     Some(prev_field) => {
571:                         tcx.sess.span_err(span_for_field(tcx, f, id),
572:                             format!("field `{}` hides field declared in super-struct",
573:                                     token::get_name(f.name)));
574:                         tcx.sess.span_note(span_for_field(tcx, prev_field, parent_id),
575:                             "previously declared here");


librustc/middle/typeck/check/mod.rs:3754:75-3754:75 -fn- definition:
// Returns the type parameter count and the type for the given definition.
pub fn ty_param_bounds_and_ty_for_def(fcx: &FnCtxt,
                                      sp: Span,
references:- 2
2901:         check_type_parameter_positions_in_path(fcx, pth, defn);
2902:         let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
2903:         instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
--
3770:       ast::DefUpvar(_, inner, _, _) => {
3771:         return ty_param_bounds_and_ty_for_def(fcx, sp, *inner);
3772:       }


librustc/middle/typeck/check/mod.rs:3413:1-3413:1 -fn- definition:
pub fn check_block_with_expected(fcx: &FnCtxt,
                                 blk: &ast::Block,
                                 expected: Option<ty::t>) {
references:- 4
3399: pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
3400:     check_block_with_expected(fcx, blk, Some(ty::mk_nil()));
3401:     let blkty = fcx.node_ty(blk.id);


librustc/middle/typeck/check/mod.rs:4125:4-4125:4 -fn- definition:
    fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
        ty::mk_param(ccx.tcx, n, local_def(0))
    }
references:- 27
4147:             "min"  | "umax" | "umin" => {
4148:                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
4149:                  param(ccx, 0))
--
4169:             "uninit" => (1u, Vec::new(), param(ccx, 0u)),
4170:             "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
4171:             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
--
4255:                   ty::mk_ptr(tcx, ty::mt {
4256:                       ty: param(ccx, 0),
4257:                       mutbl: ast::MutMutable
--
4342:             "volatile_load" =>
4343:                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
4344:             "volatile_store" =>
4345:                 (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),


librustc/middle/typeck/check/mod.rs:1305:1-1305:1 -fn- definition:
pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
                    expr_id: Option<ast::NodeId>,
                    mut lvalue_pref: LvaluePreference,
references:- 5
3251:               let (base_t, autoderefs, field_ty) =
3252:                 autoderef(fcx, expr.span, raw_base_t, Some(base.id),
3253:                           lvalue_pref, |base_t, _| ty::index(base_t));
librustc/middle/typeck/check/method.rs:
346:         let (self_ty, autoderefs, result) =
347:             check::autoderef(
348:                 self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
--
453:         let span = self.self_expr.map_or(self.span, |e| e.span);
454:         check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
455:             match get(self_ty).sty {
librustc/middle/typeck/check/mod.rs:
2357:         let (_, autoderefs, field_ty) =
2358:             autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2359:                 match ty::get(base_t).sty {


librustc/middle/typeck/check/mod.rs:222:19-222:19 -struct- definition:
pub struct FnCtxt<'a> {
    // This flag is set to true if, during the writeback phase, we encounter
    // a type error in this function.
references:- 100
librustc/middle/typeck/check/_match.rs:
librustc/middle/typeck/check/vtable.rs:
librustc/middle/typeck/check/writeback.rs:
librustc/middle/typeck/check/regionck.rs:
librustc/middle/typeck/check/demand.rs:
librustc/middle/typeck/check/method.rs:
librustc/middle/typeck/check/vtable.rs: