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