1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12 * # Categorization
13 *
14 * The job of the categorization module is to analyze an expression to
15 * determine what kind of memory is used in evaluating it (for example,
16 * where dereferences occur and what kind of pointer is dereferenced;
17 * whether the memory is mutable; etc)
18 *
19 * Categorization effectively transforms all of our expressions into
20 * expressions of the following forms (the actual enum has many more
21 * possibilities, naturally, but they are all variants of these base
22 * forms):
23 *
24 * E = rvalue // some computed rvalue
25 * | x // address of a local variable or argument
26 * | *E // deref of a ptr
27 * | E.comp // access to an interior component
28 *
29 * Imagine a routine ToAddr(Expr) that evaluates an expression and returns an
30 * address where the result is to be found. If Expr is an lvalue, then this
31 * is the address of the lvalue. If Expr is an rvalue, this is the address of
32 * some temporary spot in memory where the result is stored.
33 *
34 * Now, cat_expr() classies the expression Expr and the address A=ToAddr(Expr)
35 * as follows:
36 *
37 * - cat: what kind of expression was this? This is a subset of the
38 * full expression forms which only includes those that we care about
39 * for the purpose of the analysis.
40 * - mutbl: mutability of the address A
41 * - ty: the type of data found at the address A
42 *
43 * The resulting categorization tree differs somewhat from the expressions
44 * themselves. For example, auto-derefs are explicit. Also, an index a[b] is
45 * decomposed into two operations: a derefence to reach the array data and
46 * then an index to jump forward to the relevant item.
47 *
48 * ## By-reference upvars
49 *
50 * One part of the translation which may be non-obvious is that we translate
51 * closure upvars into the dereference of a borrowed pointer; this more closely
52 * resembles the runtime translation. So, for example, if we had:
53 *
54 * let mut x = 3;
55 * let y = 5;
56 * let inc = || x += y;
57 *
58 * Then when we categorize `x` (*within* the closure) we would yield a
59 * result of `*x'`, effectively, where `x'` is a `cat_upvar` reference
60 * tied to `x`. The type of `x'` will be a borrowed pointer.
61 */
62
63 #![allow(non_camel_case_types)]
64
65 use middle::ty;
66 use middle::typeck;
67 use util::nodemap::NodeMap;
68 use util::ppaux::{ty_to_str, Repr};
69
70 use syntax::ast::{MutImmutable, MutMutable};
71 use syntax::ast;
72 use syntax::codemap::Span;
73 use syntax::print::pprust;
74 use syntax::parse::token;
75
76 use std::cell::RefCell;
77 use std::rc::Rc;
78
79 #[deriving(Clone, Eq)]
80 pub enum categorization {
81 cat_rvalue(ty::Region), // temporary val, argument is its scope
82 cat_static_item,
83 cat_copied_upvar(CopiedUpvar), // upvar copied into proc env
84 cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure
85 cat_local(ast::NodeId), // local variable
86 cat_arg(ast::NodeId), // formal argument
87 cat_deref(cmt, uint, PointerKind), // deref of a ptr
88 cat_interior(cmt, InteriorKind), // something interior: field, tuple, etc
89 cat_downcast(cmt), // selects a particular enum variant (*1)
90 cat_discr(cmt, ast::NodeId), // match discriminant (see preserve())
91
92 // (*1) downcast is only required if the enum has more than one variant
93 }
94
95 #[deriving(Clone, Eq)]
96 pub struct CopiedUpvar {
97 pub upvar_id: ast::NodeId,
98 pub onceness: ast::Onceness,
99 }
100
101 // different kinds of pointers:
102 #[deriving(Clone, Eq, TotalEq, Hash)]
103 pub enum PointerKind {
104 OwnedPtr,
105 GcPtr,
106 BorrowedPtr(ty::BorrowKind, ty::Region),
107 UnsafePtr(ast::Mutability),
108 }
109
110 // We use the term "interior" to mean "something reachable from the
111 // base without a pointer dereference", e.g. a field
112 #[deriving(Clone, Eq, TotalEq, Hash)]
113 pub enum InteriorKind {
114 InteriorField(FieldName),
115 InteriorElement(ElementKind),
116 }
117
118 #[deriving(Clone, Eq, TotalEq, Hash)]
119 pub enum FieldName {
120 NamedField(ast::Name),
121 PositionalField(uint)
122 }
123
124 #[deriving(Clone, Eq, TotalEq, Hash)]
125 pub enum ElementKind {
126 VecElement,
127 StrElement,
128 OtherElement,
129 }
130
131 #[deriving(Clone, Eq, TotalEq, Hash, Show)]
132 pub enum MutabilityCategory {
133 McImmutable, // Immutable.
134 McDeclared, // Directly declared as mutable.
135 McInherited, // Inherited from the fact that owner is mutable.
136 }
137
138 // `cmt`: "Category, Mutability, and Type".
139 //
140 // a complete categorization of a value indicating where it originated
141 // and how it is located, as well as the mutability of the memory in
142 // which the value is stored.
143 //
144 // *WARNING* The field `cmt.type` is NOT necessarily the same as the
145 // result of `node_id_to_type(cmt.id)`. This is because the `id` is
146 // always the `id` of the node producing the type; in an expression
147 // like `*x`, the type of this deref node is the deref'd type (`T`),
148 // but in a pattern like `@x`, the `@x` pattern is again a
149 // dereference, but its type is the type *before* the dereference
150 // (`@T`). So use `cmt.type` to find the type of the value in a consistent
151 // fashion. For more details, see the method `cat_pattern`
152 #[deriving(Clone, Eq)]
153 pub struct cmt_ {
154 pub id: ast::NodeId, // id of expr/pat producing this value
155 pub span: Span, // span of same expr/pat
156 pub cat: categorization, // categorization of expr
157 pub mutbl: MutabilityCategory, // mutability of expr as lvalue
158 pub ty: ty::t // type of the expr (*see WARNING above*)
159 }
160
161 pub type cmt = Rc<cmt_>;
162
163 // We pun on *T to mean both actual deref of a ptr as well
164 // as accessing of components:
165 pub enum deref_kind {
166 deref_ptr(PointerKind),
167 deref_interior(InteriorKind),
168 }
169
170 // Categorizes a derefable type. Note that we include vectors and strings as
171 // derefable (we model an index as the combination of a deref and then a
172 // pointer adjustment).
173 pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
174 match ty::get(t).sty {
175 ty::ty_uniq(_) |
176 ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) |
177 ty::ty_closure(box ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
178 Some(deref_ptr(OwnedPtr))
179 }
180
181 ty::ty_rptr(r, mt) => {
182 let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
183 Some(deref_ptr(BorrowedPtr(kind, r)))
184 }
185 ty::ty_trait(box ty::TyTrait {
186 store: ty::RegionTraitStore(r, mutbl),
187 ..
188 }) => {
189 let kind = ty::BorrowKind::from_mutbl(mutbl);
190 Some(deref_ptr(BorrowedPtr(kind, r)))
191 }
192
193 ty::ty_closure(box ty::ClosureTy {
194 store: ty::RegionTraitStore(r, _),
195 ..
196 }) => {
197 Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
198 }
199
200 ty::ty_box(..) => {
201 Some(deref_ptr(GcPtr))
202 }
203
204 ty::ty_ptr(ref mt) => {
205 Some(deref_ptr(UnsafePtr(mt.mutbl)))
206 }
207
208 ty::ty_enum(..) |
209 ty::ty_struct(..) => { // newtype
210 Some(deref_interior(InteriorField(PositionalField(0))))
211 }
212
213 ty::ty_vec(_, Some(_)) => {
214 Some(deref_interior(InteriorElement(element_kind(t))))
215 }
216
217 _ => None
218 }
219 }
220
221 pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind {
222 match opt_deref_kind(t) {
223 Some(k) => k,
224 None => {
225 tcx.sess.bug(
226 format!("deref_cat() invoked on non-derefable type {}",
227 ty_to_str(tcx, t)));
228 }
229 }
230 }
231
232 trait ast_node {
233 fn id(&self) -> ast::NodeId;
234 fn span(&self) -> Span;
235 }
236
237 impl ast_node for ast::Expr {
238 fn id(&self) -> ast::NodeId { self.id }
239 fn span(&self) -> Span { self.span }
240 }
241
242 impl ast_node for ast::Pat {
243 fn id(&self) -> ast::NodeId { self.id }
244 fn span(&self) -> Span { self.span }
245 }
246
247 pub struct MemCategorizationContext<'t,TYPER> {
248 typer: &'t TYPER
249 }
250
251 pub type McResult<T> = Result<T, ()>;
252
253 /**
254 * The `Typer` trait provides the interface for the mem-categorization
255 * module to the results of the type check. It can be used to query
256 * the type assigned to an expression node, to inquire after adjustments,
257 * and so on.
258 *
259 * This interface is needed because mem-categorization is used from
260 * two places: `regionck` and `borrowck`. `regionck` executes before
261 * type inference is complete, and hence derives types and so on from
262 * intermediate tables. This also implies that type errors can occur,
263 * and hence `node_ty()` and friends return a `Result` type -- any
264 * error will propagate back up through the mem-categorization
265 * routines.
266 *
267 * In the borrow checker, in contrast, type checking is complete and we
268 * know that no errors have occurred, so we simply consult the tcx and we
269 * can be sure that only `Ok` results will occur.
270 */
271 pub trait Typer {
272 fn tcx<'a>(&'a self) -> &'a ty::ctxt;
273 fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t>;
274 fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t>;
275 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>>;
276 fn is_method_call(&self, id: ast::NodeId) -> bool;
277 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
278 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
279 }
280
281 impl MutabilityCategory {
282 pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory {
283 match m {
284 MutImmutable => McImmutable,
285 MutMutable => McDeclared
286 }
287 }
288
289 pub fn from_borrow_kind(borrow_kind: ty::BorrowKind) -> MutabilityCategory {
290 match borrow_kind {
291 ty::ImmBorrow => McImmutable,
292 ty::UniqueImmBorrow => McImmutable,
293 ty::MutBorrow => McDeclared,
294 }
295 }
296
297 pub fn from_pointer_kind(base_mutbl: MutabilityCategory,
298 ptr: PointerKind) -> MutabilityCategory {
299 match ptr {
300 OwnedPtr => {
301 base_mutbl.inherit()
302 }
303 BorrowedPtr(borrow_kind, _) => {
304 MutabilityCategory::from_borrow_kind(borrow_kind)
305 }
306 GcPtr => {
307 McImmutable
308 }
309 UnsafePtr(m) => {
310 MutabilityCategory::from_mutbl(m)
311 }
312 }
313 }
314
315 pub fn inherit(&self) -> MutabilityCategory {
316 match *self {
317 McImmutable => McImmutable,
318 McDeclared => McInherited,
319 McInherited => McInherited,
320 }
321 }
322
323 pub fn is_mutable(&self) -> bool {
324 match *self {
325 McImmutable => false,
326 McInherited => true,
327 McDeclared => true,
328 }
329 }
330
331 pub fn is_immutable(&self) -> bool {
332 match *self {
333 McImmutable => true,
334 McDeclared | McInherited => false
335 }
336 }
337
338 pub fn to_user_str(&self) -> &'static str {
339 match *self {
340 McDeclared | McInherited => "mutable",
341 McImmutable => "immutable",
342 }
343 }
344 }
345
346 macro_rules! if_ok(
347 ($inp: expr) => (
348 match $inp {
349 Ok(v) => { v }
350 Err(e) => { return Err(e); }
351 }
352 )
353 )
354
355 impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
356 pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
357 MemCategorizationContext { typer: typer }
358 }
359
360 fn tcx(&self) -> &'t ty::ctxt {
361 self.typer.tcx()
362 }
363
364 fn expr_ty(&self, expr: &ast::Expr) -> McResult<ty::t> {
365 self.typer.node_ty(expr.id)
366 }
367
368 fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<ty::t> {
369 let unadjusted_ty = if_ok!(self.expr_ty(expr));
370 Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
371 self.typer.adjustments().borrow().find(&expr.id),
372 |method_call| self.typer.node_method_ty(method_call)))
373 }
374
375 fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
376 self.typer.node_ty(id)
377 }
378
379 fn pat_ty(&self, pat: &ast::Pat) -> McResult<ty::t> {
380 self.typer.node_ty(pat.id)
381 }
382
383 pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt> {
384 match self.typer.adjustments().borrow().find(&expr.id) {
385 None => {
386 // No adjustments.
387 self.cat_expr_unadjusted(expr)
388 }
389
390 Some(adjustment) => {
391 match *adjustment {
392 ty::AutoObject(..) => {
393 // Implicity casts a concrete object to trait object
394 // so just patch up the type
395 let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
396 let mut expr_cmt = (*if_ok!(self.cat_expr_unadjusted(expr))).clone();
397 expr_cmt.ty = expr_ty;
398 Ok(Rc::new(expr_cmt))
399 }
400
401 ty::AutoAddEnv(..) => {
402 // Convert a bare fn to a closure by adding NULL env.
403 // Result is an rvalue.
404 let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
405 Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
406 }
407
408 ty::AutoDerefRef(
409 ty::AutoDerefRef {
410 autoref: Some(_), ..}) => {
411 // Equivalent to &*expr or something similar.
412 // Result is an rvalue.
413 let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
414 Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
415 }
416
417 ty::AutoDerefRef(
418 ty::AutoDerefRef {
419 autoref: None, autoderefs: autoderefs}) => {
420 // Equivalent to *expr or something similar.
421 self.cat_expr_autoderefd(expr, autoderefs)
422 }
423 }
424 }
425 }
426 }
427
428 pub fn cat_expr_autoderefd(&self,
429 expr: &ast::Expr,
430 autoderefs: uint)
431 -> McResult<cmt> {
432 let mut cmt = if_ok!(self.cat_expr_unadjusted(expr));
433 for deref in range(1u, autoderefs + 1) {
434 cmt = self.cat_deref(expr, cmt, deref);
435 }
436 return Ok(cmt);
437 }
438
439 pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt> {
440 debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
441
442 let expr_ty = if_ok!(self.expr_ty(expr));
443 match expr.node {
444 ast::ExprUnary(ast::UnDeref, e_base) => {
445 let base_cmt = if_ok!(self.cat_expr(e_base));
446 Ok(self.cat_deref(expr, base_cmt, 0))
447 }
448
449 ast::ExprField(base, f_name, _) => {
450 let base_cmt = if_ok!(self.cat_expr(base));
451 Ok(self.cat_field(expr, base_cmt, f_name, expr_ty))
452 }
453
454 ast::ExprIndex(base, _) => {
455 if self.typer.is_method_call(expr.id) {
456 return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
457 }
458
459 let base_cmt = if_ok!(self.cat_expr(base));
460 Ok(self.cat_index(expr, base_cmt, 0))
461 }
462
463 ast::ExprPath(_) => {
464 let def = self.tcx().def_map.borrow().get_copy(&expr.id);
465 self.cat_def(expr.id, expr.span, expr_ty, def)
466 }
467
468 ast::ExprParen(e) => {
469 self.cat_expr(e)
470 }
471
472 ast::ExprAddrOf(..) | ast::ExprCall(..) |
473 ast::ExprAssign(..) | ast::ExprAssignOp(..) |
474 ast::ExprFnBlock(..) | ast::ExprProc(..) | ast::ExprRet(..) |
475 ast::ExprUnary(..) |
476 ast::ExprMethodCall(..) | ast::ExprCast(..) | ast::ExprVstore(..) |
477 ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
478 ast::ExprBinary(..) | ast::ExprWhile(..) |
479 ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
480 ast::ExprLit(..) | ast::ExprBreak(..) | ast::ExprMac(..) |
481 ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
482 ast::ExprInlineAsm(..) | ast::ExprBox(..) => {
483 Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
484 }
485
486 ast::ExprForLoop(..) => fail!("non-desugared expr_for_loop")
487 }
488 }
489
490 pub fn cat_def(&self,
491 id: ast::NodeId,
492 span: Span,
493 expr_ty: ty::t,
494 def: ast::Def)
495 -> McResult<cmt> {
496 debug!("cat_def: id={} expr={} def={:?}",
497 id, expr_ty.repr(self.tcx()), def);
498
499 match def {
500 ast::DefStruct(..) | ast::DefVariant(..) => {
501 Ok(self.cat_rvalue_node(id, span, expr_ty))
502 }
503 ast::DefFn(..) | ast::DefStaticMethod(..) | ast::DefMod(_) |
504 ast::DefForeignMod(_) | ast::DefStatic(_, false) |
505 ast::DefUse(_) | ast::DefTrait(_) | ast::DefTy(_) | ast::DefPrimTy(_) |
506 ast::DefTyParam(..) | ast::DefTyParamBinder(..) | ast::DefRegion(_) |
507 ast::DefLabel(_) | ast::DefSelfTy(..) | ast::DefMethod(..) => {
508 Ok(Rc::new(cmt_ {
509 id:id,
510 span:span,
511 cat:cat_static_item,
512 mutbl: McImmutable,
513 ty:expr_ty
514 }))
515 }
516
517 ast::DefStatic(_, true) => {
518 Ok(Rc::new(cmt_ {
519 id:id,
520 span:span,
521 cat:cat_static_item,
522 mutbl: McDeclared,
523 ty:expr_ty
524 }))
525 }
526
527 ast::DefArg(vid, binding_mode) => {
528 // Idea: make this could be rewritten to model by-ref
529 // stuff as `&const` and `&mut`?
530
531 // m: mutability of the argument
532 let m = match binding_mode {
533 ast::BindByValue(ast::MutMutable) => McDeclared,
534 _ => McImmutable
535 };
536 Ok(Rc::new(cmt_ {
537 id: id,
538 span: span,
539 cat: cat_arg(vid),
540 mutbl: m,
541 ty:expr_ty
542 }))
543 }
544
545 ast::DefUpvar(var_id, _, fn_node_id, _) => {
546 let ty = if_ok!(self.node_ty(fn_node_id));
547 match ty::get(ty).sty {
548 ty::ty_closure(ref closure_ty) => {
549 // Decide whether to use implicit reference or by copy/move
550 // capture for the upvar. This, combined with the onceness,
551 // determines whether the closure can move out of it.
552 let var_is_refd = match (closure_ty.store, closure_ty.onceness) {
553 // Many-shot stack closures can never move out.
554 (ty::RegionTraitStore(..), ast::Many) => true,
555 // 1-shot stack closures can move out.
556 (ty::RegionTraitStore(..), ast::Once) => false,
557 // Heap closures always capture by copy/move, and can
558 // move out if they are once.
559 (ty::UniqTraitStore, _) => false,
560
561 };
562 if var_is_refd {
563 self.cat_upvar(id, span, var_id, fn_node_id)
564 } else {
565 // FIXME #2152 allow mutation of moved upvars
566 Ok(Rc::new(cmt_ {
567 id:id,
568 span:span,
569 cat:cat_copied_upvar(CopiedUpvar {
570 upvar_id: var_id,
571 onceness: closure_ty.onceness}),
572 mutbl:McImmutable,
573 ty:expr_ty
574 }))
575 }
576 }
577 _ => {
578 self.tcx().sess.span_bug(
579 span,
580 format!("Upvar of non-closure {} - {}",
581 fn_node_id, ty.repr(self.tcx())));
582 }
583 }
584 }
585
586 ast::DefLocal(vid, binding_mode) |
587 ast::DefBinding(vid, binding_mode) => {
588 // by-value/by-ref bindings are local variables
589 let m = match binding_mode {
590 ast::BindByValue(ast::MutMutable) => McDeclared,
591 _ => McImmutable
592 };
593
594 Ok(Rc::new(cmt_ {
595 id: id,
596 span: span,
597 cat: cat_local(vid),
598 mutbl: m,
599 ty: expr_ty
600 }))
601 }
602 }
603 }
604
605 fn cat_upvar(&self,
606 id: ast::NodeId,
607 span: Span,
608 var_id: ast::NodeId,
609 fn_node_id: ast::NodeId)
610 -> McResult<cmt> {
611 /*!
612 * Upvars through a closure are in fact indirect
613 * references. That is, when a closure refers to a
614 * variable from a parent stack frame like `x = 10`,
615 * that is equivalent to `*x_ = 10` where `x_` is a
616 * borrowed pointer (`&mut x`) created when the closure
617 * was created and store in the environment. This
618 * equivalence is expose in the mem-categorization.
619 */
620
621 let upvar_id = ty::UpvarId { var_id: var_id,
622 closure_expr_id: fn_node_id };
623
624 let upvar_borrow = self.typer.upvar_borrow(upvar_id);
625
626 let var_ty = if_ok!(self.node_ty(var_id));
627
628 // We can't actually represent the types of all upvars
629 // as user-describable types, since upvars support const
630 // and unique-imm borrows! Therefore, we cheat, and just
631 // give err type. Nobody should be inspecting this type anyhow.
632 let upvar_ty = ty::mk_err();
633
634 let base_cmt = Rc::new(cmt_ {
635 id:id,
636 span:span,
637 cat:cat_upvar(upvar_id, upvar_borrow),
638 mutbl:McImmutable,
639 ty:upvar_ty,
640 });
641
642 let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region);
643
644 let deref_cmt = Rc::new(cmt_ {
645 id:id,
646 span:span,
647 cat:cat_deref(base_cmt, 0, ptr),
648 mutbl:MutabilityCategory::from_borrow_kind(upvar_borrow.kind),
649 ty:var_ty,
650 });
651
652 Ok(deref_cmt)
653 }
654
655 pub fn cat_rvalue_node(&self,
656 id: ast::NodeId,
657 span: Span,
658 expr_ty: ty::t)
659 -> cmt {
660 match self.typer.temporary_scope(id) {
661 Some(scope) => {
662 self.cat_rvalue(id, span, ty::ReScope(scope), expr_ty)
663 }
664 None => {
665 self.cat_rvalue(id, span, ty::ReStatic, expr_ty)
666 }
667 }
668 }
669
670 pub fn cat_rvalue(&self,
671 cmt_id: ast::NodeId,
672 span: Span,
673 temp_scope: ty::Region,
674 expr_ty: ty::t) -> cmt {
675 Rc::new(cmt_ {
676 id:cmt_id,
677 span:span,
678 cat:cat_rvalue(temp_scope),
679 mutbl:McDeclared,
680 ty:expr_ty
681 })
682 }
683
684 pub fn cat_field<N:ast_node>(&self,
685 node: &N,
686 base_cmt: cmt,
687 f_name: ast::Ident,
688 f_ty: ty::t)
689 -> cmt {
690 Rc::new(cmt_ {
691 id: node.id(),
692 span: node.span(),
693 mutbl: base_cmt.mutbl.inherit(),
694 cat: cat_interior(base_cmt, InteriorField(NamedField(f_name.name))),
695 ty: f_ty
696 })
697 }
698
699 pub fn cat_deref_obj<N:ast_node>(&self, node: &N, base_cmt: cmt) -> cmt {
700 self.cat_deref_common(node, base_cmt, 0, ty::mk_nil())
701 }
702
703 fn cat_deref<N:ast_node>(&self,
704 node: &N,
705 base_cmt: cmt,
706 deref_cnt: uint)
707 -> cmt {
708 let method_call = typeck::MethodCall {
709 expr_id: node.id(),
710 autoderef: deref_cnt as u32
711 };
712 let method_ty = self.typer.node_method_ty(method_call);
713
714 debug!("cat_deref: method_call={:?} method_ty={}",
715 method_call, method_ty.map(|ty| ty.repr(self.tcx())));
716
717 let base_cmt = match method_ty {
718 Some(method_ty) => {
719 let ref_ty = ty::ty_fn_ret(method_ty);
720 self.cat_rvalue_node(node.id(), node.span(), ref_ty)
721 }
722 None => base_cmt
723 };
724 match ty::deref(base_cmt.ty, true) {
725 Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty),
726 None => {
727 self.tcx().sess.span_bug(
728 node.span(),
729 format!("Explicit deref of non-derefable type: {}",
730 base_cmt.ty.repr(self.tcx())));
731 }
732 }
733 }
734
735 fn cat_deref_common<N:ast_node>(&self,
736 node: &N,
737 base_cmt: cmt,
738 deref_cnt: uint,
739 deref_ty: ty::t)
740 -> cmt {
741 let (m, cat) = match deref_kind(self.tcx(), base_cmt.ty) {
742 deref_ptr(ptr) => {
743 // for unique ptrs, we inherit mutability from the
744 // owning reference.
745 (MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
746 cat_deref(base_cmt, deref_cnt, ptr))
747 }
748 deref_interior(interior) => {
749 (base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior))
750 }
751 };
752 Rc::new(cmt_ {
753 id: node.id(),
754 span: node.span(),
755 cat: cat,
756 mutbl: m,
757 ty: deref_ty
758 })
759 }
760
761 pub fn cat_index<N:ast_node>(&self,
762 elt: &N,
763 base_cmt: cmt,
764 derefs: uint)
765 -> cmt {
766 //! Creates a cmt for an indexing operation (`[]`); this
767 //! indexing operation may occurs as part of an
768 //! AutoBorrowVec, which when converting a `~[]` to an `&[]`
769 //! effectively takes the address of the 0th element.
770 //!
771 //! One subtle aspect of indexing that may not be
772 //! immediately obvious: for anything other than a fixed-length
773 //! vector, an operation like `x[y]` actually consists of two
774 //! disjoint (from the point of view of borrowck) operations.
775 //! The first is a deref of `x` to create a pointer `p` that points
776 //! at the first element in the array. The second operation is
777 //! an index which adds `y*sizeof(T)` to `p` to obtain the
778 //! pointer to `x[y]`. `cat_index` will produce a resulting
779 //! cmt containing both this deref and the indexing,
780 //! presuming that `base_cmt` is not of fixed-length type.
781 //!
782 //! In the event that a deref is needed, the "deref count"
783 //! is taken from the parameter `derefs`. See the comment
784 //! on the def'n of `root_map_key` in borrowck/mod.rs
785 //! for more details about deref counts; the summary is
786 //! that `derefs` should be 0 for an explicit indexing
787 //! operation and N+1 for an indexing that is part of
788 //! an auto-adjustment, where N is the number of autoderefs
789 //! in that adjustment.
790 //!
791 //! # Parameters
792 //! - `elt`: the AST node being indexed
793 //! - `base_cmt`: the cmt of `elt`
794 //! - `derefs`: the deref number to be used for
795 //! the implicit index deref, if any (see above)
796
797 let element_ty = match ty::index(base_cmt.ty) {
798 Some(ref mt) => mt.ty,
799 None => {
800 self.tcx().sess.span_bug(
801 elt.span(),
802 format!("Explicit index of non-index type `{}`",
803 base_cmt.ty.repr(self.tcx())));
804 }
805 };
806
807 return match deref_kind(self.tcx(), base_cmt.ty) {
808 deref_ptr(ptr) => {
809 // for unique ptrs, we inherit mutability from the
810 // owning reference.
811 let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
812
813 // the deref is explicit in the resulting cmt
814 let deref_cmt = Rc::new(cmt_ {
815 id:elt.id(),
816 span:elt.span(),
817 cat:cat_deref(base_cmt.clone(), derefs, ptr),
818 mutbl:m,
819 ty:element_ty
820 });
821
822 interior(elt, deref_cmt, base_cmt.ty, m.inherit(), element_ty)
823 }
824
825 deref_interior(_) => {
826 // fixed-length vectors have no deref
827 let m = base_cmt.mutbl.inherit();
828 interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty)
829 }
830 };
831
832 fn interior<N: ast_node>(elt: &N,
833 of_cmt: cmt,
834 vec_ty: ty::t,
835 mutbl: MutabilityCategory,
836 element_ty: ty::t) -> cmt
837 {
838 Rc::new(cmt_ {
839 id:elt.id(),
840 span:elt.span(),
841 cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
842 mutbl:mutbl,
843 ty:element_ty
844 })
845 }
846 }
847
848 pub fn cat_slice_pattern(&self,
849 vec_cmt: cmt,
850 slice_pat: &ast::Pat)
851 -> McResult<(cmt, ast::Mutability, ty::Region)> {
852 /*!
853 * Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is
854 * the cmt for `P`, `slice_pat` is the pattern `Q`, returns:
855 * - a cmt for `Q`
856 * - the mutability and region of the slice `Q`
857 *
858 * These last two bits of info happen to be things that
859 * borrowck needs.
860 */
861
862 let slice_ty = if_ok!(self.node_ty(slice_pat.id));
863 let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
864 slice_pat,
865 slice_ty);
866 let cmt_slice = self.cat_index(slice_pat, vec_cmt, 0);
867 return Ok((cmt_slice, slice_mutbl, slice_r));
868
869 fn vec_slice_info(tcx: &ty::ctxt,
870 pat: &ast::Pat,
871 slice_ty: ty::t)
872 -> (ast::Mutability, ty::Region) {
873 /*!
874 * In a pattern like [a, b, ..c], normally `c` has slice type,
875 * but if you have [a, b, ..ref c], then the type of `ref c`
876 * will be `&&[]`, so to extract the slice details we have
877 * to recurse through rptrs.
878 */
879
880 match ty::get(slice_ty).sty {
881 ty::ty_rptr(r, ref mt) => match ty::get(mt.ty).sty {
882 ty::ty_vec(slice_mt, None) => (slice_mt.mutbl, r),
883 _ => vec_slice_info(tcx, pat, mt.ty),
884 },
885
886 _ => {
887 tcx.sess.span_bug(
888 pat.span,
889 format!("Type of slice pattern is not a slice"));
890 }
891 }
892 }
893 }
894
895 pub fn cat_imm_interior<N:ast_node>(&self,
896 node: &N,
897 base_cmt: cmt,
898 interior_ty: ty::t,
899 interior: InteriorKind)
900 -> cmt {
901 Rc::new(cmt_ {
902 id: node.id(),
903 span: node.span(),
904 mutbl: base_cmt.mutbl.inherit(),
905 cat: cat_interior(base_cmt, interior),
906 ty: interior_ty
907 })
908 }
909
910 pub fn cat_downcast<N:ast_node>(&self,
911 node: &N,
912 base_cmt: cmt,
913 downcast_ty: ty::t)
914 -> cmt {
915 Rc::new(cmt_ {
916 id: node.id(),
917 span: node.span(),
918 mutbl: base_cmt.mutbl.inherit(),
919 cat: cat_downcast(base_cmt),
920 ty: downcast_ty
921 })
922 }
923
924 pub fn cat_pattern(&self,
925 cmt: cmt,
926 pat: &ast::Pat,
927 op: |&MemCategorizationContext<TYPER>,
928 cmt,
929 &ast::Pat|)
930 -> McResult<()> {
931 // Here, `cmt` is the categorization for the value being
932 // matched and pat is the pattern it is being matched against.
933 //
934 // In general, the way that this works is that we walk down
935 // the pattern, constructing a cmt that represents the path
936 // that will be taken to reach the value being matched.
937 //
938 // When we encounter named bindings, we take the cmt that has
939 // been built up and pass it off to guarantee_valid() so that
940 // we can be sure that the binding will remain valid for the
941 // duration of the arm.
942 //
943 // (*2) There is subtlety concerning the correspondence between
944 // pattern ids and types as compared to *expression* ids and
945 // types. This is explained briefly. on the definition of the
946 // type `cmt`, so go off and read what it says there, then
947 // come back and I'll dive into a bit more detail here. :) OK,
948 // back?
949 //
950 // In general, the id of the cmt should be the node that
951 // "produces" the value---patterns aren't executable code
952 // exactly, but I consider them to "execute" when they match a
953 // value, and I consider them to produce the value that was
954 // matched. So if you have something like:
955 //
956 // let x = @@3;
957 // match x {
958 // @@y { ... }
959 // }
960 //
961 // In this case, the cmt and the relevant ids would be:
962 //
963 // CMT Id Type of Id Type of cmt
964 //
965 // local(x)->@->@
966 // ^~~~~~~^ `x` from discr @@int @@int
967 // ^~~~~~~~~~^ `@@y` pattern node @@int @int
968 // ^~~~~~~~~~~~~^ `@y` pattern node @int int
969 //
970 // You can see that the types of the id and the cmt are in
971 // sync in the first line, because that id is actually the id
972 // of an expression. But once we get to pattern ids, the types
973 // step out of sync again. So you'll see below that we always
974 // get the type of the *subpattern* and use that.
975
976 debug!("cat_pattern: id={} pat={} cmt={}",
977 pat.id, pprust::pat_to_str(pat),
978 cmt.repr(self.tcx()));
979
980 op(self, cmt.clone(), pat);
981
982 match pat.node {
983 ast::PatWild | ast::PatWildMulti => {
984 // _
985 }
986
987 ast::PatEnum(_, None) => {
988 // variant(..)
989 }
990 ast::PatEnum(_, Some(ref subpats)) => {
991 match self.tcx().def_map.borrow().find(&pat.id) {
992 Some(&ast::DefVariant(enum_did, _, _)) => {
993 // variant(x, y, z)
994
995 let downcast_cmt = {
996 if ty::enum_is_univariant(self.tcx(), enum_did) {
997 cmt // univariant, no downcast needed
998 } else {
999 self.cat_downcast(pat, cmt.clone(), cmt.ty)
1000 }
1001 };
1002
1003 for (i, &subpat) in subpats.iter().enumerate() {
1004 let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
1005
1006 let subcmt =
1007 self.cat_imm_interior(
1008 pat, downcast_cmt.clone(), subpat_ty,
1009 InteriorField(PositionalField(i)));
1010
1011 if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
1012 }
1013 }
1014 Some(&ast::DefFn(..)) |
1015 Some(&ast::DefStruct(..)) => {
1016 for (i, &subpat) in subpats.iter().enumerate() {
1017 let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
1018 let cmt_field =
1019 self.cat_imm_interior(
1020 pat, cmt.clone(), subpat_ty,
1021 InteriorField(PositionalField(i)));
1022 if_ok!(self.cat_pattern(cmt_field, subpat, |x,y,z| op(x,y,z)));
1023 }
1024 }
1025 Some(&ast::DefStatic(..)) => {
1026 for &subpat in subpats.iter() {
1027 if_ok!(self.cat_pattern(cmt.clone(), subpat, |x,y,z| op(x,y,z)));
1028 }
1029 }
1030 _ => {
1031 self.tcx().sess.span_bug(
1032 pat.span,
1033 "enum pattern didn't resolve to enum or struct");
1034 }
1035 }
1036 }
1037
1038 ast::PatIdent(_, _, Some(subpat)) => {
1039 if_ok!(self.cat_pattern(cmt, subpat, op));
1040 }
1041
1042 ast::PatIdent(_, _, None) => {
1043 // nullary variant or identifier: ignore
1044 }
1045
1046 ast::PatStruct(_, ref field_pats, _) => {
1047 // {f1: p1, ..., fN: pN}
1048 for fp in field_pats.iter() {
1049 let field_ty = if_ok!(self.pat_ty(fp.pat)); // see (*2)
1050 let cmt_field = self.cat_field(pat, cmt.clone(), fp.ident, field_ty);
1051 if_ok!(self.cat_pattern(cmt_field, fp.pat, |x,y,z| op(x,y,z)));
1052 }
1053 }
1054
1055 ast::PatTup(ref subpats) => {
1056 // (p1, ..., pN)
1057 for (i, &subpat) in subpats.iter().enumerate() {
1058 let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
1059 let subcmt =
1060 self.cat_imm_interior(
1061 pat, cmt.clone(), subpat_ty,
1062 InteriorField(PositionalField(i)));
1063 if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
1064 }
1065 }
1066
1067 ast::PatUniq(subpat) | ast::PatRegion(subpat) => {
1068 // @p1, ~p1
1069 let subcmt = self.cat_deref(pat, cmt, 0);
1070 if_ok!(self.cat_pattern(subcmt, subpat, op));
1071 }
1072
1073 ast::PatVec(ref before, slice, ref after) => {
1074 let elt_cmt = self.cat_index(pat, cmt, 0);
1075 for &before_pat in before.iter() {
1076 if_ok!(self.cat_pattern(elt_cmt.clone(), before_pat, |x,y,z| op(x,y,z)));
1077 }
1078 for &slice_pat in slice.iter() {
1079 let slice_ty = if_ok!(self.pat_ty(slice_pat));
1080 let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
1081 if_ok!(self.cat_pattern(slice_cmt, slice_pat, |x,y,z| op(x,y,z)));
1082 }
1083 for &after_pat in after.iter() {
1084 if_ok!(self.cat_pattern(elt_cmt.clone(), after_pat, |x,y,z| op(x,y,z)));
1085 }
1086 }
1087
1088 ast::PatLit(_) | ast::PatRange(_, _) => {
1089 /*always ok*/
1090 }
1091 }
1092
1093 Ok(())
1094 }
1095
1096 pub fn cmt_to_str(&self, cmt: &cmt_) -> ~str {
1097 match cmt.cat {
1098 cat_static_item => {
1099 "static item".to_owned()
1100 }
1101 cat_copied_upvar(_) => {
1102 "captured outer variable in a proc".to_owned()
1103 }
1104 cat_rvalue(..) => {
1105 "non-lvalue".to_owned()
1106 }
1107 cat_local(_) => {
1108 "local variable".to_owned()
1109 }
1110 cat_arg(..) => {
1111 "argument".to_owned()
1112 }
1113 cat_deref(ref base, _, pk) => {
1114 match base.cat {
1115 cat_upvar(..) => {
1116 format!("captured outer variable")
1117 }
1118 _ => {
1119 format!("dereference of `{}`-pointer", ptr_sigil(pk))
1120 }
1121 }
1122 }
1123 cat_interior(_, InteriorField(NamedField(_))) => {
1124 "field".to_owned()
1125 }
1126 cat_interior(_, InteriorField(PositionalField(_))) => {
1127 "anonymous field".to_owned()
1128 }
1129 cat_interior(_, InteriorElement(VecElement)) => {
1130 "vec content".to_owned()
1131 }
1132 cat_interior(_, InteriorElement(StrElement)) => {
1133 "str content".to_owned()
1134 }
1135 cat_interior(_, InteriorElement(OtherElement)) => {
1136 "indexed content".to_owned()
1137 }
1138 cat_upvar(..) => {
1139 "captured outer variable".to_owned()
1140 }
1141 cat_discr(ref cmt, _) => {
1142 self.cmt_to_str(&**cmt)
1143 }
1144 cat_downcast(ref cmt) => {
1145 self.cmt_to_str(&**cmt)
1146 }
1147 }
1148 }
1149 }
1150
1151 pub enum InteriorSafety {
1152 InteriorUnsafe,
1153 InteriorSafe
1154 }
1155
1156 pub enum AliasableReason {
1157 AliasableManaged,
1158 AliasableBorrowed,
1159 AliasableOther,
1160 AliasableStatic(InteriorSafety),
1161 AliasableStaticMut(InteriorSafety),
1162 }
1163
1164 impl cmt_ {
1165 pub fn guarantor(&self) -> cmt {
1166 //! Returns `self` after stripping away any owned pointer derefs or
1167 //! interior content. The return value is basically the `cmt` which
1168 //! determines how long the value in `self` remains live.
1169
1170 match self.cat {
1171 cat_rvalue(..) |
1172 cat_static_item |
1173 cat_copied_upvar(..) |
1174 cat_local(..) |
1175 cat_arg(..) |
1176 cat_deref(_, _, UnsafePtr(..)) |
1177 cat_deref(_, _, GcPtr(..)) |
1178 cat_deref(_, _, BorrowedPtr(..)) |
1179 cat_upvar(..) => {
1180 Rc::new((*self).clone())
1181 }
1182 cat_downcast(ref b) |
1183 cat_discr(ref b, _) |
1184 cat_interior(ref b, _) |
1185 cat_deref(ref b, _, OwnedPtr) => {
1186 b.guarantor()
1187 }
1188 }
1189 }
1190
1191 pub fn freely_aliasable(&self, ctxt: &ty::ctxt) -> Option<AliasableReason> {
1192 /*!
1193 * Returns `Some(_)` if this lvalue represents a freely aliasable
1194 * pointer type.
1195 */
1196
1197 // Maybe non-obvious: copied upvars can only be considered
1198 // non-aliasable in once closures, since any other kind can be
1199 // aliased and eventually recused.
1200
1201 match self.cat {
1202 cat_deref(ref b, _, BorrowedPtr(ty::MutBorrow, _)) |
1203 cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
1204 cat_downcast(ref b) |
1205 cat_deref(ref b, _, OwnedPtr) |
1206 cat_interior(ref b, _) |
1207 cat_discr(ref b, _) => {
1208 // Aliasability depends on base cmt
1209 b.freely_aliasable(ctxt)
1210 }
1211
1212 cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) |
1213 cat_rvalue(..) |
1214 cat_local(..) |
1215 cat_upvar(..) |
1216 cat_arg(_) |
1217 cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but...
1218 None
1219 }
1220
1221 cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => {
1222 Some(AliasableOther)
1223 }
1224
1225 cat_static_item(..) => {
1226 let int_safe = if ty::type_interior_is_unsafe(ctxt, self.ty) {
1227 InteriorUnsafe
1228 } else {
1229 InteriorSafe
1230 };
1231
1232 if self.mutbl.is_mutable() {
1233 Some(AliasableStaticMut(int_safe))
1234 } else {
1235 Some(AliasableStatic(int_safe))
1236 }
1237 }
1238
1239 cat_deref(_, _, GcPtr) => {
1240 Some(AliasableManaged)
1241 }
1242
1243 cat_deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) => {
1244 Some(AliasableBorrowed)
1245 }
1246 }
1247 }
1248 }
1249
1250 impl Repr for cmt_ {
1251 fn repr(&self, tcx: &ty::ctxt) -> ~str {
1252 format!("\\{{} id:{} m:{:?} ty:{}\\}",
1253 self.cat.repr(tcx),
1254 self.id,
1255 self.mutbl,
1256 self.ty.repr(tcx))
1257 }
1258 }
1259
1260 impl Repr for categorization {
1261 fn repr(&self, tcx: &ty::ctxt) -> ~str {
1262 match *self {
1263 cat_static_item |
1264 cat_rvalue(..) |
1265 cat_copied_upvar(..) |
1266 cat_local(..) |
1267 cat_upvar(..) |
1268 cat_arg(..) => {
1269 format!("{:?}", *self)
1270 }
1271 cat_deref(ref cmt, derefs, ptr) => {
1272 format!("{}-{}{}->",
1273 cmt.cat.repr(tcx),
1274 ptr_sigil(ptr),
1275 derefs)
1276 }
1277 cat_interior(ref cmt, interior) => {
1278 format!("{}.{}",
1279 cmt.cat.repr(tcx),
1280 interior.repr(tcx))
1281 }
1282 cat_downcast(ref cmt) => {
1283 format!("{}->(enum)", cmt.cat.repr(tcx))
1284 }
1285 cat_discr(ref cmt, _) => {
1286 cmt.cat.repr(tcx)
1287 }
1288 }
1289 }
1290 }
1291
1292 pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
1293 match ptr {
1294 OwnedPtr => "~",
1295 GcPtr => "@",
1296 BorrowedPtr(ty::ImmBorrow, _) => "&",
1297 BorrowedPtr(ty::MutBorrow, _) => "&mut",
1298 BorrowedPtr(ty::UniqueImmBorrow, _) => "&unique",
1299 UnsafePtr(_) => "*"
1300 }
1301 }
1302
1303 impl Repr for InteriorKind {
1304 fn repr(&self, _tcx: &ty::ctxt) -> ~str {
1305 match *self {
1306 InteriorField(NamedField(fld)) => {
1307 token::get_name(fld).get().to_str()
1308 }
1309 InteriorField(PositionalField(i)) => format!("\\#{:?}", i),
1310 InteriorElement(_) => "[]".to_owned(),
1311 }
1312 }
1313 }
1314
1315 fn element_kind(t: ty::t) -> ElementKind {
1316 match ty::get(t).sty {
1317 ty::ty_rptr(_, ty::mt{ty:ty, ..}) |
1318 ty::ty_uniq(ty) => match ty::get(ty).sty {
1319 ty::ty_vec(_, None) => VecElement,
1320 ty::ty_str => StrElement,
1321 _ => OtherElement
1322 },
1323 ty::ty_vec(..) => VecElement,
1324 _ => OtherElement
1325 }
1326 }
librustc/middle/mem_categorization.rs:1291:1-1291:1 -fn- definition:
pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
match ptr {
OwnedPtr => "~",
references:- 21273: cmt.cat.repr(tcx),
1274: ptr_sigil(ptr),
1275: derefs)
librustc/middle/mem_categorization.rs:79:23-79:23 -enum- definition:
pub enum categorization {
cat_rvalue(ty::Region), // temporary val, argument is its scope
cat_static_item,
references:- 780: pub enum categorization {
--
1260: impl Repr for categorization {
1261: fn repr(&self, tcx: &ty::ctxt) -> ~str {
librustc/middle/mem_categorization.rs:1155:1-1155:1 -enum- definition:
pub enum AliasableReason {
AliasableManaged,
AliasableBorrowed,
references:- 21191: pub fn freely_aliasable(&self, ctxt: &ty::ctxt) -> Option<AliasableReason> {
1192: /*!
librustc/middle/borrowck/mod.rs:
626: kind: AliasableViolationKind,
627: cause: mc::AliasableReason) {
628: let prefix = match kind {
librustc/middle/mem_categorization.rs:1314:1-1314:1 -fn- definition:
fn element_kind(t: ty::t) -> ElementKind {
match ty::get(t).sty {
ty::ty_rptr(_, ty::mt{ty:ty, ..}) |
references:- 2213: ty::ty_vec(_, Some(_)) => {
214: Some(deref_interior(InteriorElement(element_kind(t))))
215: }
--
840: span:elt.span(),
841: cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
842: mutbl:mutbl,
librustc/middle/mem_categorization.rs:118:38-118:38 -enum- definition:
pub enum FieldName {
NamedField(ast::Name),
PositionalField(uint)
references:- 8113: pub enum InteriorKind {
114: InteriorField(FieldName),
115: InteriorElement(ElementKind),
--
119: pub enum FieldName {
librustc/middle/mem_categorization.rs:124:38-124:38 -enum- definition:
pub enum ElementKind {
VecElement,
StrElement,
references:- 9125: pub enum ElementKind {
--
1315: fn element_kind(t: ty::t) -> ElementKind {
1316: match ty::get(t).sty {
librustc/middle/mem_categorization.rs:1150:1-1150:1 -enum- definition:
pub enum InteriorSafety {
InteriorUnsafe,
InteriorSafe
references:- 21159: AliasableOther,
1160: AliasableStatic(InteriorSafety),
1161: AliasableStaticMut(InteriorSafety),
1162: }
librustc/middle/mem_categorization.rs:250:1-250:1 -NK_AS_STR_TODO- definition:
pub type McResult<T> = Result<T, ()>;
/**
* The `Typer` trait provides the interface for the mem-categorization
references:- 15929: &ast::Pat|)
930: -> McResult<()> {
931: // Here, `cmt` is the categorization for the value being
librustc/middle/expr_use_visitor.rs:
846: upvar_def: ast::Def)
847: -> mc::McResult<mc::cmt> {
848: // Create the cmt for the variable being borrowed, from the
librustc/middle/ty.rs:
4749: fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
4750: Ok(ty::node_id_to_type(self, id))
librustc/middle/typeck/check/regionck.rs:
269: fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
270: let t = self.resolve_node_type(id);
librustc/middle/mem_categorization.rs:
439: pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt> {
440: debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
librustc/middle/mem_categorization.rs:231:1-231:1 -trait- definition:
trait ast_node {
fn id(&self) -> ast::NodeId;
fn span(&self) -> Span;
references:- 10910: pub fn cat_downcast<N:ast_node>(&self,
911: node: &N,
librustc/middle/mem_categorization.rs:270:4-270:4 -trait- definition:
*/
pub trait Typer {
fn tcx<'a>(&'a self) -> &'a ty::ctxt;
references:- 4355: impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
356: pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
librustc/middle/ty.rs:
4744: impl mc::Typer for ty::ctxt {
4745: fn tcx<'a>(&'a self) -> &'a ty::ctxt {
librustc/middle/typeck/check/regionck.rs:
264: impl<'fcx> mc::Typer for Rcx<'fcx> {
265: fn tcx<'a>(&'a self) -> &'a ty::ctxt {
librustc/middle/expr_use_visitor.rs:
123: impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
124: pub fn new(delegate: &'d mut Delegate,
librustc/middle/mem_categorization.rs:246:1-246:1 -struct- definition:
pub struct MemCategorizationContext<'t,TYPER> {
typer: &'t TYPER
}
references:- 7356: pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
357: MemCategorizationContext { typer: typer }
358: }
librustc/middle/expr_use_visitor.rs:
102: typer: &'t TYPER,
103: mc: mc::MemCategorizationContext<'t,TYPER>,
104: delegate: &'d mut Delegate,
librustc/middle/typeck/check/regionck.rs:
1081: fn link_pattern(rcx: &Rcx,
1082: mc: mc::MemCategorizationContext<Rcx>,
1083: discr_cmt: mc::cmt,
librustc/middle/borrowck/mod.rs:
357: pub fn mc(&self) -> mc::MemCategorizationContext<'a,ty::ctxt> {
358: mc::MemCategorizationContext::new(self.tcx)
librustc/middle/mem_categorization.rs:
926: pat: &ast::Pat,
927: op: |&MemCategorizationContext<TYPER>,
928: cmt,
librustc/middle/mem_categorization.rs:112:38-112:38 -enum- definition:
pub enum InteriorKind {
InteriorField(FieldName),
InteriorElement(ElementKind),
references:- 12111: // base without a pointer dereference", e.g. a field
113: pub enum InteriorKind {
--
1303: impl Repr for InteriorKind {
1304: fn repr(&self, _tcx: &ty::ctxt) -> ~str {
librustc/middle/borrowck/mod.rs:
206: LpDeref(mc::PointerKind), // `*LV` in doc.rs
207: LpInterior(mc::InteriorKind) // `LV.f` in doc.rs
208: }
librustc/middle/mem_categorization.rs:
898: interior_ty: ty::t,
899: interior: InteriorKind)
900: -> cmt {
librustc/middle/mem_categorization.rs:131:44-131:44 -enum- definition:
pub enum MutabilityCategory {
McImmutable, // Immutable.
McDeclared, // Directly declared as mutable.
references:- 18132: pub enum MutabilityCategory {
--
281: impl MutabilityCategory {
282: pub fn from_mutbl(m: ast::Mutability) -> MutabilityCategory {
--
289: pub fn from_borrow_kind(borrow_kind: ty::BorrowKind) -> MutabilityCategory {
290: match borrow_kind {
--
315: pub fn inherit(&self) -> MutabilityCategory {
316: match *self {
--
834: vec_ty: ty::t,
835: mutbl: MutabilityCategory,
836: element_ty: ty::t) -> cmt
librustc/middle/borrowck/mod.rs:
200: LpVar(ast::NodeId), // `x` in doc.rs
201: LpExtend(Rc<LoanPath>, mc::MutabilityCategory, LoanPathElem)
202: }
librustc/middle/borrowck/gather_loans/restrictions.rs:
173: result: RestrictionResult,
174: mc: mc::MutabilityCategory,
175: elem: LoanPathElem,
librustc/middle/mem_categorization.rs:
132: pub enum MutabilityCategory {
librustc/middle/mem_categorization.rs:152:23-152:23 -struct- definition:
pub struct cmt_ {
pub id: ast::NodeId, // id of expr/pat producing this value
pub span: Span, // span of same expr/pat
references:- 31librustc/middle/borrowck/mod.rs:
librustc/middle/mem_categorization.rs:
librustc/middle/borrowck/mod.rs:
librustc/middle/mem_categorization.rs:
librustc/middle/mem_categorization.rs:102:38-102:38 -enum- definition:
pub enum PointerKind {
OwnedPtr,
GcPtr,
references:- 12297: pub fn from_pointer_kind(base_mutbl: MutabilityCategory,
298: ptr: PointerKind) -> MutabilityCategory {
299: match ptr {
--
1292: pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
1293: match ptr {
librustc/middle/borrowck/mod.rs:
205: pub enum LoanPathElem {
206: LpDeref(mc::PointerKind), // `*LV` in doc.rs
207: LpInterior(mc::InteriorKind) // `LV.f` in doc.rs
librustc/middle/mem_categorization.rs:
101: // different kinds of pointers:
103: pub enum PointerKind {
librustc/middle/mem_categorization.rs:164:31-164:31 -enum- definition:
// as accessing of components:
pub enum deref_kind {
deref_ptr(PointerKind),
references:- 2172: // pointer adjustment).
173: pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
174: match ty::get(t).sty {
--
221: pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind {
222: match opt_deref_kind(t) {
librustc/middle/mem_categorization.rs:832:8-832:8 -fn- definition:
fn interior<N: ast_node>(elt: &N,
of_cmt: cmt,
vec_ty: ty::t,
references:- 2827: let m = base_cmt.mutbl.inherit();
828: interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty)
829: }
librustc/middle/mem_categorization.rs:869:8-869:8 -fn- definition:
fn vec_slice_info(tcx: &ty::ctxt,
pat: &ast::Pat,
slice_ty: ty::t)
references:- 2862: let slice_ty = if_ok!(self.node_ty(slice_pat.id));
863: let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
864: slice_pat,
--
882: ty::ty_vec(slice_mt, None) => (slice_mt.mutbl, r),
883: _ => vec_slice_info(tcx, pat, mt.ty),
884: },
librustc/middle/mem_categorization.rs:220:1-220:1 -fn- definition:
pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind {
match opt_deref_kind(t) {
Some(k) => k,
references:- 2807: return match deref_kind(self.tcx(), base_cmt.ty) {
808: deref_ptr(ptr) => {
librustc/middle/mem_categorization.rs:95:23-95:23 -struct- definition:
pub struct CopiedUpvar {
pub upvar_id: ast::NodeId,
pub onceness: ast::Onceness,
references:- 2096: pub struct CopiedUpvar {
--
568: span:span,
569: cat:cat_copied_upvar(CopiedUpvar {
570: upvar_id: var_id,
--
1221: cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => {
1222: Some(AliasableOther)
librustc/middle/borrowck/mod.rs:
228: mc::cat_static_item |
229: mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
230: None
librustc/middle/borrowck/gather_loans/gather_moves.rs:
138: // (see mem_categorization.rs).
139: mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Once, .. }) => {
140: None
librustc/middle/borrowck/gather_loans/move_error.rs:
129: mc::cat_upvar(..) | mc::cat_static_item |
130: mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
131: bccx.span_err(
librustc/middle/borrowck/mod.rs:
234: mc::cat_arg(id) |
235: mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
236: mc::cat_upvar(ty::UpvarId {var_id: id, ..}, _) => {
librustc/middle/mem_categorization.rs:160:1-160:1 -NK_AS_STR_TODO- definition:
pub type cmt = Rc<cmt_>;
// We pun on *T to mean both actual deref of a ptr as well
// as accessing of components:
references:- 85librustc/middle/expr_use_visitor.rs:
librustc/middle/typeck/check/regionck.rs:
librustc/middle/borrowck/mod.rs:
librustc/middle/borrowck/check_loans.rs:
librustc/middle/borrowck/gather_loans/mod.rs:
librustc/middle/borrowck/gather_loans/lifetime.rs:
librustc/middle/borrowck/gather_loans/restrictions.rs:
librustc/middle/borrowck/gather_loans/gather_moves.rs:
librustc/middle/borrowck/gather_loans/move_error.rs:
librustc/middle/mem_categorization.rs: