(index<- )        ./librustc/middle/kind.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  use middle::freevars::freevar_entry;
  13  use middle::freevars;
  14  use middle::ty;
  15  use middle::typeck;
  16  use util::ppaux::{Repr, ty_to_str};
  17  use util::ppaux::UserString;
  18  
  19  use syntax::ast::*;
  20  use syntax::attr;
  21  use syntax::codemap::Span;
  22  use syntax::owned_slice::OwnedSlice;
  23  use syntax::print::pprust::{expr_to_str,path_to_str};
  24  use syntax::{visit,ast_util};
  25  use syntax::visit::Visitor;
  26  
  27  // Kind analysis pass.
  28  //
  29  // There are several kinds defined by various operations. The most restrictive
  30  // kind is noncopyable. The noncopyable kind can be extended with any number
  31  // of the following attributes.
  32  //
  33  //  Send: Things that can be sent on channels or included in spawned closures. It
  34  //  includes scalar types as well as classes and unique types containing only
  35  //  sendable types.
  36  //  'static: Things that do not contain references.
  37  //
  38  // This pass ensures that type parameters are only instantiated with types
  39  // whose kinds are equal or less general than the way the type parameter was
  40  // annotated (with the `Send` bound).
  41  //
  42  // It also verifies that noncopyable kinds are not copied. Sendability is not
  43  // applied, since none of our language primitives send. Instead, the sending
  44  // primitives in the stdlib are explicitly annotated to only take sendable
  45  // types.
  46  
  47  #[deriving(Clone)]
  48  pub struct Context<'a> {
  49      tcx: &'a ty::ctxt,
  50  }
  51  
  52  impl<'a> Visitor<()> for Context<'a> {
  53  
  54      fn visit_expr(&mut self, ex&Expr, _()) {
  55          check_expr(self, ex);
  56      }
  57  
  58      fn visit_fn(&mut self, fk&visit::FnKind, fd&FnDecl,
  59                  b&Block, sSpan, nNodeId, _()) {
  60          check_fn(self, fk, fd, b, s, n);
  61      }
  62  
  63      fn visit_ty(&mut self, t&Ty, _()) {
  64          check_ty(self, t);
  65      }
  66  
  67      fn visit_item(&mut self, i&Item, _()) {
  68          check_item(self, i);
  69      }
  70  
  71      fn visit_pat(&mut self, p&Pat, _()) {
  72          check_pat(self, p);
  73      }
  74  }
  75  
  76  pub fn check_crate(tcx: &ty::ctxt,
  77                     krate: &Crate) {
  78      let mut ctx = Context {
  79          tcx: tcx,
  80      };
  81      visit::walk_crate(&mut ctx, krate, ());
  82      tcx.sess.abort_if_errors();
  83  }
  84  
  85  fn check_struct_safe_for_destructor(cx: &mut Context,
  86                                      spanSpan,
  87                                      struct_didDefId) {
  88      let struct_tpt = ty::lookup_item_type(cx.tcx, struct_did);
  89      if !struct_tpt.generics.has_type_params() {
  90          let struct_ty = ty::mk_struct(cx.tcx, struct_did, ty::substs {
  91              regions: ty::NonerasedRegions(OwnedSlice::empty()),
  92              self_ty: None,
  93              tps: Vec::new()
  94          });
  95          if !ty::type_is_sendable(cx.tcx, struct_ty) {
  96              cx.tcx.sess.span_err(span,
  97                                   "cannot implement a destructor on a \
  98                                    structure that does not satisfy Send");
  99              cx.tcx.sess.span_note(span,
 100                                    "use \"#[unsafe_destructor]\" on the \
 101                                     implementation to force the compiler to \
 102                                     allow this");
 103          }
 104      } else {
 105          cx.tcx.sess.span_err(span,
 106                               "cannot implement a destructor on a structure \
 107                                with type parameters");
 108          cx.tcx.sess.span_note(span,
 109                                "use \"#[unsafe_destructor]\" on the \
 110                                 implementation to force the compiler to \
 111                                 allow this");
 112      }
 113  }
 114  
 115  fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_type: &Ty) {
 116      let ast_trait_def = *cx.tcx.def_map.borrow()
 117                                .find(&trait_ref.ref_id)
 118                                .expect("trait ref not in def map!");
 119      let trait_def_id = ast_util::def_id_of_def(ast_trait_def);
 120      let trait_def = cx.tcx.trait_defs.borrow()
 121                            .find_copy(&trait_def_id)
 122                            .expect("trait def not in trait-defs map!");
 123  
 124      // If this trait has builtin-kind supertraits, meet them.
 125      let self_tyty::t = ty::node_id_to_type(cx.tcx, it.id);
 126      debug!("checking impl with self type {:?}", ty::get(self_ty).sty);
 127      check_builtin_bounds(cx, self_ty, trait_def.bounds, |missing| {
 128          cx.tcx.sess.span_err(self_type.span,
 129              format!("the type `{}', which does not fulfill `{}`, cannot implement this \
 130                    trait", ty_to_str(cx.tcx, self_ty), missing.user_string(cx.tcx)));
 131          cx.tcx.sess.span_note(self_type.span,
 132              format!("types implementing this trait must fulfill `{}`",
 133                   trait_def.bounds.user_string(cx.tcx)));
 134      });
 135  
 136      // If this is a destructor, check kinds.
 137      if cx.tcx.lang_items.drop_trait() == Some(trait_def_id) {
 138          match self_type.node {
 139              TyPath(_, ref bounds, path_node_id) => {
 140                  assert!(bounds.is_none());
 141                  let struct_def = cx.tcx.def_map.borrow().get_copy(&path_node_id);
 142                  let struct_did = ast_util::def_id_of_def(struct_def);
 143                  check_struct_safe_for_destructor(cx, self_type.span, struct_did);
 144              }
 145              _ => {
 146                  cx.tcx.sess.span_bug(self_type.span,
 147                      "the self type for the Drop trait impl is not a path");
 148              }
 149          }
 150      }
 151  }
 152  
 153  fn check_item(cx: &mut Context, item: &Item) {
 154      if !attr::contains_name(item.attrs.as_slice(), "unsafe_destructor") {
 155          match item.node {
 156              ItemImpl(_, Some(ref trait_ref), self_type, _) => {
 157                  check_impl_of_trait(cx, item, trait_ref, self_type);
 158              }
 159              _ => {}
 160          }
 161      }
 162  
 163      visit::walk_item(cx, item, ());
 164  }
 165  
 166  // Yields the appropriate function to check the kind of closed over
 167  // variables. `id` is the NodeId for some expression that creates the
 168  // closure.
 169  fn with_appropriate_checker(cx: &Context,
 170                              idNodeId,
 171                              b: |checker: |&Context, &freevar_entry||) {
 172      fn check_for_uniq(cx&Context, fv&freevar_entry, boundsty::BuiltinBounds) {
 173          // all captured data must be owned, regardless of whether it is
 174          // moved in or copied in.
 175          let id = ast_util::def_id_of_def(fv.def).node;
 176          let var_t = ty::node_id_to_type(cx.tcx, id);
 177  
 178          check_freevar_bounds(cx, fv.span, var_t, bounds, None);
 179      }
 180  
 181      fn check_for_block(cx&Context, fv&freevar_entry,
 182                         boundsty::BuiltinBounds, regionty::Region) {
 183          let id = ast_util::def_id_of_def(fv.def).node;
 184          let var_t = ty::node_id_to_type(cx.tcx, id);
 185          // FIXME(#3569): Figure out whether the implicit borrow is actually
 186          // mutable. Currently we assume all upvars are referenced mutably.
 187          let implicit_borrowed_type = ty::mk_mut_rptr(cx.tcx, region, var_t);
 188          check_freevar_bounds(cx, fv.span, implicit_borrowed_type,
 189                               bounds, Some(var_t));
 190      }
 191  
 192      fn check_for_bare(cx&Context, fv&freevar_entry) {
 193          cx.tcx.sess.span_err(
 194              fv.span,
 195              "can't capture dynamic environment in a fn item; \
 196              use the || { ... } closure form instead");
 197      } // same check is done in resolve.rs, but shouldn't be done
 198  
 199      let fty = ty::node_id_to_type(cx.tcx, id);
 200      match ty::get(fty).sty {
 201          ty::ty_closure(box ty::ClosureTy {
 202              store: ty::UniqTraitStore, bounds, ..
 203          }) => b(|cx, fv| check_for_uniq(cx, fv, bounds)),
 204  
 205          ty::ty_closure(box ty::ClosureTy {
 206              store: ty::RegionTraitStore(region, _), bounds, ..
 207          }) => b(|cx, fv| check_for_block(cx, fv, bounds, region)),
 208  
 209          ty::ty_bare_fn(_) => {
 210              b(check_for_bare)
 211          }
 212          ref s => {
 213              cx.tcx.sess.bug(
 214                  format!("expect fn type in kind checker, not {:?}", s));
 215          }
 216      }
 217  }
 218  
 219  // Check that the free variables used in a shared/sendable closure conform
 220  // to the copy/move kind bounds. Then recursively check the function body.
 221  fn check_fn(
 222      cx: &mut Context,
 223      fk: &visit::FnKind,
 224      decl: &FnDecl,
 225      body: &Block,
 226      spSpan,
 227      fn_idNodeId) {
 228  
 229      // Check kinds on free variables:
 230      with_appropriate_checker(cx, fn_id, |chk| {
 231          freevars::with_freevars(cx.tcx, fn_id, |freevars| {
 232              for fv in freevars.iter() {
 233                  chk(cx, fv);
 234              }
 235          });
 236      });
 237  
 238      visit::walk_fn(cx, fk, decl, body, sp, fn_id, ());
 239  }
 240  
 241  pub fn check_expr(cx: &mut Context, e: &Expr) {
 242      debug!("kind::check_expr({})", expr_to_str(e));
 243  
 244      // Handle any kind bounds on type parameters
 245      {
 246          let method_map = cx.tcx.method_map.borrow();
 247          let method = method_map.find(&typeck::MethodCall::expr(e.id));
 248          let node_type_substs = cx.tcx.node_type_substs.borrow();
 249          let r = match method {
 250              Some(method) => Some(&method.substs.tps),
 251              None => node_type_substs.find(&e.id)
 252          };
 253          for ts in r.iter() {
 254              let def_map = cx.tcx.def_map.borrow();
 255              let type_param_defs = match e.node {
 256                ExprPath(_) => {
 257                  let did = ast_util::def_id_of_def(def_map.get_copy(&e.id));
 258                  ty::lookup_item_type(cx.tcx, did).generics.type_param_defs.clone()
 259                }
 260                _ => {
 261                  // Type substitutions should only occur on paths and
 262                  // method calls, so this needs to be a method call.
 263  
 264                  // Even though the callee_id may have been the id with
 265                  // node_type_substs, e.id is correct here.
 266                  match method {
 267                      Some(method) => {
 268                          ty::method_call_type_param_defs(cx.tcx, method.origin)
 269                      }
 270                      None => {
 271                          cx.tcx.sess.span_bug(e.span,
 272                              "non path/method call expr has type substs??");
 273                      }
 274                  }
 275                }
 276              };
 277              if ts.len() != type_param_defs.len() {
 278                  // Fail earlier to make debugging easier
 279                  fail!("internal error: in kind::check_expr, length \
 280                        mismatch between actual and declared bounds: actual = \
 281                        {}, declared = {}",
 282                        ts.repr(cx.tcx),
 283                        type_param_defs.repr(cx.tcx));
 284              }
 285              for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
 286                  check_typaram_bounds(cx, e.span, ty, type_param_def)
 287              }
 288          }
 289      }
 290  
 291      match e.node {
 292          ExprUnary(UnBox, interior) => {
 293              let interior_type = ty::expr_ty(cx.tcx, interior);
 294              let _ = check_static(cx.tcx, interior_type, interior.span);
 295          }
 296          ExprCast(source, _) => {
 297              let source_ty = ty::expr_ty(cx.tcx, source);
 298              let target_ty = ty::expr_ty(cx.tcx, e);
 299              check_trait_cast(cx, source_ty, target_ty, source.span);
 300          }
 301          ExprRepeat(element, count_expr) => {
 302              let count = ty::eval_repeat_count(cx.tcx, count_expr);
 303              if count > 1 {
 304                  let element_ty = ty::expr_ty(cx.tcx, element);
 305                  check_copy(cx, element_ty, element.span,
 306                             "repeated element will be copied");
 307              }
 308          }
 309          _ => {}
 310      }
 311  
 312      // Search for auto-adjustments to find trait coercions.
 313      match cx.tcx.adjustments.borrow().find(&e.id) {
 314          Some(adjustment) => {
 315              match *adjustment {
 316                  ty::AutoObject(..) => {
 317                      let source_ty = ty::expr_ty(cx.tcx, e);
 318                      let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
 319                      check_trait_cast(cx, source_ty, target_ty, e.span);
 320                  }
 321                  ty::AutoAddEnv(..) |
 322                  ty::AutoDerefRef(..) => {}
 323              }
 324          }
 325          None => {}
 326      }
 327  
 328      visit::walk_expr(cx, e, ());
 329  }
 330  
 331  fn check_trait_cast(cx: &mut Context, source_tyty::t, target_tyty::t, spanSpan) {
 332      check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
 333      match ty::get(target_ty).sty {
 334          ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
 335              check_trait_cast_bounds(cx, span, source_ty, bounds);
 336          }
 337          _ => {}
 338      }
 339  }
 340  
 341  fn check_ty(cx: &mut Context, aty: &Ty) {
 342      match aty.node {
 343          TyPath(_, _, id) => {
 344              let node_type_substs = cx.tcx.node_type_substs.borrow();
 345              let r = node_type_substs.find(&id);
 346              for ts in r.iter() {
 347                  let def_map = cx.tcx.def_map.borrow();
 348                  let did = ast_util::def_id_of_def(def_map.get_copy(&id));
 349                  let generics = ty::lookup_item_type(cx.tcx, did).generics;
 350                  let type_param_defs = generics.type_param_defs();
 351                  for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
 352                      check_typaram_bounds(cx, aty.span, ty, type_param_def)
 353                  }
 354              }
 355          }
 356          _ => {}
 357      }
 358      visit::walk_ty(cx, aty, ());
 359  }
 360  
 361  // Calls "any_missing" if any bounds were missing.
 362  pub fn check_builtin_bounds(cx: &Context,
 363                              tyty::t,
 364                              boundsty::BuiltinBounds,
 365                              any_missing: |ty::BuiltinBounds|) {
 366      let kind = ty::type_contents(cx.tcx, ty);
 367      let mut missing = ty::EmptyBuiltinBounds();
 368      for bound in bounds.iter() {
 369          if !kind.meets_bound(cx.tcx, bound) {
 370              missing.add(bound);
 371          }
 372      }
 373      if !missing.is_empty() {
 374          any_missing(missing);
 375      }
 376  }
 377  
 378  pub fn check_typaram_bounds(cx: &Context,
 379                              spSpan,
 380                              tyty::t,
 381                              type_param_def: &ty::TypeParameterDef) {
 382      check_builtin_bounds(cx,
 383                           ty,
 384                           type_param_def.bounds.builtin_bounds,
 385                           |missing| {
 386          cx.tcx.sess.span_err(
 387              sp,
 388              format!("instantiating a type parameter with an incompatible type \
 389                    `{}`, which does not fulfill `{}`",
 390                   ty_to_str(cx.tcx, ty),
 391                   missing.user_string(cx.tcx)));
 392      });
 393  }
 394  
 395  pub fn check_freevar_bounds(cx: &Context, spSpan, tyty::t,
 396                              boundsty::BuiltinBounds, referenced_tyOption<ty::t>)
 397  {
 398      check_builtin_bounds(cx, ty, bounds, |missing| {
 399          // Will be Some if the freevar is implicitly borrowed (stack closure).
 400          // Emit a less mysterious error message in this case.
 401          match referenced_ty {
 402              Some(rty) => cx.tcx.sess.span_err(sp,
 403                  format!("cannot implicitly borrow variable of type `{}` in a bounded \
 404                        stack closure (implicit reference does not fulfill `{}`)",
 405                       ty_to_str(cx.tcx, rty), missing.user_string(cx.tcx))),
 406              None => cx.tcx.sess.span_err(sp,
 407                  format!("cannot capture variable of type `{}`, which does \
 408                        not fulfill `{}`, in a bounded closure",
 409                       ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx))),
 410          }
 411          cx.tcx.sess.span_note(
 412              sp,
 413              format!("this closure's environment must satisfy `{}`",
 414                   bounds.user_string(cx.tcx)));
 415      });
 416  }
 417  
 418  pub fn check_trait_cast_bounds(cx: &Context, spSpan, tyty::t,
 419                                 boundsty::BuiltinBounds) {
 420      check_builtin_bounds(cx, ty, bounds, |missing| {
 421          cx.tcx.sess.span_err(sp,
 422              format!("cannot pack type `{}`, which does not fulfill \
 423                    `{}`, as a trait bounded by {}",
 424                   ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx),
 425                   bounds.user_string(cx.tcx)));
 426      });
 427  }
 428  
 429  fn check_copy(cx: &Context, tyty::t, spSpan, reason: &str) {
 430      debug!("type_contents({})={}",
 431             ty_to_str(cx.tcx, ty),
 432             ty::type_contents(cx.tcx, ty).to_str());
 433      if ty::type_moves_by_default(cx.tcx, ty) {
 434          cx.tcx.sess.span_err(
 435              sp, format!("copying a value of non-copyable type `{}`",
 436                       ty_to_str(cx.tcx, ty)));
 437          cx.tcx.sess.span_note(sp, format!("{}", reason));
 438      }
 439  }
 440  
 441  pub fn check_static(tcx: &ty::ctxt, tyty::t, spSpan) -> bool {
 442      if !ty::type_is_static(tcx, ty) {
 443          match ty::get(ty).sty {
 444            ty::ty_param(..) => {
 445              tcx.sess.span_err(sp,
 446                  format!("value may contain references; \
 447                           add `'static` bound to `{}`", ty_to_str(tcx, ty)));
 448            }
 449            _ => {
 450              tcx.sess.span_err(sp, "value may contain references");
 451            }
 452          }
 453          false
 454      } else {
 455          true
 456      }
 457  }
 458  
 459  /// This is rather subtle.  When we are casting a value to an instantiated
 460  /// trait like `a as trait<'r>`, regionck already ensures that any references
 461  /// that appear in the type of `a` are bounded by `'r` (ed.: rem
 462  /// FIXME(#5723)).  However, it is possible that there are *type parameters*
 463  /// in the type of `a`, and those *type parameters* may have references
 464  /// within them.  We have to guarantee that the regions which appear in those
 465  /// type parameters are not obscured.
 466  ///
 467  /// Therefore, we ensure that one of three conditions holds:
 468  ///
 469  /// (1) The trait instance cannot escape the current fn.  This is
 470  /// guaranteed if the region bound `&r` is some scope within the fn
 471  /// itself.  This case is safe because whatever references are
 472  /// found within the type parameter, they must enclose the fn body
 473  /// itself.
 474  ///
 475  /// (2) The type parameter appears in the type of the trait.  For
 476  /// example, if the type parameter is `T` and the trait type is
 477  /// `deque<T>`, then whatever references may appear in `T` also
 478  /// appear in `deque<T>`.
 479  ///
 480  /// (3) The type parameter is sendable (and therefore does not contain
 481  /// references).
 482  ///
 483  /// FIXME(#5723)---This code should probably move into regionck.
 484  pub fn check_cast_for_escaping_regions(
 485      cx: &Context,
 486      source_tyty::t,
 487      target_tyty::t,
 488      source_spanSpan)
 489  {
 490      // Determine what type we are casting to; if it is not a trait, then no
 491      // worries.
 492      match ty::get(target_ty).sty {
 493          ty::ty_trait(..) => {}
 494          _ => { return; }
 495      }
 496  
 497      // Collect up the regions that appear in the target type.  We want to
 498      // ensure that these lifetimes are shorter than all lifetimes that are in
 499      // the source type.  See test `src/test/compile-fail/regions-trait-2.rs`
 500      let mut target_regions = Vec::new();
 501      ty::walk_regions_and_ty(
 502          cx.tcx,
 503          target_ty,
 504          |r| {
 505              if !r.is_bound() {
 506                  target_regions.push(r);
 507              }
 508          },
 509          |_| ());
 510  
 511      // Check, based on the region associated with the trait, whether it can
 512      // possibly escape the enclosing fn item (note that all type parameters
 513      // must have been declared on the enclosing fn item).
 514      if target_regions.iter().any(|r| is_ReScope(*r)) {
 515          return; /* case (1) */
 516      }
 517  
 518      // Assuming the trait instance can escape, then ensure that each parameter
 519      // either appears in the trait type or is sendable.
 520      let target_params = ty::param_tys_in_type(target_ty);
 521      ty::walk_regions_and_ty(
 522          cx.tcx,
 523          source_ty,
 524  
 525          |_r| {
 526              // FIXME(#5723) --- turn this check on once &Objects are usable
 527              //
 528              // if !target_regions.iter().any(|t_r| is_subregion_of(cx, *t_r, r)) {
 529              //     cx.tcx.sess.span_err(
 530              //         source_span,
 531              //         format!("source contains reference with lifetime \
 532              //               not found in the target type `{}`",
 533              //              ty_to_str(cx.tcx, target_ty)));
 534              //     note_and_explain_region(
 535              //         cx.tcx, "source data is only valid for ", r, "");
 536              // }
 537          },
 538  
 539          |ty| {
 540              match ty::get(ty).sty {
 541                  ty::ty_param(source_param) => {
 542                      if target_params.iter().any(|x| x == &source_param) {
 543                          /* case (2) */
 544                      } else {
 545                          check_static(cx.tcx, ty, source_span); /* case (3) */
 546                      }
 547                  }
 548                  _ => {}
 549              }
 550          });
 551  
 552      fn is_ReScope(rty::Region) -> bool {
 553          match r {
 554              ty::ReScope(..) => true,
 555              _ => false
 556          }
 557      }
 558  }
 559  
 560  // Ensure that `ty` has a statically known size (i.e., it has the `Sized` bound).
 561  fn check_sized(tcx: &ty::ctxt, tyty::t, name: ~str, spSpan) {
 562      if !ty::type_is_sized(tcx, ty) {
 563          tcx.sess.span_err(sp, format!("variable `{}` has dynamically sized type `{}`",
 564                                        name, ty_to_str(tcx, ty)));
 565      }
 566  }
 567  
 568  // Check that any variables in a pattern have types with statically known size.
 569  fn check_pat(cx: &mut Context, pat: &Pat) {
 570      let var_name = match pat.node {
 571          PatWild => Some("_".to_owned()),
 572          PatIdent(_, ref path, _) => Some(path_to_str(path).to_owned()),
 573          _ => None
 574      };
 575  
 576      match var_name {
 577          Some(name) => {
 578              let types = cx.tcx.node_types.borrow();
 579              let ty = types.find(&(pat.id as uint));
 580              match ty {
 581                  Some(ty) => {
 582                      debug!("kind: checking sized-ness of variable {}{}",
 583                             name, ty_to_str(cx.tcx, *ty));
 584                      check_sized(cx.tcx, *ty, name, pat.span);
 585                  }
 586                  None => {} // extern fn args
 587              }
 588          }
 589          None => {}
 590      }
 591  
 592      visit::walk_pat(cx, pat, ());
 593  }


