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