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