librustc/middle/kind.rs:361:51-361:51 -fn- definition:
// Calls "any_missing" if any bounds were missing.
pub fn check_builtin_bounds(cx: &Context,
                            ty: ty::t,
references:- 4
397: {
398:     check_builtin_bounds(cx, ty, bounds, |missing| {
399:         // Will be Some if the freevar is implicitly borrowed (stack closure).
--
419:                                bounds: ty::BuiltinBounds) {
420:     check_builtin_bounds(cx, ty, bounds, |missing| {
421:         cx.tcx.sess.span_err(sp,


librustc/middle/kind.rs:47:19-47:19 -struct- definition:
pub struct Context<'a> {
    tcx: &'a ty::ctxt,
}
references:- 25
77:                    krate: &Crate) {
78:     let mut ctx = Context {
79:         tcx: tcx,
--
484: pub fn check_cast_for_escaping_regions(
485:     cx: &Context,
486:     source_ty: ty::t,
--
568: // Check that any variables in a pattern have types with statically known size.
569: fn check_pat(cx: &mut Context, pat: &Pat) {
570:     let var_name = match pat.node {


librustc/middle/kind.rs:330:1-330:1 -fn- definition:
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
    check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
    match ty::get(target_ty).sty {
references:- 2
318:                     let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
319:                     check_trait_cast(cx, source_ty, target_ty, e.span);
320:                 }


librustc/middle/kind.rs:440:1-440:1 -fn- definition:
pub fn check_static(tcx: &ty::ctxt, ty: ty::t, sp: Span) -> bool {
    if !ty::type_is_static(tcx, ty) {
        match ty::get(ty).sty {
references:- 2
544:                     } else {
545:                         check_static(cx.tcx, ty, source_span); /* case (3) */
546:                     }


librustc/middle/kind.rs:377:1-377:1 -fn- definition:
pub fn check_typaram_bounds(cx: &Context,
                            sp: Span,
                            ty: ty::t,
references:- 2
285:             for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
286:                 check_typaram_bounds(cx, e.span, ty, type_param_def)
287:             }
--
351:                 for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
352:                     check_typaram_bounds(cx, aty.span, ty, type_param_def)
353:                 }


librustc/middle/kind.rs:394:1-394:1 -fn- definition:
pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t,
                            bounds: ty::BuiltinBounds, referenced_ty: Option<ty::t>)
{
references:- 2
187:         let implicit_borrowed_type = ty::mk_mut_rptr(cx.tcx, region, var_t);
188:         check_freevar_bounds(cx, fv.span, implicit_borrowed_type,
189:                              bounds, Some(var_t));