]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/mem_categorization.rs
Unignore u128 test for stage 0,1
[rust.git] / src / librustc / middle / mem_categorization.rs
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 //! # Categorization
12 //!
13 //! The job of the categorization module is to analyze an expression to
14 //! determine what kind of memory is used in evaluating it (for example,
15 //! where dereferences occur and what kind of pointer is dereferenced;
16 //! whether the memory is mutable; etc)
17 //!
18 //! Categorization effectively transforms all of our expressions into
19 //! expressions of the following forms (the actual enum has many more
20 //! possibilities, naturally, but they are all variants of these base
21 //! forms):
22 //!
23 //!     E = rvalue    // some computed rvalue
24 //!       | x         // address of a local variable or argument
25 //!       | *E        // deref of a ptr
26 //!       | E.comp    // access to an interior component
27 //!
28 //! Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
29 //! address where the result is to be found.  If Expr is an lvalue, then this
30 //! is the address of the lvalue.  If Expr is an rvalue, this is the address of
31 //! some temporary spot in memory where the result is stored.
32 //!
33 //! Now, cat_expr() classifies the expression Expr and the address A=ToAddr(Expr)
34 //! as follows:
35 //!
36 //! - cat: what kind of expression was this?  This is a subset of the
37 //!   full expression forms which only includes those that we care about
38 //!   for the purpose of the analysis.
39 //! - mutbl: mutability of the address A
40 //! - ty: the type of data found at the address A
41 //!
42 //! The resulting categorization tree differs somewhat from the expressions
43 //! themselves.  For example, auto-derefs are explicit.  Also, an index a[b] is
44 //! decomposed into two operations: a dereference to reach the array data and
45 //! then an index to jump forward to the relevant item.
46 //!
47 //! ## By-reference upvars
48 //!
49 //! One part of the translation which may be non-obvious is that we translate
50 //! closure upvars into the dereference of a borrowed pointer; this more closely
51 //! resembles the runtime translation. So, for example, if we had:
52 //!
53 //!     let mut x = 3;
54 //!     let y = 5;
55 //!     let inc = || x += y;
56 //!
57 //! Then when we categorize `x` (*within* the closure) we would yield a
58 //! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference
59 //! tied to `x`. The type of `x'` will be a borrowed pointer.
60
61 #![allow(non_camel_case_types)]
62
63 pub use self::PointerKind::*;
64 pub use self::InteriorKind::*;
65 pub use self::FieldName::*;
66 pub use self::ElementKind::*;
67 pub use self::MutabilityCategory::*;
68 pub use self::AliasableReason::*;
69 pub use self::Note::*;
70
71 use self::Aliasability::*;
72
73 use hir::def_id::DefId;
74 use hir::map as hir_map;
75 use infer::InferCtxt;
76 use hir::def::{Def, CtorKind};
77 use ty::adjustment;
78 use ty::{self, Ty, TyCtxt};
79
80 use hir::{MutImmutable, MutMutable, PatKind};
81 use hir::pat_util::EnumerateAndAdjustIterator;
82 use hir;
83 use syntax::ast;
84 use syntax_pos::Span;
85
86 use std::fmt;
87 use std::rc::Rc;
88
89 #[derive(Clone, PartialEq)]
90 pub enum Categorization<'tcx> {
91     // temporary val, argument is its scope
92     Rvalue(&'tcx ty::Region, &'tcx ty::Region),
93     StaticItem,
94     Upvar(Upvar),                          // upvar referenced by closure env
95     Local(ast::NodeId),                    // local variable
96     Deref(cmt<'tcx>, usize, PointerKind<'tcx>),  // deref of a ptr
97     Interior(cmt<'tcx>, InteriorKind),     // something interior: field, tuple, etc
98     Downcast(cmt<'tcx>, DefId),            // selects a particular enum variant (*1)
99
100     // (*1) downcast is only required if the enum has more than one variant
101 }
102
103 // Represents any kind of upvar
104 #[derive(Clone, Copy, PartialEq)]
105 pub struct Upvar {
106     pub id: ty::UpvarId,
107     pub kind: ty::ClosureKind
108 }
109
110 // different kinds of pointers:
111 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
112 pub enum PointerKind<'tcx> {
113     /// `Box<T>`
114     Unique,
115
116     /// `&T`
117     BorrowedPtr(ty::BorrowKind, &'tcx ty::Region),
118
119     /// `*T`
120     UnsafePtr(hir::Mutability),
121
122     /// Implicit deref of the `&T` that results from an overloaded index `[]`.
123     Implicit(ty::BorrowKind, &'tcx ty::Region),
124 }
125
126 // We use the term "interior" to mean "something reachable from the
127 // base without a pointer dereference", e.g. a field
128 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
129 pub enum InteriorKind {
130     InteriorField(FieldName),
131     InteriorElement(InteriorOffsetKind, ElementKind),
132 }
133
134 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
135 pub enum FieldName {
136     NamedField(ast::Name),
137     PositionalField(usize)
138 }
139
140 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
141 pub enum InteriorOffsetKind {
142     Index,            // e.g. `array_expr[index_expr]`
143     Pattern,          // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }`
144 }
145
146 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
147 pub enum ElementKind {
148     VecElement,
149     OtherElement,
150 }
151
152 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
153 pub enum MutabilityCategory {
154     McImmutable, // Immutable.
155     McDeclared,  // Directly declared as mutable.
156     McInherited, // Inherited from the fact that owner is mutable.
157 }
158
159 // A note about the provenance of a `cmt`.  This is used for
160 // special-case handling of upvars such as mutability inference.
161 // Upvar categorization can generate a variable number of nested
162 // derefs.  The note allows detecting them without deep pattern
163 // matching on the categorization.
164 #[derive(Clone, Copy, PartialEq, Debug)]
165 pub enum Note {
166     NoteClosureEnv(ty::UpvarId), // Deref through closure env
167     NoteUpvarRef(ty::UpvarId),   // Deref through by-ref upvar
168     NoteNone                     // Nothing special
169 }
170
171 // `cmt`: "Category, Mutability, and Type".
172 //
173 // a complete categorization of a value indicating where it originated
174 // and how it is located, as well as the mutability of the memory in
175 // which the value is stored.
176 //
177 // *WARNING* The field `cmt.type` is NOT necessarily the same as the
178 // result of `node_id_to_type(cmt.id)`. This is because the `id` is
179 // always the `id` of the node producing the type; in an expression
180 // like `*x`, the type of this deref node is the deref'd type (`T`),
181 // but in a pattern like `@x`, the `@x` pattern is again a
182 // dereference, but its type is the type *before* the dereference
183 // (`@T`). So use `cmt.ty` to find the type of the value in a consistent
184 // fashion. For more details, see the method `cat_pattern`
185 #[derive(Clone, PartialEq)]
186 pub struct cmt_<'tcx> {
187     pub id: ast::NodeId,           // id of expr/pat producing this value
188     pub span: Span,                // span of same expr/pat
189     pub cat: Categorization<'tcx>, // categorization of expr
190     pub mutbl: MutabilityCategory, // mutability of expr as lvalue
191     pub ty: Ty<'tcx>,              // type of the expr (*see WARNING above*)
192     pub note: Note,                // Note about the provenance of this cmt
193 }
194
195 pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
196
197 impl<'tcx> cmt_<'tcx> {
198     pub fn get_field(&self, name: ast::Name) -> Option<DefId> {
199         match self.cat {
200             Categorization::Deref(ref cmt, ..) |
201             Categorization::Interior(ref cmt, _) |
202             Categorization::Downcast(ref cmt, _) => {
203                 if let Categorization::Local(_) = cmt.cat {
204                     if let ty::TyAdt(def, _) = self.ty.sty {
205                         return def.struct_variant().find_field_named(name).map(|x| x.did);
206                     }
207                     None
208                 } else {
209                     cmt.get_field(name)
210                 }
211             }
212             _ => None
213         }
214     }
215
216     pub fn get_field_name(&self) -> Option<ast::Name> {
217         match self.cat {
218             Categorization::Interior(_, ref ik) => {
219                 if let InteriorKind::InteriorField(FieldName::NamedField(name)) = *ik {
220                     Some(name)
221                 } else {
222                     None
223                 }
224             }
225             Categorization::Deref(ref cmt, ..) |
226             Categorization::Downcast(ref cmt, _) => {
227                 cmt.get_field_name()
228             }
229             _ => None,
230         }
231     }
232
233     pub fn get_arg_if_immutable(&self, map: &hir_map::Map) -> Option<ast::NodeId> {
234         match self.cat {
235             Categorization::Deref(ref cmt, ..) |
236             Categorization::Interior(ref cmt, _) |
237             Categorization::Downcast(ref cmt, _) => {
238                 if let Categorization::Local(nid) = cmt.cat {
239                     if let ty::TyAdt(_, _) = self.ty.sty {
240                         if let ty::TyRef(_, ty::TypeAndMut{mutbl: MutImmutable, ..}) = cmt.ty.sty {
241                             return Some(nid);
242                         }
243                     }
244                     None
245                 } else {
246                     cmt.get_arg_if_immutable(map)
247                 }
248             }
249             _ => None
250         }
251     }
252 }
253
254 pub trait ast_node {
255     fn id(&self) -> ast::NodeId;
256     fn span(&self) -> Span;
257 }
258
259 impl ast_node for hir::Expr {
260     fn id(&self) -> ast::NodeId { self.id }
261     fn span(&self) -> Span { self.span }
262 }
263
264 impl ast_node for hir::Pat {
265     fn id(&self) -> ast::NodeId { self.id }
266     fn span(&self) -> Span { self.span }
267 }
268
269 #[derive(Copy, Clone)]
270 pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
271     pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
272     options: MemCategorizationOptions,
273 }
274
275 #[derive(Copy, Clone, Default)]
276 pub struct MemCategorizationOptions {
277     // If true, then when analyzing a closure upvar, if the closure
278     // has a missing kind, we treat it like a Fn closure. When false,
279     // we ICE if the closure has a missing kind. Should be false
280     // except during closure kind inference. It is used by the
281     // mem-categorization code to be able to have stricter assertions
282     // (which are always true except during upvar inference).
283     pub during_closure_kind_inference: bool,
284 }
285
286 pub type McResult<T> = Result<T, ()>;
287
288 impl MutabilityCategory {
289     pub fn from_mutbl(m: hir::Mutability) -> MutabilityCategory {
290         let ret = match m {
291             MutImmutable => McImmutable,
292             MutMutable => McDeclared
293         };
294         debug!("MutabilityCategory::{}({:?}) => {:?}",
295                "from_mutbl", m, ret);
296         ret
297     }
298
299     pub fn from_borrow_kind(borrow_kind: ty::BorrowKind) -> MutabilityCategory {
300         let ret = match borrow_kind {
301             ty::ImmBorrow => McImmutable,
302             ty::UniqueImmBorrow => McImmutable,
303             ty::MutBorrow => McDeclared,
304         };
305         debug!("MutabilityCategory::{}({:?}) => {:?}",
306                "from_borrow_kind", borrow_kind, ret);
307         ret
308     }
309
310     fn from_pointer_kind(base_mutbl: MutabilityCategory,
311                          ptr: PointerKind) -> MutabilityCategory {
312         let ret = match ptr {
313             Unique => {
314                 base_mutbl.inherit()
315             }
316             BorrowedPtr(borrow_kind, _) | Implicit(borrow_kind, _) => {
317                 MutabilityCategory::from_borrow_kind(borrow_kind)
318             }
319             UnsafePtr(m) => {
320                 MutabilityCategory::from_mutbl(m)
321             }
322         };
323         debug!("MutabilityCategory::{}({:?}, {:?}) => {:?}",
324                "from_pointer_kind", base_mutbl, ptr, ret);
325         ret
326     }
327
328     fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory {
329         let ret = match tcx.hir.get(id) {
330             hir_map::NodeLocal(p) => match p.node {
331                 PatKind::Binding(bind_mode, ..) => {
332                     if bind_mode == hir::BindByValue(hir::MutMutable) {
333                         McDeclared
334                     } else {
335                         McImmutable
336                     }
337                 }
338                 _ => span_bug!(p.span, "expected identifier pattern")
339             },
340             _ => span_bug!(tcx.hir.span(id), "expected identifier pattern")
341         };
342         debug!("MutabilityCategory::{}(tcx, id={:?}) => {:?}",
343                "from_local", id, ret);
344         ret
345     }
346
347     pub fn inherit(&self) -> MutabilityCategory {
348         let ret = match *self {
349             McImmutable => McImmutable,
350             McDeclared => McInherited,
351             McInherited => McInherited,
352         };
353         debug!("{:?}.inherit() => {:?}", self, ret);
354         ret
355     }
356
357     pub fn is_mutable(&self) -> bool {
358         let ret = match *self {
359             McImmutable => false,
360             McInherited => true,
361             McDeclared => true,
362         };
363         debug!("{:?}.is_mutable() => {:?}", self, ret);
364         ret
365     }
366
367     pub fn is_immutable(&self) -> bool {
368         let ret = match *self {
369             McImmutable => true,
370             McDeclared | McInherited => false
371         };
372         debug!("{:?}.is_immutable() => {:?}", self, ret);
373         ret
374     }
375
376     pub fn to_user_str(&self) -> &'static str {
377         match *self {
378             McDeclared | McInherited => "mutable",
379             McImmutable => "immutable",
380         }
381     }
382 }
383
384 impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
385     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
386                -> MemCategorizationContext<'a, 'gcx, 'tcx> {
387         MemCategorizationContext::with_options(infcx, MemCategorizationOptions::default())
388     }
389
390     pub fn with_options(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
391                         options: MemCategorizationOptions)
392                         -> MemCategorizationContext<'a, 'gcx, 'tcx> {
393         MemCategorizationContext {
394             infcx: infcx,
395             options: options,
396         }
397     }
398
399     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
400         self.infcx.tcx
401     }
402
403     fn expr_ty(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
404         match self.infcx.node_ty(expr.id) {
405             Ok(t) => Ok(t),
406             Err(()) => {
407                 debug!("expr_ty({:?}) yielded Err", expr);
408                 Err(())
409             }
410         }
411     }
412
413     fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
414         self.infcx.expr_ty_adjusted(expr)
415     }
416
417     fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
418         self.infcx.node_ty(id)
419     }
420
421     fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
422         let base_ty = self.infcx.node_ty(pat.id)?;
423         // FIXME (Issue #18207): This code detects whether we are
424         // looking at a `ref x`, and if so, figures out what the type
425         // *being borrowed* is.  But ideally we would put in a more
426         // fundamental fix to this conflated use of the node id.
427         let ret_ty = match pat.node {
428             PatKind::Binding(hir::BindByRef(_), ..) => {
429                 // a bind-by-ref means that the base_ty will be the type of the ident itself,
430                 // but what we want here is the type of the underlying value being borrowed.
431                 // So peel off one-level, turning the &T into T.
432                 match base_ty.builtin_deref(false, ty::NoPreference) {
433                     Some(t) => t.ty,
434                     None => { return Err(()); }
435                 }
436             }
437             _ => base_ty,
438         };
439         debug!("pat_ty(pat={:?}) base_ty={:?} ret_ty={:?}",
440                pat, base_ty, ret_ty);
441         Ok(ret_ty)
442     }
443
444     pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
445         match self.infcx.tables.borrow().adjustments.get(&expr.id) {
446             None => {
447                 // No adjustments.
448                 self.cat_expr_unadjusted(expr)
449             }
450
451             Some(adjustment) => {
452                 match adjustment.kind {
453                     adjustment::Adjust::DerefRef {
454                         autoderefs,
455                         autoref: None,
456                         unsize: false
457                     } => {
458                         // Equivalent to *expr or something similar.
459                         self.cat_expr_autoderefd(expr, autoderefs)
460                     }
461
462                     adjustment::Adjust::NeverToAny |
463                     adjustment::Adjust::ReifyFnPointer |
464                     adjustment::Adjust::UnsafeFnPointer |
465                     adjustment::Adjust::MutToConstPointer |
466                     adjustment::Adjust::DerefRef {..} => {
467                         debug!("cat_expr({:?}): {:?}",
468                                adjustment,
469                                expr);
470                         // Result is an rvalue.
471                         let expr_ty = self.expr_ty_adjusted(expr)?;
472                         Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
473                     }
474                 }
475             }
476         }
477     }
478
479     pub fn cat_expr_autoderefd(&self,
480                                expr: &hir::Expr,
481                                autoderefs: usize)
482                                -> McResult<cmt<'tcx>> {
483         let mut cmt = self.cat_expr_unadjusted(expr)?;
484         debug!("cat_expr_autoderefd: autoderefs={}, cmt={:?}",
485                autoderefs,
486                cmt);
487         for deref in 1..autoderefs + 1 {
488             cmt = self.cat_deref(expr, cmt, deref)?;
489         }
490         return Ok(cmt);
491     }
492
493     pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
494         debug!("cat_expr: id={} expr={:?}", expr.id, expr);
495
496         let expr_ty = self.expr_ty(expr)?;
497         match expr.node {
498           hir::ExprUnary(hir::UnDeref, ref e_base) => {
499             let base_cmt = self.cat_expr(&e_base)?;
500             self.cat_deref(expr, base_cmt, 0)
501           }
502
503           hir::ExprField(ref base, f_name) => {
504             let base_cmt = self.cat_expr(&base)?;
505             debug!("cat_expr(cat_field): id={} expr={:?} base={:?}",
506                    expr.id,
507                    expr,
508                    base_cmt);
509             Ok(self.cat_field(expr, base_cmt, f_name.node, expr_ty))
510           }
511
512           hir::ExprTupField(ref base, idx) => {
513             let base_cmt = self.cat_expr(&base)?;
514             Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
515           }
516
517           hir::ExprIndex(ref base, _) => {
518             let method_call = ty::MethodCall::expr(expr.id());
519             match self.infcx.node_method_ty(method_call) {
520                 Some(method_ty) => {
521                     // If this is an index implemented by a method call, then it
522                     // will include an implicit deref of the result.
523                     let ret_ty = self.overloaded_method_return_ty(method_ty);
524
525                     // The index method always returns an `&T`, so
526                     // dereference it to find the result type.
527                     let elem_ty = match ret_ty.sty {
528                         ty::TyRef(_, mt) => mt.ty,
529                         _ => {
530                             debug!("cat_expr_unadjusted: return type of overloaded index is {:?}?",
531                                    ret_ty);
532                             return Err(());
533                         }
534                     };
535
536                     // The call to index() returns a `&T` value, which
537                     // is an rvalue. That is what we will be
538                     // dereferencing.
539                     let base_cmt = self.cat_rvalue_node(expr.id(), expr.span(), ret_ty);
540                     Ok(self.cat_deref_common(expr, base_cmt, 1, elem_ty, true))
541                 }
542                 None => {
543                     self.cat_index(expr, self.cat_expr(&base)?, InteriorOffsetKind::Index)
544                 }
545             }
546           }
547
548           hir::ExprPath(ref qpath) => {
549             let def = self.infcx.tables.borrow().qpath_def(qpath, expr.id);
550             self.cat_def(expr.id, expr.span, expr_ty, def)
551           }
552
553           hir::ExprType(ref e, _) => {
554             self.cat_expr(&e)
555           }
556
557           hir::ExprAddrOf(..) | hir::ExprCall(..) |
558           hir::ExprAssign(..) | hir::ExprAssignOp(..) |
559           hir::ExprClosure(..) | hir::ExprRet(..) |
560           hir::ExprUnary(..) |
561           hir::ExprMethodCall(..) | hir::ExprCast(..) |
562           hir::ExprArray(..) | hir::ExprTup(..) | hir::ExprIf(..) |
563           hir::ExprBinary(..) | hir::ExprWhile(..) |
564           hir::ExprBlock(..) | hir::ExprLoop(..) | hir::ExprMatch(..) |
565           hir::ExprLit(..) | hir::ExprBreak(..) |
566           hir::ExprAgain(..) | hir::ExprStruct(..) | hir::ExprRepeat(..) |
567           hir::ExprInlineAsm(..) | hir::ExprBox(..) => {
568             Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
569           }
570         }
571     }
572
573     pub fn cat_def(&self,
574                    id: ast::NodeId,
575                    span: Span,
576                    expr_ty: Ty<'tcx>,
577                    def: Def)
578                    -> McResult<cmt<'tcx>> {
579         debug!("cat_def: id={} expr={:?} def={:?}",
580                id, expr_ty, def);
581
582         match def {
583           Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
584           Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) => {
585                 Ok(self.cat_rvalue_node(id, span, expr_ty))
586           }
587
588           Def::Static(_, mutbl) => {
589               Ok(Rc::new(cmt_ {
590                   id:id,
591                   span:span,
592                   cat:Categorization::StaticItem,
593                   mutbl: if mutbl { McDeclared } else { McImmutable},
594                   ty:expr_ty,
595                   note: NoteNone
596               }))
597           }
598
599           Def::Upvar(def_id, _, fn_node_id) => {
600               let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
601               let ty = self.node_ty(fn_node_id)?;
602               match ty.sty {
603                   ty::TyClosure(closure_id, _) => {
604                       match self.infcx.closure_kind(closure_id) {
605                           Some(kind) => {
606                               self.cat_upvar(id, span, var_id, fn_node_id, kind)
607                           }
608                           None => {
609                               if !self.options.during_closure_kind_inference {
610                                   span_bug!(
611                                       span,
612                                       "No closure kind for {:?}",
613                                       closure_id);
614                               }
615
616                               // during closure kind inference, we
617                               // don't know the closure kind yet, but
618                               // it's ok because we detect that we are
619                               // accessing an upvar and handle that
620                               // case specially anyhow. Use Fn
621                               // arbitrarily.
622                               self.cat_upvar(id, span, var_id, fn_node_id, ty::ClosureKind::Fn)
623                           }
624                       }
625                   }
626                   _ => {
627                       span_bug!(
628                           span,
629                           "Upvar of non-closure {} - {:?}",
630                           fn_node_id,
631                           ty);
632                   }
633               }
634           }
635
636           Def::Local(def_id) => {
637             let vid = self.tcx().hir.as_local_node_id(def_id).unwrap();
638             Ok(Rc::new(cmt_ {
639                 id: id,
640                 span: span,
641                 cat: Categorization::Local(vid),
642                 mutbl: MutabilityCategory::from_local(self.tcx(), vid),
643                 ty: expr_ty,
644                 note: NoteNone
645             }))
646           }
647
648           def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
649         }
650     }
651
652     // Categorize an upvar, complete with invisible derefs of closure
653     // environment and upvar reference as appropriate.
654     fn cat_upvar(&self,
655                  id: ast::NodeId,
656                  span: Span,
657                  var_id: ast::NodeId,
658                  fn_node_id: ast::NodeId,
659                  kind: ty::ClosureKind)
660                  -> McResult<cmt<'tcx>>
661     {
662         // An upvar can have up to 3 components. We translate first to a
663         // `Categorization::Upvar`, which is itself a fiction -- it represents the reference to the
664         // field from the environment.
665         //
666         // `Categorization::Upvar`.  Next, we add a deref through the implicit
667         // environment pointer with an anonymous free region 'env and
668         // appropriate borrow kind for closure kinds that take self by
669         // reference.  Finally, if the upvar was captured
670         // by-reference, we add a deref through that reference.  The
671         // region of this reference is an inference variable 'up that
672         // was previously generated and recorded in the upvar borrow
673         // map.  The borrow kind bk is inferred by based on how the
674         // upvar is used.
675         //
676         // This results in the following table for concrete closure
677         // types:
678         //
679         //                | move                 | ref
680         // ---------------+----------------------+-------------------------------
681         // Fn             | copied -> &'env      | upvar -> &'env -> &'up bk
682         // FnMut          | copied -> &'env mut  | upvar -> &'env mut -> &'up bk
683         // FnOnce         | copied               | upvar -> &'up bk
684
685         let upvar_id = ty::UpvarId { var_id: var_id,
686                                      closure_expr_id: fn_node_id };
687         let var_ty = self.node_ty(var_id)?;
688
689         // Mutability of original variable itself
690         let var_mutbl = MutabilityCategory::from_local(self.tcx(), var_id);
691
692         // Construct the upvar. This represents access to the field
693         // from the environment (perhaps we should eventually desugar
694         // this field further, but it will do for now).
695         let cmt_result = cmt_ {
696             id: id,
697             span: span,
698             cat: Categorization::Upvar(Upvar {id: upvar_id, kind: kind}),
699             mutbl: var_mutbl,
700             ty: var_ty,
701             note: NoteNone
702         };
703
704         // If this is a `FnMut` or `Fn` closure, then the above is
705         // conceptually a `&mut` or `&` reference, so we have to add a
706         // deref.
707         let cmt_result = match kind {
708             ty::ClosureKind::FnOnce => {
709                 cmt_result
710             }
711             ty::ClosureKind::FnMut => {
712                 self.env_deref(id, span, upvar_id, var_mutbl, ty::MutBorrow, cmt_result)
713             }
714             ty::ClosureKind::Fn => {
715                 self.env_deref(id, span, upvar_id, var_mutbl, ty::ImmBorrow, cmt_result)
716             }
717         };
718
719         // If this is a by-ref capture, then the upvar we loaded is
720         // actually a reference, so we have to add an implicit deref
721         // for that.
722         let upvar_id = ty::UpvarId { var_id: var_id,
723                                      closure_expr_id: fn_node_id };
724         let upvar_capture = self.infcx.upvar_capture(upvar_id).unwrap();
725         let cmt_result = match upvar_capture {
726             ty::UpvarCapture::ByValue => {
727                 cmt_result
728             }
729             ty::UpvarCapture::ByRef(upvar_borrow) => {
730                 let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region);
731                 cmt_ {
732                     id: id,
733                     span: span,
734                     cat: Categorization::Deref(Rc::new(cmt_result), 0, ptr),
735                     mutbl: MutabilityCategory::from_borrow_kind(upvar_borrow.kind),
736                     ty: var_ty,
737                     note: NoteUpvarRef(upvar_id)
738                 }
739             }
740         };
741
742         let ret = Rc::new(cmt_result);
743         debug!("cat_upvar ret={:?}", ret);
744         Ok(ret)
745     }
746
747     fn env_deref(&self,
748                  id: ast::NodeId,
749                  span: Span,
750                  upvar_id: ty::UpvarId,
751                  upvar_mutbl: MutabilityCategory,
752                  env_borrow_kind: ty::BorrowKind,
753                  cmt_result: cmt_<'tcx>)
754                  -> cmt_<'tcx>
755     {
756         // Look up the node ID of the closure body so we can construct
757         // a free region within it
758         let fn_body_id = {
759             let fn_expr = match self.tcx().hir.find(upvar_id.closure_expr_id) {
760                 Some(hir_map::NodeExpr(e)) => e,
761                 _ => bug!()
762             };
763
764             match fn_expr.node {
765                 hir::ExprClosure(.., body_id, _) => body_id.node_id,
766                 _ => bug!()
767             }
768         };
769
770         // Region of environment pointer
771         let env_region = self.tcx().mk_region(ty::ReFree(ty::FreeRegion {
772             // The environment of a closure is guaranteed to
773             // outlive any bindings introduced in the body of the
774             // closure itself.
775             scope: self.tcx().region_maps.item_extent(fn_body_id),
776             bound_region: ty::BrEnv
777         }));
778
779         let env_ptr = BorrowedPtr(env_borrow_kind, env_region);
780
781         let var_ty = cmt_result.ty;
782
783         // We need to add the env deref.  This means
784         // that the above is actually immutable and
785         // has a ref type.  However, nothing should
786         // actually look at the type, so we can get
787         // away with stuffing a `TyError` in there
788         // instead of bothering to construct a proper
789         // one.
790         let cmt_result = cmt_ {
791             mutbl: McImmutable,
792             ty: self.tcx().types.err,
793             ..cmt_result
794         };
795
796         let mut deref_mutbl = MutabilityCategory::from_borrow_kind(env_borrow_kind);
797
798         // Issue #18335. If variable is declared as immutable, override the
799         // mutability from the environment and substitute an `&T` anyway.
800         match upvar_mutbl {
801             McImmutable => { deref_mutbl = McImmutable; }
802             McDeclared | McInherited => { }
803         }
804
805         let ret = cmt_ {
806             id: id,
807             span: span,
808             cat: Categorization::Deref(Rc::new(cmt_result), 0, env_ptr),
809             mutbl: deref_mutbl,
810             ty: var_ty,
811             note: NoteClosureEnv(upvar_id)
812         };
813
814         debug!("env_deref ret {:?}", ret);
815
816         ret
817     }
818
819     /// Returns the lifetime of a temporary created by expr with id `id`.
820     /// This could be `'static` if `id` is part of a constant expression.
821     pub fn temporary_scope(&self, id: ast::NodeId) -> (&'tcx ty::Region, &'tcx ty::Region)
822     {
823         let (scope, old_scope) =
824             self.tcx().region_maps.old_and_new_temporary_scope(id);
825         (self.tcx().mk_region(match scope {
826             Some(scope) => ty::ReScope(scope),
827             None => ty::ReStatic
828         }),
829          self.tcx().mk_region(match old_scope {
830             Some(scope) => ty::ReScope(scope),
831             None => ty::ReStatic
832         }))
833     }
834
835     pub fn cat_rvalue_node(&self,
836                            id: ast::NodeId,
837                            span: Span,
838                            expr_ty: Ty<'tcx>)
839                            -> cmt<'tcx> {
840         let promotable = self.tcx().rvalue_promotable_to_static.borrow().get(&id).cloned()
841                                    .unwrap_or(false);
842
843         // Only promote `[T; 0]` before an RFC for rvalue promotions
844         // is accepted.
845         let promotable = match expr_ty.sty {
846             ty::TyArray(_, 0) => true,
847             _ => promotable & false
848         };
849
850         // Compute maximum lifetime of this rvalue. This is 'static if
851         // we can promote to a constant, otherwise equal to enclosing temp
852         // lifetime.
853         let (re, old_re) = if promotable {
854             (self.tcx().mk_region(ty::ReStatic),
855              self.tcx().mk_region(ty::ReStatic))
856         } else {
857             self.temporary_scope(id)
858         };
859         let ret = self.cat_rvalue(id, span, re, old_re, expr_ty);
860         debug!("cat_rvalue_node ret {:?}", ret);
861         ret
862     }
863
864     pub fn cat_rvalue(&self,
865                       cmt_id: ast::NodeId,
866                       span: Span,
867                       temp_scope: &'tcx ty::Region,
868                       old_temp_scope: &'tcx ty::Region,
869                       expr_ty: Ty<'tcx>) -> cmt<'tcx> {
870         let ret = Rc::new(cmt_ {
871             id:cmt_id,
872             span:span,
873             cat:Categorization::Rvalue(temp_scope, old_temp_scope),
874             mutbl:McDeclared,
875             ty:expr_ty,
876             note: NoteNone
877         });
878         debug!("cat_rvalue ret {:?}", ret);
879         ret
880     }
881
882     pub fn cat_field<N:ast_node>(&self,
883                                  node: &N,
884                                  base_cmt: cmt<'tcx>,
885                                  f_name: ast::Name,
886                                  f_ty: Ty<'tcx>)
887                                  -> cmt<'tcx> {
888         let ret = Rc::new(cmt_ {
889             id: node.id(),
890             span: node.span(),
891             mutbl: base_cmt.mutbl.inherit(),
892             cat: Categorization::Interior(base_cmt, InteriorField(NamedField(f_name))),
893             ty: f_ty,
894             note: NoteNone
895         });
896         debug!("cat_field ret {:?}", ret);
897         ret
898     }
899
900     pub fn cat_tup_field<N:ast_node>(&self,
901                                      node: &N,
902                                      base_cmt: cmt<'tcx>,
903                                      f_idx: usize,
904                                      f_ty: Ty<'tcx>)
905                                      -> cmt<'tcx> {
906         let ret = Rc::new(cmt_ {
907             id: node.id(),
908             span: node.span(),
909             mutbl: base_cmt.mutbl.inherit(),
910             cat: Categorization::Interior(base_cmt, InteriorField(PositionalField(f_idx))),
911             ty: f_ty,
912             note: NoteNone
913         });
914         debug!("cat_tup_field ret {:?}", ret);
915         ret
916     }
917
918     fn cat_deref<N:ast_node>(&self,
919                              node: &N,
920                              base_cmt: cmt<'tcx>,
921                              deref_cnt: usize)
922                              -> McResult<cmt<'tcx>> {
923         let method_call = ty::MethodCall {
924             expr_id: node.id(),
925             autoderef: deref_cnt as u32
926         };
927         let method_ty = self.infcx.node_method_ty(method_call);
928
929         debug!("cat_deref: method_call={:?} method_ty={:?}",
930                method_call, method_ty.map(|ty| ty));
931
932         let base_cmt = match method_ty {
933             Some(method_ty) => {
934                 let ref_ty =
935                     self.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap();
936                 self.cat_rvalue_node(node.id(), node.span(), ref_ty)
937             }
938             None => base_cmt
939         };
940         let base_cmt_ty = base_cmt.ty;
941         match base_cmt_ty.builtin_deref(true, ty::NoPreference) {
942             Some(mt) => {
943                 let ret = self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty, false);
944                 debug!("cat_deref ret {:?}", ret);
945                 Ok(ret)
946             }
947             None => {
948                 debug!("Explicit deref of non-derefable type: {:?}",
949                        base_cmt_ty);
950                 return Err(());
951             }
952         }
953     }
954
955     fn cat_deref_common<N:ast_node>(&self,
956                                     node: &N,
957                                     base_cmt: cmt<'tcx>,
958                                     deref_cnt: usize,
959                                     deref_ty: Ty<'tcx>,
960                                     implicit: bool)
961                                     -> cmt<'tcx>
962     {
963         let ptr = match base_cmt.ty.sty {
964             ty::TyAdt(def, ..) if def.is_box() => Unique,
965             ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
966             ty::TyRef(r, mt) => {
967                 let bk = ty::BorrowKind::from_mutbl(mt.mutbl);
968                 if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
969             }
970             ref ty => bug!("unexpected type in cat_deref_common: {:?}", ty)
971         };
972         let ret = Rc::new(cmt_ {
973             id: node.id(),
974             span: node.span(),
975             // For unique ptrs, we inherit mutability from the owning reference.
976             mutbl: MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
977             cat: Categorization::Deref(base_cmt, deref_cnt, ptr),
978             ty: deref_ty,
979             note: NoteNone
980         });
981         debug!("cat_deref_common ret {:?}", ret);
982         ret
983     }
984
985     pub fn cat_index<N:ast_node>(&self,
986                                  elt: &N,
987                                  mut base_cmt: cmt<'tcx>,
988                                  context: InteriorOffsetKind)
989                                  -> McResult<cmt<'tcx>> {
990         //! Creates a cmt for an indexing operation (`[]`).
991         //!
992         //! One subtle aspect of indexing that may not be
993         //! immediately obvious: for anything other than a fixed-length
994         //! vector, an operation like `x[y]` actually consists of two
995         //! disjoint (from the point of view of borrowck) operations.
996         //! The first is a deref of `x` to create a pointer `p` that points
997         //! at the first element in the array. The second operation is
998         //! an index which adds `y*sizeof(T)` to `p` to obtain the
999         //! pointer to `x[y]`. `cat_index` will produce a resulting
1000         //! cmt containing both this deref and the indexing,
1001         //! presuming that `base_cmt` is not of fixed-length type.
1002         //!
1003         //! # Parameters
1004         //! - `elt`: the AST node being indexed
1005         //! - `base_cmt`: the cmt of `elt`
1006
1007         let method_call = ty::MethodCall::expr(elt.id());
1008         let method_ty = self.infcx.node_method_ty(method_call);
1009
1010         let (element_ty, element_kind) = match method_ty {
1011             Some(method_ty) => {
1012                 let ref_ty = self.overloaded_method_return_ty(method_ty);
1013                 base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
1014
1015                 (ref_ty.builtin_deref(false, ty::NoPreference).unwrap().ty,
1016                  ElementKind::OtherElement)
1017             }
1018             None => {
1019                 match base_cmt.ty.builtin_index() {
1020                     Some(ty) => (ty, ElementKind::VecElement),
1021                     None => {
1022                         return Err(());
1023                     }
1024                 }
1025             }
1026         };
1027
1028         let interior_elem = InteriorElement(context, element_kind);
1029         let ret =
1030             self.cat_imm_interior(elt, base_cmt.clone(), element_ty, interior_elem);
1031         debug!("cat_index ret {:?}", ret);
1032         return Ok(ret);
1033     }
1034
1035     pub fn cat_imm_interior<N:ast_node>(&self,
1036                                         node: &N,
1037                                         base_cmt: cmt<'tcx>,
1038                                         interior_ty: Ty<'tcx>,
1039                                         interior: InteriorKind)
1040                                         -> cmt<'tcx> {
1041         let ret = Rc::new(cmt_ {
1042             id: node.id(),
1043             span: node.span(),
1044             mutbl: base_cmt.mutbl.inherit(),
1045             cat: Categorization::Interior(base_cmt, interior),
1046             ty: interior_ty,
1047             note: NoteNone
1048         });
1049         debug!("cat_imm_interior ret={:?}", ret);
1050         ret
1051     }
1052
1053     pub fn cat_downcast<N:ast_node>(&self,
1054                                     node: &N,
1055                                     base_cmt: cmt<'tcx>,
1056                                     downcast_ty: Ty<'tcx>,
1057                                     variant_did: DefId)
1058                                     -> cmt<'tcx> {
1059         let ret = Rc::new(cmt_ {
1060             id: node.id(),
1061             span: node.span(),
1062             mutbl: base_cmt.mutbl.inherit(),
1063             cat: Categorization::Downcast(base_cmt, variant_did),
1064             ty: downcast_ty,
1065             note: NoteNone
1066         });
1067         debug!("cat_downcast ret={:?}", ret);
1068         ret
1069     }
1070
1071     pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
1072         where F: FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat),
1073     {
1074         self.cat_pattern_(cmt, pat, &mut op)
1075     }
1076
1077     // FIXME(#19596) This is a workaround, but there should be a better way to do this
1078     fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()>
1079         where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat)
1080     {
1081         // Here, `cmt` is the categorization for the value being
1082         // matched and pat is the pattern it is being matched against.
1083         //
1084         // In general, the way that this works is that we walk down
1085         // the pattern, constructing a cmt that represents the path
1086         // that will be taken to reach the value being matched.
1087         //
1088         // When we encounter named bindings, we take the cmt that has
1089         // been built up and pass it off to guarantee_valid() so that
1090         // we can be sure that the binding will remain valid for the
1091         // duration of the arm.
1092         //
1093         // (*2) There is subtlety concerning the correspondence between
1094         // pattern ids and types as compared to *expression* ids and
1095         // types. This is explained briefly. on the definition of the
1096         // type `cmt`, so go off and read what it says there, then
1097         // come back and I'll dive into a bit more detail here. :) OK,
1098         // back?
1099         //
1100         // In general, the id of the cmt should be the node that
1101         // "produces" the value---patterns aren't executable code
1102         // exactly, but I consider them to "execute" when they match a
1103         // value, and I consider them to produce the value that was
1104         // matched. So if you have something like:
1105         //
1106         //     let x = @@3;
1107         //     match x {
1108         //       @@y { ... }
1109         //     }
1110         //
1111         // In this case, the cmt and the relevant ids would be:
1112         //
1113         //     CMT             Id                  Type of Id Type of cmt
1114         //
1115         //     local(x)->@->@
1116         //     ^~~~~~~^        `x` from discr      @@int      @@int
1117         //     ^~~~~~~~~~^     `@@y` pattern node  @@int      @int
1118         //     ^~~~~~~~~~~~~^  `@y` pattern node   @int       int
1119         //
1120         // You can see that the types of the id and the cmt are in
1121         // sync in the first line, because that id is actually the id
1122         // of an expression. But once we get to pattern ids, the types
1123         // step out of sync again. So you'll see below that we always
1124         // get the type of the *subpattern* and use that.
1125
1126         debug!("cat_pattern: {:?} cmt={:?}", pat, cmt);
1127
1128         op(self, cmt.clone(), pat);
1129
1130         // Note: This goes up here (rather than within the PatKind::TupleStruct arm
1131         // alone) because PatKind::Struct can also refer to variants.
1132         let cmt = match pat.node {
1133             PatKind::Path(hir::QPath::Resolved(_, ref path)) |
1134             PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
1135             PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
1136                 match path.def {
1137                     Def::Err => return Err(()),
1138                     Def::Variant(variant_did) |
1139                     Def::VariantCtor(variant_did, ..) => {
1140                         // univariant enums do not need downcasts
1141                         let enum_did = self.tcx().parent_def_id(variant_did).unwrap();
1142                         if !self.tcx().lookup_adt_def(enum_did).is_univariant() {
1143                             self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
1144                         } else {
1145                             cmt
1146                         }
1147                     }
1148                     _ => cmt
1149                 }
1150             }
1151             _ => cmt
1152         };
1153
1154         match pat.node {
1155           PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
1156             let def = self.infcx.tables.borrow().qpath_def(qpath, pat.id);
1157             let expected_len = match def {
1158                 Def::VariantCtor(def_id, CtorKind::Fn) => {
1159                     let enum_def = self.tcx().parent_def_id(def_id).unwrap();
1160                     self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
1161                 }
1162                 Def::StructCtor(_, CtorKind::Fn) => {
1163                     match self.pat_ty(&pat)?.sty {
1164                         ty::TyAdt(adt_def, _) => {
1165                             adt_def.struct_variant().fields.len()
1166                         }
1167                         ref ty => {
1168                             span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
1169                         }
1170                     }
1171                 }
1172                 def => {
1173                     span_bug!(pat.span, "tuple struct pattern didn't resolve \
1174                                          to variant or struct {:?}", def);
1175                 }
1176             };
1177
1178             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
1179                 let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
1180                 let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
1181                                                    InteriorField(PositionalField(i)));
1182                 self.cat_pattern_(subcmt, &subpat, op)?;
1183             }
1184           }
1185
1186           PatKind::Struct(_, ref field_pats, _) => {
1187             // {f1: p1, ..., fN: pN}
1188             for fp in field_pats {
1189                 let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2)
1190                 let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty);
1191                 self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
1192             }
1193           }
1194
1195           PatKind::Binding(.., Some(ref subpat)) => {
1196               self.cat_pattern_(cmt, &subpat, op)?;
1197           }
1198
1199           PatKind::Tuple(ref subpats, ddpos) => {
1200             // (p1, ..., pN)
1201             let expected_len = match self.pat_ty(&pat)?.sty {
1202                 ty::TyTuple(ref tys, _) => tys.len(),
1203                 ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
1204             };
1205             for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
1206                 let subpat_ty = self.pat_ty(&subpat)?; // see (*2)
1207                 let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty,
1208                                                    InteriorField(PositionalField(i)));
1209                 self.cat_pattern_(subcmt, &subpat, op)?;
1210             }
1211           }
1212
1213           PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => {
1214             // box p1, &p1, &mut p1.  we can ignore the mutability of
1215             // PatKind::Ref since that information is already contained
1216             // in the type.
1217             let subcmt = self.cat_deref(pat, cmt, 0)?;
1218             self.cat_pattern_(subcmt, &subpat, op)?;
1219           }
1220
1221           PatKind::Slice(ref before, ref slice, ref after) => {
1222             let context = InteriorOffsetKind::Pattern;
1223             let elt_cmt = self.cat_index(pat, cmt, context)?;
1224             for before_pat in before {
1225                 self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
1226             }
1227             if let Some(ref slice_pat) = *slice {
1228                 self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
1229             }
1230             for after_pat in after {
1231                 self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
1232             }
1233           }
1234
1235           PatKind::Path(_) | PatKind::Binding(.., None) |
1236           PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
1237             // always ok
1238           }
1239         }
1240
1241         Ok(())
1242     }
1243
1244     fn overloaded_method_return_ty(&self,
1245                                    method_ty: Ty<'tcx>)
1246                                    -> Ty<'tcx>
1247     {
1248         // When we process an overloaded `*` or `[]` etc, we often
1249         // need to extract the return type of the method. These method
1250         // types are generated by method resolution and always have
1251         // all late-bound regions fully instantiated, so we just want
1252         // to skip past the binder.
1253         self.tcx().no_late_bound_regions(&method_ty.fn_ret())
1254            .unwrap()
1255     }
1256 }
1257
1258 #[derive(Clone, Debug)]
1259 pub enum Aliasability {
1260     FreelyAliasable(AliasableReason),
1261     NonAliasable,
1262     ImmutableUnique(Box<Aliasability>),
1263 }
1264
1265 #[derive(Copy, Clone, Debug)]
1266 pub enum AliasableReason {
1267     AliasableBorrowed,
1268     AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env
1269     AliasableOther,
1270     UnaliasableImmutable, // Created as needed upon seeing ImmutableUnique
1271     AliasableStatic,
1272     AliasableStaticMut,
1273 }
1274
1275 impl<'tcx> cmt_<'tcx> {
1276     pub fn guarantor(&self) -> cmt<'tcx> {
1277         //! Returns `self` after stripping away any derefs or
1278         //! interior content. The return value is basically the `cmt` which
1279         //! determines how long the value in `self` remains live.
1280
1281         match self.cat {
1282             Categorization::Rvalue(..) |
1283             Categorization::StaticItem |
1284             Categorization::Local(..) |
1285             Categorization::Deref(.., UnsafePtr(..)) |
1286             Categorization::Deref(.., BorrowedPtr(..)) |
1287             Categorization::Deref(.., Implicit(..)) |
1288             Categorization::Upvar(..) => {
1289                 Rc::new((*self).clone())
1290             }
1291             Categorization::Downcast(ref b, _) |
1292             Categorization::Interior(ref b, _) |
1293             Categorization::Deref(ref b, _, Unique) => {
1294                 b.guarantor()
1295             }
1296         }
1297     }
1298
1299     /// Returns `FreelyAliasable(_)` if this lvalue represents a freely aliasable pointer type.
1300     pub fn freely_aliasable(&self) -> Aliasability {
1301         // Maybe non-obvious: copied upvars can only be considered
1302         // non-aliasable in once closures, since any other kind can be
1303         // aliased and eventually recused.
1304
1305         match self.cat {
1306             Categorization::Deref(ref b, _, BorrowedPtr(ty::MutBorrow, _)) |
1307             Categorization::Deref(ref b, _, Implicit(ty::MutBorrow, _)) |
1308             Categorization::Deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
1309             Categorization::Deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) |
1310             Categorization::Downcast(ref b, _) |
1311             Categorization::Interior(ref b, _) => {
1312                 // Aliasability depends on base cmt
1313                 b.freely_aliasable()
1314             }
1315
1316             Categorization::Deref(ref b, _, Unique) => {
1317                 let sub = b.freely_aliasable();
1318                 if b.mutbl.is_mutable() {
1319                     // Aliasability depends on base cmt alone
1320                     sub
1321                 } else {
1322                     // Do not allow mutation through an immutable box.
1323                     ImmutableUnique(Box::new(sub))
1324                 }
1325             }
1326
1327             Categorization::Rvalue(..) |
1328             Categorization::Local(..) |
1329             Categorization::Upvar(..) |
1330             Categorization::Deref(.., UnsafePtr(..)) => { // yes, it's aliasable, but...
1331                 NonAliasable
1332             }
1333
1334             Categorization::StaticItem => {
1335                 if self.mutbl.is_mutable() {
1336                     FreelyAliasable(AliasableStaticMut)
1337                 } else {
1338                     FreelyAliasable(AliasableStatic)
1339                 }
1340             }
1341
1342             Categorization::Deref(ref base, _, BorrowedPtr(ty::ImmBorrow, _)) |
1343             Categorization::Deref(ref base, _, Implicit(ty::ImmBorrow, _)) => {
1344                 match base.cat {
1345                     Categorization::Upvar(Upvar{ id, .. }) =>
1346                         FreelyAliasable(AliasableClosure(id.closure_expr_id)),
1347                     _ => FreelyAliasable(AliasableBorrowed)
1348                 }
1349             }
1350         }
1351     }
1352
1353     // Digs down through one or two layers of deref and grabs the cmt
1354     // for the upvar if a note indicates there is one.
1355     pub fn upvar(&self) -> Option<cmt<'tcx>> {
1356         match self.note {
1357             NoteClosureEnv(..) | NoteUpvarRef(..) => {
1358                 Some(match self.cat {
1359                     Categorization::Deref(ref inner, ..) => {
1360                         match inner.cat {
1361                             Categorization::Deref(ref inner, ..) => inner.clone(),
1362                             Categorization::Upvar(..) => inner.clone(),
1363                             _ => bug!()
1364                         }
1365                     }
1366                     _ => bug!()
1367                 })
1368             }
1369             NoteNone => None
1370         }
1371     }
1372
1373
1374     pub fn descriptive_string(&self, tcx: TyCtxt) -> String {
1375         match self.cat {
1376             Categorization::StaticItem => {
1377                 "static item".to_string()
1378             }
1379             Categorization::Rvalue(..) => {
1380                 "non-lvalue".to_string()
1381             }
1382             Categorization::Local(vid) => {
1383                 if tcx.hir.is_argument(vid) {
1384                     "argument".to_string()
1385                 } else {
1386                     "local variable".to_string()
1387                 }
1388             }
1389             Categorization::Deref(.., pk) => {
1390                 let upvar = self.upvar();
1391                 match upvar.as_ref().map(|i| &i.cat) {
1392                     Some(&Categorization::Upvar(ref var)) => {
1393                         var.to_string()
1394                     }
1395                     Some(_) => bug!(),
1396                     None => {
1397                         match pk {
1398                             Implicit(..) => {
1399                                 format!("indexed content")
1400                             }
1401                             Unique => {
1402                                 format!("`Box` content")
1403                             }
1404                             UnsafePtr(..) => {
1405                                 format!("dereference of raw pointer")
1406                             }
1407                             BorrowedPtr(..) => {
1408                                 format!("borrowed content")
1409                             }
1410                         }
1411                     }
1412                 }
1413             }
1414             Categorization::Interior(_, InteriorField(NamedField(_))) => {
1415                 "field".to_string()
1416             }
1417             Categorization::Interior(_, InteriorField(PositionalField(_))) => {
1418                 "anonymous field".to_string()
1419             }
1420             Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index,
1421                                                         VecElement)) |
1422             Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index,
1423                                                         OtherElement)) => {
1424                 "indexed content".to_string()
1425             }
1426             Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Pattern,
1427                                                         VecElement)) |
1428             Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Pattern,
1429                                                         OtherElement)) => {
1430                 "pattern-bound indexed content".to_string()
1431             }
1432             Categorization::Upvar(ref var) => {
1433                 var.to_string()
1434             }
1435             Categorization::Downcast(ref cmt, _) => {
1436                 cmt.descriptive_string(tcx)
1437             }
1438         }
1439     }
1440 }
1441
1442 impl<'tcx> fmt::Debug for cmt_<'tcx> {
1443     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1444         write!(f, "{{{:?} id:{} m:{:?} ty:{:?}}}",
1445                self.cat,
1446                self.id,
1447                self.mutbl,
1448                self.ty)
1449     }
1450 }
1451
1452 impl<'tcx> fmt::Debug for Categorization<'tcx> {
1453     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1454         match *self {
1455             Categorization::StaticItem => write!(f, "static"),
1456             Categorization::Rvalue(r, or) => {
1457                 write!(f, "rvalue({:?}, {:?})", r, or)
1458             }
1459             Categorization::Local(id) => {
1460                let name = ty::tls::with(|tcx| tcx.local_var_name_str(id));
1461                write!(f, "local({})", name)
1462             }
1463             Categorization::Upvar(upvar) => {
1464                 write!(f, "upvar({:?})", upvar)
1465             }
1466             Categorization::Deref(ref cmt, derefs, ptr) => {
1467                 write!(f, "{:?}-{:?}{}->", cmt.cat, ptr, derefs)
1468             }
1469             Categorization::Interior(ref cmt, interior) => {
1470                 write!(f, "{:?}.{:?}", cmt.cat, interior)
1471             }
1472             Categorization::Downcast(ref cmt, _) => {
1473                 write!(f, "{:?}->(enum)", cmt.cat)
1474             }
1475         }
1476     }
1477 }
1478
1479 pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
1480     match ptr {
1481         Unique => "Box",
1482         BorrowedPtr(ty::ImmBorrow, _) |
1483         Implicit(ty::ImmBorrow, _) => "&",
1484         BorrowedPtr(ty::MutBorrow, _) |
1485         Implicit(ty::MutBorrow, _) => "&mut",
1486         BorrowedPtr(ty::UniqueImmBorrow, _) |
1487         Implicit(ty::UniqueImmBorrow, _) => "&unique",
1488         UnsafePtr(_) => "*",
1489     }
1490 }
1491
1492 impl<'tcx> fmt::Debug for PointerKind<'tcx> {
1493     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1494         match *self {
1495             Unique => write!(f, "Box"),
1496             BorrowedPtr(ty::ImmBorrow, ref r) |
1497             Implicit(ty::ImmBorrow, ref r) => {
1498                 write!(f, "&{:?}", r)
1499             }
1500             BorrowedPtr(ty::MutBorrow, ref r) |
1501             Implicit(ty::MutBorrow, ref r) => {
1502                 write!(f, "&{:?} mut", r)
1503             }
1504             BorrowedPtr(ty::UniqueImmBorrow, ref r) |
1505             Implicit(ty::UniqueImmBorrow, ref r) => {
1506                 write!(f, "&{:?} uniq", r)
1507             }
1508             UnsafePtr(_) => write!(f, "*")
1509         }
1510     }
1511 }
1512
1513 impl fmt::Debug for InteriorKind {
1514     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1515         match *self {
1516             InteriorField(NamedField(fld)) => write!(f, "{}", fld),
1517             InteriorField(PositionalField(i)) => write!(f, "#{}", i),
1518             InteriorElement(..) => write!(f, "[]"),
1519         }
1520     }
1521 }
1522
1523 impl fmt::Debug for Upvar {
1524     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1525         write!(f, "{:?}/{:?}", self.id, self.kind)
1526     }
1527 }
1528
1529 impl fmt::Display for Upvar {
1530     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1531         let kind = match self.kind {
1532             ty::ClosureKind::Fn => "Fn",
1533             ty::ClosureKind::FnMut => "FnMut",
1534             ty::ClosureKind::FnOnce => "FnOnce",
1535         };
1536         write!(f, "captured outer variable in an `{}` closure", kind)
1537     }
1538 }