]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/ty.rs
8d84d089c01b2adff75514cf313a74df9196d7b6
[rust.git] / src / librustc / middle / ty.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![allow(non_camel_case_types)]
12
13 use back::svh::Svh;
14 use driver::session::Session;
15 use metadata::csearch;
16 use mc = middle::mem_categorization;
17 use lint;
18 use middle::const_eval;
19 use middle::def;
20 use middle::dependency_format;
21 use middle::lang_items::OpaqueStructLangItem;
22 use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
23 use middle::freevars;
24 use middle::resolve;
25 use middle::resolve_lifetime;
26 use middle::subst;
27 use middle::subst::{Subst, Substs, VecPerParamSpace};
28 use middle::stability;
29 use middle::ty;
30 use middle::typeck;
31 use middle::typeck::MethodCall;
32 use middle::ty_fold;
33 use middle::ty_fold::{TypeFoldable,TypeFolder};
34 use middle;
35 use util::ppaux::{note_and_explain_region, bound_region_ptr_to_str};
36 use util::ppaux::{trait_store_to_str, ty_to_str};
37 use util::ppaux::{Repr, UserString};
38 use util::common::{indenter};
39 use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet, FnvHashMap};
40
41 use std::cell::{Cell, RefCell};
42 use std::cmp;
43 use std::fmt::Show;
44 use std::fmt;
45 use std::hash::{Hash, sip, Writer};
46 use std::gc::Gc;
47 use std::iter::AdditiveIterator;
48 use std::mem;
49 use std::ops;
50 use std::rc::Rc;
51 use std::collections::{HashMap, HashSet};
52 use syntax::abi;
53 use syntax::ast::*;
54 use syntax::ast_util::{is_local, lit_is_str};
55 use syntax::ast_util;
56 use syntax::attr;
57 use syntax::attr::AttrMetaMethods;
58 use syntax::codemap::Span;
59 use syntax::parse::token;
60 use syntax::parse::token::InternedString;
61 use syntax::{ast, ast_map};
62 use syntax::util::small_vector::SmallVector;
63 use std::collections::enum_set::{EnumSet, CLike};
64
65 pub type Disr = u64;
66
67 pub static INITIAL_DISCRIMINANT_VALUE: Disr = 0;
68
69 // Data types
70
71 #[deriving(PartialEq, Eq, Hash)]
72 pub struct field {
73     pub ident: ast::Ident,
74     pub mt: mt
75 }
76
77 #[deriving(Clone)]
78 pub enum MethodContainer {
79     TraitContainer(ast::DefId),
80     ImplContainer(ast::DefId),
81 }
82
83 #[deriving(Clone)]
84 pub struct Method {
85     pub ident: ast::Ident,
86     pub generics: ty::Generics,
87     pub fty: BareFnTy,
88     pub explicit_self: ast::ExplicitSelf_,
89     pub vis: ast::Visibility,
90     pub def_id: ast::DefId,
91     pub container: MethodContainer,
92
93     // If this method is provided, we need to know where it came from
94     pub provided_source: Option<ast::DefId>
95 }
96
97 impl Method {
98     pub fn new(ident: ast::Ident,
99                generics: ty::Generics,
100                fty: BareFnTy,
101                explicit_self: ast::ExplicitSelf_,
102                vis: ast::Visibility,
103                def_id: ast::DefId,
104                container: MethodContainer,
105                provided_source: Option<ast::DefId>)
106                -> Method {
107        Method {
108             ident: ident,
109             generics: generics,
110             fty: fty,
111             explicit_self: explicit_self,
112             vis: vis,
113             def_id: def_id,
114             container: container,
115             provided_source: provided_source
116         }
117     }
118
119     pub fn container_id(&self) -> ast::DefId {
120         match self.container {
121             TraitContainer(id) => id,
122             ImplContainer(id) => id,
123         }
124     }
125 }
126
127 #[deriving(Clone, PartialEq, Eq, Hash)]
128 pub struct mt {
129     pub ty: t,
130     pub mutbl: ast::Mutability,
131 }
132
133 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
134 pub enum TraitStore {
135     /// Box<Trait>
136     UniqTraitStore,
137     /// &Trait and &mut Trait
138     RegionTraitStore(Region, ast::Mutability),
139 }
140
141 #[deriving(Clone)]
142 pub struct field_ty {
143     pub name: Name,
144     pub id: DefId,
145     pub vis: ast::Visibility,
146     pub origin: ast::DefId,  // The DefId of the struct in which the field is declared.
147 }
148
149 // Contains information needed to resolve types and (in the future) look up
150 // the types of AST nodes.
151 #[deriving(PartialEq, Eq, Hash)]
152 pub struct creader_cache_key {
153     pub cnum: CrateNum,
154     pub pos: uint,
155     pub len: uint
156 }
157
158 pub type creader_cache = RefCell<HashMap<creader_cache_key, t>>;
159
160 pub struct intern_key {
161     sty: *const sty,
162 }
163
164 // NB: Do not replace this with #[deriving(PartialEq)]. The automatically-derived
165 // implementation will not recurse through sty and you will get stack
166 // exhaustion.
167 impl cmp::PartialEq for intern_key {
168     fn eq(&self, other: &intern_key) -> bool {
169         unsafe {
170             *self.sty == *other.sty
171         }
172     }
173     fn ne(&self, other: &intern_key) -> bool {
174         !self.eq(other)
175     }
176 }
177
178 impl Eq for intern_key {}
179
180 impl<W:Writer> Hash<W> for intern_key {
181     fn hash(&self, s: &mut W) {
182         unsafe { (*self.sty).hash(s) }
183     }
184 }
185
186 pub enum ast_ty_to_ty_cache_entry {
187     atttce_unresolved,  /* not resolved yet */
188     atttce_resolved(t)  /* resolved to a type, irrespective of region */
189 }
190
191 #[deriving(Clone, PartialEq, Decodable, Encodable)]
192 pub struct ItemVariances {
193     pub types: VecPerParamSpace<Variance>,
194     pub regions: VecPerParamSpace<Variance>,
195 }
196
197 #[deriving(Clone, PartialEq, Decodable, Encodable, Show)]
198 pub enum Variance {
199     Covariant,      // T<A> <: T<B> iff A <: B -- e.g., function return type
200     Invariant,      // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
201     Contravariant,  // T<A> <: T<B> iff B <: A -- e.g., function param type
202     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
203 }
204
205 #[deriving(Clone)]
206 pub enum AutoAdjustment {
207     AutoAddEnv(ty::TraitStore),
208     AutoDerefRef(AutoDerefRef),
209     AutoObject(ty::TraitStore,
210                ty::BuiltinBounds,
211                ast::DefId, /* Trait ID */
212                subst::Substs /* Trait substitutions */)
213 }
214
215 #[deriving(Clone, Decodable, Encodable)]
216 pub struct AutoDerefRef {
217     pub autoderefs: uint,
218     pub autoref: Option<AutoRef>
219 }
220
221 #[deriving(Clone, Decodable, Encodable, PartialEq, Show)]
222 pub enum AutoRef {
223     /// Convert from T to &T
224     AutoPtr(Region, ast::Mutability),
225
226     /// Convert from ~[]/&[] to &[] or str
227     AutoBorrowVec(Region, ast::Mutability),
228
229     /// Convert from ~[]/&[] to &&[] or str
230     AutoBorrowVecRef(Region, ast::Mutability),
231
232     /// Convert from T to *T
233     AutoUnsafe(ast::Mutability),
234
235     /// Convert from Box<Trait>/&Trait to &Trait
236     AutoBorrowObj(Region, ast::Mutability),
237 }
238
239 /// A restriction that certain types must be the same size. The use of
240 /// `transmute` gives rise to these restrictions.
241 pub struct TransmuteRestriction {
242     /// The span from whence the restriction comes.
243     pub span: Span,
244     /// The type being transmuted from.
245     pub from: t,
246     /// The type being transmuted to.
247     pub to: t,
248 }
249
250 /// The data structure to keep track of all the information that typechecker
251 /// generates so that so that it can be reused and doesn't have to be redone
252 /// later on.
253 pub struct ctxt {
254     /// Specifically use a speedy hash algorithm for this hash map, it's used
255     /// quite often.
256     pub interner: RefCell<FnvHashMap<intern_key, Box<t_box_>>>,
257     pub next_id: Cell<uint>,
258     pub sess: Session,
259     pub def_map: resolve::DefMap,
260
261     pub named_region_map: resolve_lifetime::NamedRegionMap,
262
263     pub region_maps: middle::region::RegionMaps,
264
265     /// Stores the types for various nodes in the AST.  Note that this table
266     /// is not guaranteed to be populated until after typeck.  See
267     /// typeck::check::fn_ctxt for details.
268     pub node_types: node_type_table,
269
270     /// Stores the type parameters which were substituted to obtain the type
271     /// of this node.  This only applies to nodes that refer to entities
272     /// param<eterized by type parameters, such as generic fns, types, or
273     /// other items.
274     pub item_substs: RefCell<NodeMap<ItemSubsts>>,
275
276     /// Maps from a method to the method "descriptor"
277     pub methods: RefCell<DefIdMap<Rc<Method>>>,
278
279     /// Maps from a trait def-id to a list of the def-ids of its methods
280     pub trait_method_def_ids: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
281
282     /// A cache for the trait_methods() routine
283     pub trait_methods_cache: RefCell<DefIdMap<Rc<Vec<Rc<Method>>>>>,
284
285     pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef>>>>,
286
287     pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
288     pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
289
290     pub map: ast_map::Map,
291     pub intrinsic_defs: RefCell<DefIdMap<t>>,
292     pub freevars: RefCell<freevars::freevar_map>,
293     pub tcache: type_cache,
294     pub rcache: creader_cache,
295     pub short_names_cache: RefCell<HashMap<t, String>>,
296     pub needs_unwind_cleanup_cache: RefCell<HashMap<t, bool>>,
297     pub tc_cache: RefCell<HashMap<uint, TypeContents>>,
298     pub ast_ty_to_ty_cache: RefCell<NodeMap<ast_ty_to_ty_cache_entry>>,
299     pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo>>>>>,
300     pub ty_param_defs: RefCell<NodeMap<TypeParameterDef>>,
301     pub adjustments: RefCell<NodeMap<AutoAdjustment>>,
302     pub normalized_cache: RefCell<HashMap<t, t>>,
303     pub lang_items: middle::lang_items::LanguageItems,
304     /// A mapping of fake provided method def_ids to the default implementation
305     pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
306     pub supertraits: RefCell<DefIdMap<Rc<Vec<Rc<TraitRef>>>>>,
307     pub superstructs: RefCell<DefIdMap<Option<ast::DefId>>>,
308     pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
309
310     /// Maps from def-id of a type or region parameter to its
311     /// (inferred) variance.
312     pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
313
314     /// A mapping from the def ID of an enum or struct type to the def ID
315     /// of the method that implements its destructor. If the type is not
316     /// present in this map, it does not have a destructor. This map is
317     /// populated during the coherence phase of typechecking.
318     pub destructor_for_type: RefCell<DefIdMap<ast::DefId>>,
319
320     /// A method will be in this list if and only if it is a destructor.
321     pub destructors: RefCell<DefIdSet>,
322
323     /// Maps a trait onto a list of impls of that trait.
324     pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
325
326     /// Maps a DefId of a type to a list of its inherent impls.
327     /// Contains implementations of methods that are inherent to a type.
328     /// Methods in these implementations don't need to be exported.
329     pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
330
331     /// Maps a DefId of an impl to a list of its methods.
332     /// Note that this contains all of the impls that we know about,
333     /// including ones in other crates. It's not clear that this is the best
334     /// way to do it.
335     pub impl_methods: RefCell<DefIdMap<Vec<ast::DefId>>>,
336
337     /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
338     /// present in this set can be warned about.
339     pub used_unsafe: RefCell<NodeSet>,
340
341     /// Set of nodes which mark locals as mutable which end up getting used at
342     /// some point. Local variable definitions not in this set can be warned
343     /// about.
344     pub used_mut_nodes: RefCell<NodeSet>,
345
346     /// vtable resolution information for impl declarations
347     pub impl_vtables: typeck::impl_vtable_map,
348
349     /// The set of external nominal types whose implementations have been read.
350     /// This is used for lazy resolution of methods.
351     pub populated_external_types: RefCell<DefIdSet>,
352
353     /// The set of external traits whose implementations have been read. This
354     /// is used for lazy resolution of traits.
355     pub populated_external_traits: RefCell<DefIdSet>,
356
357     /// Borrows
358     pub upvar_borrow_map: RefCell<UpvarBorrowMap>,
359
360     /// These two caches are used by const_eval when decoding external statics
361     /// and variants that are found.
362     pub extern_const_statics: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
363     pub extern_const_variants: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
364
365     pub method_map: typeck::MethodMap,
366     pub vtable_map: typeck::vtable_map,
367
368     pub dependency_formats: RefCell<dependency_format::Dependencies>,
369
370     pub node_lint_levels: RefCell<HashMap<(ast::NodeId, lint::LintId),
371                                           lint::LevelSource>>,
372
373     /// The types that must be asserted to be the same size for `transmute`
374     /// to be valid. We gather up these restrictions in the intrinsicck pass
375     /// and check them in trans.
376     pub transmute_restrictions: RefCell<Vec<TransmuteRestriction>>,
377
378     /// Maps any item's def-id to its stability index.
379     pub stability: RefCell<stability::Index>,
380 }
381
382 pub enum tbox_flag {
383     has_params = 1,
384     has_self = 2,
385     needs_infer = 4,
386     has_regions = 8,
387     has_ty_err = 16,
388     has_ty_bot = 32,
389
390     // a meta-pub flag: subst may be required if the type has parameters, a self
391     // type, or references bound regions
392     needs_subst = 1 | 2 | 8
393 }
394
395 pub type t_box = &'static t_box_;
396
397 pub struct t_box_ {
398     pub sty: sty,
399     pub id: uint,
400     pub flags: uint,
401 }
402
403 // To reduce refcounting cost, we're representing types as unsafe pointers
404 // throughout the compiler. These are simply casted t_box values. Use ty::get
405 // to cast them back to a box. (Without the cast, compiler performance suffers
406 // ~15%.) This does mean that a t value relies on the ctxt to keep its box
407 // alive, and using ty::get is unsafe when the ctxt is no longer alive.
408 enum t_opaque {}
409
410 #[allow(raw_pointer_deriving)]
411 #[deriving(Clone, PartialEq, Eq, Hash)]
412 pub struct t { inner: *const t_opaque }
413
414 impl fmt::Show for t {
415     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416         "*t_opaque".fmt(f)
417     }
418 }
419
420 pub fn get(t: t) -> t_box {
421     unsafe {
422         let t2: t_box = mem::transmute(t);
423         t2
424     }
425 }
426
427 pub fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
428     (tb.flags & (flag as uint)) != 0u
429 }
430 pub fn type_has_params(t: t) -> bool {
431     tbox_has_flag(get(t), has_params)
432 }
433 pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
434 pub fn type_needs_infer(t: t) -> bool {
435     tbox_has_flag(get(t), needs_infer)
436 }
437 pub fn type_id(t: t) -> uint { get(t).id }
438
439 #[deriving(Clone, PartialEq, Eq, Hash)]
440 pub struct BareFnTy {
441     pub fn_style: ast::FnStyle,
442     pub abi: abi::Abi,
443     pub sig: FnSig,
444 }
445
446 #[deriving(Clone, PartialEq, Eq, Hash)]
447 pub struct ClosureTy {
448     pub fn_style: ast::FnStyle,
449     pub onceness: ast::Onceness,
450     pub store: TraitStore,
451     pub bounds: BuiltinBounds,
452     pub sig: FnSig,
453 }
454
455 /**
456  * Signature of a function type, which I have arbitrarily
457  * decided to use to refer to the input/output types.
458  *
459  * - `binder_id` is the node id where this fn type appeared;
460  *   it is used to identify all the bound regions appearing
461  *   in the input/output types that are bound by this fn type
462  *   (vs some enclosing or enclosed fn type)
463  * - `inputs` is the list of arguments and their modes.
464  * - `output` is the return type.
465  * - `variadic` indicates whether this is a varidic function. (only true for foreign fns)
466  */
467 #[deriving(Clone, PartialEq, Eq, Hash)]
468 pub struct FnSig {
469     pub binder_id: ast::NodeId,
470     pub inputs: Vec<t>,
471     pub output: t,
472     pub variadic: bool
473 }
474
475 #[deriving(Clone, PartialEq, Eq, Hash)]
476 pub struct ParamTy {
477     pub space: subst::ParamSpace,
478     pub idx: uint,
479     pub def_id: DefId
480 }
481
482 /// Representation of regions:
483 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
484 pub enum Region {
485     // Region bound in a type or fn declaration which will be
486     // substituted 'early' -- that is, at the same time when type
487     // parameters are substituted.
488     ReEarlyBound(/* param id */ ast::NodeId,
489                  subst::ParamSpace,
490                  /*index*/ uint,
491                  ast::Name),
492
493     // Region bound in a function scope, which will be substituted when the
494     // function is called. The first argument must be the `binder_id` of
495     // some enclosing function signature.
496     ReLateBound(/* binder_id */ ast::NodeId, BoundRegion),
497
498     /// When checking a function body, the types of all arguments and so forth
499     /// that refer to bound region parameters are modified to refer to free
500     /// region parameters.
501     ReFree(FreeRegion),
502
503     /// A concrete region naming some expression within the current function.
504     ReScope(NodeId),
505
506     /// Static data that has an "infinite" lifetime. Top in the region lattice.
507     ReStatic,
508
509     /// A region variable.  Should not exist after typeck.
510     ReInfer(InferRegion),
511
512     /// Empty lifetime is for data that is never accessed.
513     /// Bottom in the region lattice. We treat ReEmpty somewhat
514     /// specially; at least right now, we do not generate instances of
515     /// it during the GLB computations, but rather
516     /// generate an error instead. This is to improve error messages.
517     /// The only way to get an instance of ReEmpty is to have a region
518     /// variable with no constraints.
519     ReEmpty,
520 }
521
522 /**
523  * Upvars do not get their own node-id. Instead, we use the pair of
524  * the original var id (that is, the root variable that is referenced
525  * by the upvar) and the id of the closure expression.
526  */
527 #[deriving(Clone, PartialEq, Eq, Hash)]
528 pub struct UpvarId {
529     pub var_id: ast::NodeId,
530     pub closure_expr_id: ast::NodeId,
531 }
532
533 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
534 pub enum BorrowKind {
535     /// Data must be immutable and is aliasable.
536     ImmBorrow,
537
538     /// Data must be immutable but not aliasable.  This kind of borrow
539     /// cannot currently be expressed by the user and is used only in
540     /// implicit closure bindings. It is needed when you the closure
541     /// is borrowing or mutating a mutable referent, e.g.:
542     ///
543     ///    let x: &mut int = ...;
544     ///    let y = || *x += 5;
545     ///
546     /// If we were to try to translate this closure into a more explicit
547     /// form, we'd encounter an error with the code as written:
548     ///
549     ///    struct Env { x: & &mut int }
550     ///    let x: &mut int = ...;
551     ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
552     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
553     ///
554     /// This is then illegal because you cannot mutate a `&mut` found
555     /// in an aliasable location. To solve, you'd have to translate with
556     /// an `&mut` borrow:
557     ///
558     ///    struct Env { x: & &mut int }
559     ///    let x: &mut int = ...;
560     ///    let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
561     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
562     ///
563     /// Now the assignment to `**env.x` is legal, but creating a
564     /// mutable pointer to `x` is not because `x` is not mutable. We
565     /// could fix this by declaring `x` as `let mut x`. This is ok in
566     /// user code, if awkward, but extra weird for closures, since the
567     /// borrow is hidden.
568     ///
569     /// So we introduce a "unique imm" borrow -- the referent is
570     /// immutable, but not aliasable. This solves the problem. For
571     /// simplicity, we don't give users the way to express this
572     /// borrow, it's just used when translating closures.
573     UniqueImmBorrow,
574
575     /// Data is mutable and not aliasable.
576     MutBorrow
577 }
578
579 /**
580  * Information describing the borrowing of an upvar. This is computed
581  * during `typeck`, specifically by `regionck`. The general idea is
582  * that the compiler analyses treat closures like:
583  *
584  *     let closure: &'e fn() = || {
585  *        x = 1;   // upvar x is assigned to
586  *        use(y);  // upvar y is read
587  *        foo(&z); // upvar z is borrowed immutably
588  *     };
589  *
590  * as if they were "desugared" to something loosely like:
591  *
592  *     struct Vars<'x,'y,'z> { x: &'x mut int,
593  *                             y: &'y const int,
594  *                             z: &'z int }
595  *     let closure: &'e fn() = {
596  *         fn f(env: &Vars) {
597  *             *env.x = 1;
598  *             use(*env.y);
599  *             foo(env.z);
600  *         }
601  *         let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x,
602  *                                                       y: &'y const y,
603  *                                                       z: &'z z };
604  *         (env, f)
605  *     };
606  *
607  * This is basically what happens at runtime. The closure is basically
608  * an existentially quantified version of the `(env, f)` pair.
609  *
610  * This data structure indicates the region and mutability of a single
611  * one of the `x...z` borrows.
612  *
613  * It may not be obvious why each borrowed variable gets its own
614  * lifetime (in the desugared version of the example, these are indicated
615  * by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition).
616  * Each such lifetime must encompass the lifetime `'e` of the closure itself,
617  * but need not be identical to it. The reason that this makes sense:
618  *
619  * - Callers are only permitted to invoke the closure, and hence to
620  *   use the pointers, within the lifetime `'e`, so clearly `'e` must
621  *   be a sublifetime of `'x...'z`.
622  * - The closure creator knows which upvars were borrowed by the closure
623  *   and thus `x...z` will be reserved for `'x...'z` respectively.
624  * - Through mutation, the borrowed upvars can actually escape
625  *   the closure, so sometimes it is necessary for them to be larger
626  *   than the closure lifetime itself.
627  */
628 #[deriving(PartialEq, Clone)]
629 pub struct UpvarBorrow {
630     pub kind: BorrowKind,
631     pub region: ty::Region,
632 }
633
634 pub type UpvarBorrowMap = HashMap<UpvarId, UpvarBorrow>;
635
636 impl Region {
637     pub fn is_bound(&self) -> bool {
638         match self {
639             &ty::ReEarlyBound(..) => true,
640             &ty::ReLateBound(..) => true,
641             _ => false
642         }
643     }
644 }
645
646 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
647 pub struct FreeRegion {
648     pub scope_id: NodeId,
649     pub bound_region: BoundRegion
650 }
651
652 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
653 pub enum BoundRegion {
654     /// An anonymous region parameter for a given fn (&T)
655     BrAnon(uint),
656
657     /// Named region parameters for functions (a in &'a T)
658     ///
659     /// The def-id is needed to distinguish free regions in
660     /// the event of shadowing.
661     BrNamed(ast::DefId, ast::Name),
662
663     /// Fresh bound identifiers created during GLB computations.
664     BrFresh(uint),
665 }
666
667 mod primitives {
668     use super::t_box_;
669
670     use syntax::ast;
671
672     macro_rules! def_prim_ty(
673         ($name:ident, $sty:expr, $id:expr) => (
674             pub static $name: t_box_ = t_box_ {
675                 sty: $sty,
676                 id: $id,
677                 flags: 0,
678             };
679         )
680     )
681
682     def_prim_ty!(TY_NIL,    super::ty_nil,                  0)
683     def_prim_ty!(TY_BOOL,   super::ty_bool,                 1)
684     def_prim_ty!(TY_CHAR,   super::ty_char,                 2)
685     def_prim_ty!(TY_INT,    super::ty_int(ast::TyI),        3)
686     def_prim_ty!(TY_I8,     super::ty_int(ast::TyI8),       4)
687     def_prim_ty!(TY_I16,    super::ty_int(ast::TyI16),      5)
688     def_prim_ty!(TY_I32,    super::ty_int(ast::TyI32),      6)
689     def_prim_ty!(TY_I64,    super::ty_int(ast::TyI64),      7)
690     def_prim_ty!(TY_UINT,   super::ty_uint(ast::TyU),       8)
691     def_prim_ty!(TY_U8,     super::ty_uint(ast::TyU8),      9)
692     def_prim_ty!(TY_U16,    super::ty_uint(ast::TyU16),     10)
693     def_prim_ty!(TY_U32,    super::ty_uint(ast::TyU32),     11)
694     def_prim_ty!(TY_U64,    super::ty_uint(ast::TyU64),     12)
695     def_prim_ty!(TY_F32,    super::ty_float(ast::TyF32),    14)
696     def_prim_ty!(TY_F64,    super::ty_float(ast::TyF64),    15)
697
698     pub static TY_BOT: t_box_ = t_box_ {
699         sty: super::ty_bot,
700         id: 16,
701         flags: super::has_ty_bot as uint,
702     };
703
704     pub static TY_ERR: t_box_ = t_box_ {
705         sty: super::ty_err,
706         id: 17,
707         flags: super::has_ty_err as uint,
708     };
709
710     pub static LAST_PRIMITIVE_ID: uint = 18;
711 }
712
713 // NB: If you change this, you'll probably want to change the corresponding
714 // AST structure in libsyntax/ast.rs as well.
715 #[deriving(Clone, PartialEq, Eq, Hash)]
716 pub enum sty {
717     ty_nil,
718     ty_bot,
719     ty_bool,
720     ty_char,
721     ty_int(ast::IntTy),
722     ty_uint(ast::UintTy),
723     ty_float(ast::FloatTy),
724     ty_enum(DefId, Substs),
725     ty_box(t),
726     ty_uniq(t),
727     ty_str,
728     ty_vec(mt, Option<uint>),  // Second field is length.
729     ty_ptr(mt),
730     ty_rptr(Region, mt),
731     ty_bare_fn(BareFnTy),
732     ty_closure(Box<ClosureTy>),
733     ty_trait(Box<TyTrait>),
734     ty_struct(DefId, Substs),
735     ty_tup(Vec<t>),
736
737     ty_param(ParamTy), // type parameter
738     ty_infer(InferTy), // something used only during inference/typeck
739     ty_err, // Also only used during inference/typeck, to represent
740             // the type of an erroneous expression (helps cut down
741             // on non-useful type error messages)
742 }
743
744 #[deriving(Clone, PartialEq, Eq, Hash)]
745 pub struct TyTrait {
746     pub def_id: DefId,
747     pub substs: Substs,
748     pub bounds: BuiltinBounds
749 }
750
751 #[deriving(PartialEq, Eq, Hash)]
752 pub struct TraitRef {
753     pub def_id: DefId,
754     pub substs: Substs,
755 }
756
757 #[deriving(Clone, PartialEq)]
758 pub enum IntVarValue {
759     IntType(ast::IntTy),
760     UintType(ast::UintTy),
761 }
762
763 #[deriving(Clone, Show)]
764 pub enum terr_vstore_kind {
765     terr_vec,
766     terr_str,
767     terr_fn,
768     terr_trait
769 }
770
771 #[deriving(Clone, Show)]
772 pub struct expected_found<T> {
773     pub expected: T,
774     pub found: T
775 }
776
777 // Data structures used in type unification
778 #[deriving(Clone, Show)]
779 pub enum type_err {
780     terr_mismatch,
781     terr_fn_style_mismatch(expected_found<FnStyle>),
782     terr_onceness_mismatch(expected_found<Onceness>),
783     terr_abi_mismatch(expected_found<abi::Abi>),
784     terr_mutability,
785     terr_sigil_mismatch(expected_found<TraitStore>),
786     terr_box_mutability,
787     terr_ptr_mutability,
788     terr_ref_mutability,
789     terr_vec_mutability,
790     terr_tuple_size(expected_found<uint>),
791     terr_ty_param_size(expected_found<uint>),
792     terr_record_size(expected_found<uint>),
793     terr_record_mutability,
794     terr_record_fields(expected_found<Ident>),
795     terr_arg_count,
796     terr_regions_does_not_outlive(Region, Region),
797     terr_regions_not_same(Region, Region),
798     terr_regions_no_overlap(Region, Region),
799     terr_regions_insufficiently_polymorphic(BoundRegion, Region),
800     terr_regions_overly_polymorphic(BoundRegion, Region),
801     terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
802     terr_sorts(expected_found<t>),
803     terr_integer_as_char,
804     terr_int_mismatch(expected_found<IntVarValue>),
805     terr_float_mismatch(expected_found<ast::FloatTy>),
806     terr_traits(expected_found<ast::DefId>),
807     terr_builtin_bounds(expected_found<BuiltinBounds>),
808     terr_variadic_mismatch(expected_found<bool>)
809 }
810
811 #[deriving(PartialEq, Eq, Hash)]
812 pub struct ParamBounds {
813     pub builtin_bounds: BuiltinBounds,
814     pub trait_bounds: Vec<Rc<TraitRef>>
815 }
816
817 pub type BuiltinBounds = EnumSet<BuiltinBound>;
818
819 #[deriving(Clone, Encodable, PartialEq, Eq, Decodable, Hash, Show)]
820 #[repr(uint)]
821 pub enum BuiltinBound {
822     BoundStatic,
823     BoundSend,
824     BoundSized,
825     BoundCopy,
826     BoundShare,
827 }
828
829 pub fn empty_builtin_bounds() -> BuiltinBounds {
830     EnumSet::empty()
831 }
832
833 pub fn all_builtin_bounds() -> BuiltinBounds {
834     let mut set = EnumSet::empty();
835     set.add(BoundStatic);
836     set.add(BoundSend);
837     set.add(BoundSized);
838     set.add(BoundShare);
839     set
840 }
841
842 impl CLike for BuiltinBound {
843     fn to_uint(&self) -> uint {
844         *self as uint
845     }
846     fn from_uint(v: uint) -> BuiltinBound {
847         unsafe { mem::transmute(v) }
848     }
849 }
850
851 #[deriving(Clone, PartialEq, Eq, Hash)]
852 pub struct TyVid {
853     pub index: uint
854 }
855
856 #[deriving(Clone, PartialEq, Eq, Hash)]
857 pub struct IntVid {
858     pub index: uint
859 }
860
861 #[deriving(Clone, PartialEq, Eq, Hash)]
862 pub struct FloatVid {
863     pub index: uint
864 }
865
866 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
867 pub struct RegionVid {
868     pub index: uint
869 }
870
871 #[deriving(Clone, PartialEq, Eq, Hash)]
872 pub enum InferTy {
873     TyVar(TyVid),
874     IntVar(IntVid),
875     FloatVar(FloatVid)
876 }
877
878 #[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
879 pub enum InferRegion {
880     ReVar(RegionVid),
881     ReSkolemized(uint, BoundRegion)
882 }
883
884 impl cmp::PartialEq for InferRegion {
885     fn eq(&self, other: &InferRegion) -> bool {
886         match ((*self), *other) {
887             (ReVar(rva), ReVar(rvb)) => {
888                 rva == rvb
889             }
890             (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
891                 rva == rvb
892             }
893             _ => false
894         }
895     }
896     fn ne(&self, other: &InferRegion) -> bool {
897         !((*self) == (*other))
898     }
899 }
900
901 impl fmt::Show for TyVid {
902     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
903         write!(f, "<generic #{}>", self.index)
904     }
905 }
906
907 impl fmt::Show for IntVid {
908     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
909         write!(f, "<generic integer #{}>", self.index)
910     }
911 }
912
913 impl fmt::Show for FloatVid {
914     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
915         write!(f, "<generic float #{}>", self.index)
916     }
917 }
918
919 impl fmt::Show for RegionVid {
920     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
921         write!(f, "'<generic lifetime #{}>", self.index)
922     }
923 }
924
925 impl fmt::Show for FnSig {
926     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
927         // grr, without tcx not much we can do.
928         write!(f, "(...)")
929     }
930 }
931
932 impl fmt::Show for InferTy {
933     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
934         match *self {
935             TyVar(ref v) => v.fmt(f),
936             IntVar(ref v) => v.fmt(f),
937             FloatVar(ref v) => v.fmt(f),
938         }
939     }
940 }
941
942 impl fmt::Show for IntVarValue {
943     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
944         match *self {
945             IntType(ref v) => v.fmt(f),
946             UintType(ref v) => v.fmt(f),
947         }
948     }
949 }
950
951 #[deriving(Clone)]
952 pub struct TypeParameterDef {
953     pub ident: ast::Ident,
954     pub def_id: ast::DefId,
955     pub space: subst::ParamSpace,
956     pub index: uint,
957     pub bounds: Rc<ParamBounds>,
958     pub default: Option<ty::t>
959 }
960
961 #[deriving(Encodable, Decodable, Clone)]
962 pub struct RegionParameterDef {
963     pub name: ast::Name,
964     pub def_id: ast::DefId,
965     pub space: subst::ParamSpace,
966     pub index: uint,
967 }
968
969 /// Information about the type/lifetime parameters associated with an
970 /// item or method. Analogous to ast::Generics.
971 #[deriving(Clone)]
972 pub struct Generics {
973     pub types: VecPerParamSpace<TypeParameterDef>,
974     pub regions: VecPerParamSpace<RegionParameterDef>,
975 }
976
977 impl Generics {
978     pub fn empty() -> Generics {
979         Generics { types: VecPerParamSpace::empty(),
980                    regions: VecPerParamSpace::empty() }
981     }
982
983     pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
984         !self.types.get_vec(space).is_empty()
985     }
986 }
987
988 /// When type checking, we use the `ParameterEnvironment` to track
989 /// details about the type/lifetime parameters that are in scope.
990 /// It primarily stores the bounds information.
991 ///
992 /// Note: This information might seem to be redundant with the data in
993 /// `tcx.ty_param_defs`, but it is not. That table contains the
994 /// parameter definitions from an "outside" perspective, but this
995 /// struct will contain the bounds for a parameter as seen from inside
996 /// the function body. Currently the only real distinction is that
997 /// bound lifetime parameters are replaced with free ones, but in the
998 /// future I hope to refine the representation of types so as to make
999 /// more distinctions clearer.
1000 pub struct ParameterEnvironment {
1001     /// A substitution that can be applied to move from
1002     /// the "outer" view of a type or method to the "inner" view.
1003     /// In general, this means converting from bound parameters to
1004     /// free parameters. Since we currently represent bound/free type
1005     /// parameters in the same way, this only has an affect on regions.
1006     pub free_substs: Substs,
1007
1008     /// Bounds on the various type parameters
1009     pub bounds: VecPerParamSpace<ParamBounds>,
1010 }
1011
1012 /// A polytype.
1013 ///
1014 /// - `generics`: the set of type parameters and their bounds
1015 /// - `ty`: the base types, which may reference the parameters defined
1016 ///   in `generics`
1017 #[deriving(Clone)]
1018 pub struct Polytype {
1019     pub generics: Generics,
1020     pub ty: t
1021 }
1022
1023 /// As `Polytype` but for a trait ref.
1024 pub struct TraitDef {
1025     pub generics: Generics,
1026     pub bounds: BuiltinBounds,
1027     pub trait_ref: Rc<ty::TraitRef>,
1028 }
1029
1030 /// Records the substitutions used to translate the polytype for an
1031 /// item into the monotype of an item reference.
1032 #[deriving(Clone)]
1033 pub struct ItemSubsts {
1034     pub substs: Substs,
1035 }
1036
1037 pub type type_cache = RefCell<DefIdMap<Polytype>>;
1038
1039 pub type node_type_table = RefCell<HashMap<uint,t>>;
1040
1041 pub fn mk_ctxt(s: Session,
1042                dm: resolve::DefMap,
1043                named_region_map: resolve_lifetime::NamedRegionMap,
1044                map: ast_map::Map,
1045                freevars: freevars::freevar_map,
1046                region_maps: middle::region::RegionMaps,
1047                lang_items: middle::lang_items::LanguageItems,
1048                stability: stability::Index)
1049             -> ctxt {
1050     ctxt {
1051         named_region_map: named_region_map,
1052         item_variance_map: RefCell::new(DefIdMap::new()),
1053         interner: RefCell::new(FnvHashMap::new()),
1054         next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
1055         sess: s,
1056         def_map: dm,
1057         region_maps: region_maps,
1058         node_types: RefCell::new(HashMap::new()),
1059         item_substs: RefCell::new(NodeMap::new()),
1060         trait_refs: RefCell::new(NodeMap::new()),
1061         trait_defs: RefCell::new(DefIdMap::new()),
1062         map: map,
1063         intrinsic_defs: RefCell::new(DefIdMap::new()),
1064         freevars: RefCell::new(freevars),
1065         tcache: RefCell::new(DefIdMap::new()),
1066         rcache: RefCell::new(HashMap::new()),
1067         short_names_cache: RefCell::new(HashMap::new()),
1068         needs_unwind_cleanup_cache: RefCell::new(HashMap::new()),
1069         tc_cache: RefCell::new(HashMap::new()),
1070         ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
1071         enum_var_cache: RefCell::new(DefIdMap::new()),
1072         methods: RefCell::new(DefIdMap::new()),
1073         trait_method_def_ids: RefCell::new(DefIdMap::new()),
1074         trait_methods_cache: RefCell::new(DefIdMap::new()),
1075         impl_trait_cache: RefCell::new(DefIdMap::new()),
1076         ty_param_defs: RefCell::new(NodeMap::new()),
1077         adjustments: RefCell::new(NodeMap::new()),
1078         normalized_cache: RefCell::new(HashMap::new()),
1079         lang_items: lang_items,
1080         provided_method_sources: RefCell::new(DefIdMap::new()),
1081         supertraits: RefCell::new(DefIdMap::new()),
1082         superstructs: RefCell::new(DefIdMap::new()),
1083         struct_fields: RefCell::new(DefIdMap::new()),
1084         destructor_for_type: RefCell::new(DefIdMap::new()),
1085         destructors: RefCell::new(DefIdSet::new()),
1086         trait_impls: RefCell::new(DefIdMap::new()),
1087         inherent_impls: RefCell::new(DefIdMap::new()),
1088         impl_methods: RefCell::new(DefIdMap::new()),
1089         used_unsafe: RefCell::new(NodeSet::new()),
1090         used_mut_nodes: RefCell::new(NodeSet::new()),
1091         impl_vtables: RefCell::new(DefIdMap::new()),
1092         populated_external_types: RefCell::new(DefIdSet::new()),
1093         populated_external_traits: RefCell::new(DefIdSet::new()),
1094         upvar_borrow_map: RefCell::new(HashMap::new()),
1095         extern_const_statics: RefCell::new(DefIdMap::new()),
1096         extern_const_variants: RefCell::new(DefIdMap::new()),
1097         method_map: RefCell::new(FnvHashMap::new()),
1098         vtable_map: RefCell::new(FnvHashMap::new()),
1099         dependency_formats: RefCell::new(HashMap::new()),
1100         node_lint_levels: RefCell::new(HashMap::new()),
1101         transmute_restrictions: RefCell::new(Vec::new()),
1102         stability: RefCell::new(stability)
1103     }
1104 }
1105
1106 // Type constructors
1107
1108 // Interns a type/name combination, stores the resulting box in cx.interner,
1109 // and returns the box as cast to an unsafe ptr (see comments for t above).
1110 pub fn mk_t(cx: &ctxt, st: sty) -> t {
1111     // Check for primitive types.
1112     match st {
1113         ty_nil => return mk_nil(),
1114         ty_err => return mk_err(),
1115         ty_bool => return mk_bool(),
1116         ty_int(i) => return mk_mach_int(i),
1117         ty_uint(u) => return mk_mach_uint(u),
1118         ty_float(f) => return mk_mach_float(f),
1119         ty_char => return mk_char(),
1120         ty_bot => return mk_bot(),
1121         _ => {}
1122     };
1123
1124     let key = intern_key { sty: &st };
1125
1126     match cx.interner.borrow().find(&key) {
1127         Some(t) => unsafe { return mem::transmute(&t.sty); },
1128         _ => ()
1129     }
1130
1131     let mut flags = 0u;
1132     fn rflags(r: Region) -> uint {
1133         (has_regions as uint) | {
1134             match r {
1135               ty::ReInfer(_) => needs_infer as uint,
1136               _ => 0u
1137             }
1138         }
1139     }
1140     fn sflags(substs: &Substs) -> uint {
1141         let mut f = 0u;
1142         let mut i = substs.types.iter();
1143         for tt in i {
1144             f |= get(*tt).flags;
1145         }
1146         match substs.regions {
1147             subst::ErasedRegions => {}
1148             subst::NonerasedRegions(ref regions) => {
1149                 for r in regions.iter() {
1150                     f |= rflags(*r)
1151                 }
1152             }
1153         }
1154         return f;
1155     }
1156     match &st {
1157       &ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
1158       &ty_str => {}
1159       // You might think that we could just return ty_err for
1160       // any type containing ty_err as a component, and get
1161       // rid of the has_ty_err flag -- likewise for ty_bot (with
1162       // the exception of function types that return bot).
1163       // But doing so caused sporadic memory corruption, and
1164       // neither I (tjc) nor nmatsakis could figure out why,
1165       // so we're doing it this way.
1166       &ty_bot => flags |= has_ty_bot as uint,
1167       &ty_err => flags |= has_ty_err as uint,
1168       &ty_param(ref p) => {
1169           if p.space == subst::SelfSpace {
1170               flags |= has_self as uint;
1171           } else {
1172               flags |= has_params as uint;
1173           }
1174       }
1175       &ty_infer(_) => flags |= needs_infer as uint,
1176       &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
1177           flags |= sflags(substs);
1178       }
1179       &ty_trait(box ty::TyTrait { ref substs, .. }) => {
1180           flags |= sflags(substs);
1181       }
1182       &ty_box(tt) | &ty_uniq(tt) => {
1183         flags |= get(tt).flags
1184       }
1185       &ty_ptr(ref m) | &ty_vec(ref m, _) => {
1186         flags |= get(m.ty).flags;
1187       }
1188       &ty_rptr(r, ref m) => {
1189         flags |= rflags(r);
1190         flags |= get(m.ty).flags;
1191       }
1192       &ty_tup(ref ts) => for tt in ts.iter() { flags |= get(*tt).flags; },
1193       &ty_bare_fn(ref f) => {
1194         for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
1195         flags |= get(f.sig.output).flags;
1196         // T -> _|_ is *not* _|_ !
1197         flags &= !(has_ty_bot as uint);
1198       }
1199       &ty_closure(ref f) => {
1200         match f.store {
1201             RegionTraitStore(r, _) => {
1202                 flags |= rflags(r);
1203             }
1204             _ => {}
1205         }
1206         for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
1207         flags |= get(f.sig.output).flags;
1208         // T -> _|_ is *not* _|_ !
1209         flags &= !(has_ty_bot as uint);
1210       }
1211     }
1212
1213     let t = box t_box_ {
1214         sty: st,
1215         id: cx.next_id.get(),
1216         flags: flags,
1217     };
1218
1219     let sty_ptr = &t.sty as *const sty;
1220
1221     let key = intern_key {
1222         sty: sty_ptr,
1223     };
1224
1225     cx.interner.borrow_mut().insert(key, t);
1226
1227     cx.next_id.set(cx.next_id.get() + 1);
1228
1229     unsafe {
1230         mem::transmute::<*const sty, t>(sty_ptr)
1231     }
1232 }
1233
1234 #[inline]
1235 pub fn mk_prim_t(primitive: &'static t_box_) -> t {
1236     unsafe {
1237         mem::transmute::<&'static t_box_, t>(primitive)
1238     }
1239 }
1240
1241 #[inline]
1242 pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) }
1243
1244 #[inline]
1245 pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) }
1246
1247 #[inline]
1248 pub fn mk_bot() -> t { mk_prim_t(&primitives::TY_BOT) }
1249
1250 #[inline]
1251 pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) }
1252
1253 #[inline]
1254 pub fn mk_int() -> t { mk_prim_t(&primitives::TY_INT) }
1255
1256 #[inline]
1257 pub fn mk_i8() -> t { mk_prim_t(&primitives::TY_I8) }
1258
1259 #[inline]
1260 pub fn mk_i16() -> t { mk_prim_t(&primitives::TY_I16) }
1261
1262 #[inline]
1263 pub fn mk_i32() -> t { mk_prim_t(&primitives::TY_I32) }
1264
1265 #[inline]
1266 pub fn mk_i64() -> t { mk_prim_t(&primitives::TY_I64) }
1267
1268 #[inline]
1269 pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) }
1270
1271 #[inline]
1272 pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
1273
1274 #[inline]
1275 pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
1276
1277 #[inline]
1278 pub fn mk_u8() -> t { mk_prim_t(&primitives::TY_U8) }
1279
1280 #[inline]
1281 pub fn mk_u16() -> t { mk_prim_t(&primitives::TY_U16) }
1282
1283 #[inline]
1284 pub fn mk_u32() -> t { mk_prim_t(&primitives::TY_U32) }
1285
1286 #[inline]
1287 pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) }
1288
1289 pub fn mk_mach_int(tm: ast::IntTy) -> t {
1290     match tm {
1291         ast::TyI    => mk_int(),
1292         ast::TyI8   => mk_i8(),
1293         ast::TyI16  => mk_i16(),
1294         ast::TyI32  => mk_i32(),
1295         ast::TyI64  => mk_i64(),
1296     }
1297 }
1298
1299 pub fn mk_mach_uint(tm: ast::UintTy) -> t {
1300     match tm {
1301         ast::TyU    => mk_uint(),
1302         ast::TyU8   => mk_u8(),
1303         ast::TyU16  => mk_u16(),
1304         ast::TyU32  => mk_u32(),
1305         ast::TyU64  => mk_u64(),
1306     }
1307 }
1308
1309 pub fn mk_mach_float(tm: ast::FloatTy) -> t {
1310     match tm {
1311         ast::TyF32  => mk_f32(),
1312         ast::TyF64  => mk_f64(),
1313     }
1314 }
1315
1316 #[inline]
1317 pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
1318
1319 pub fn mk_str(cx: &ctxt) -> t {
1320     mk_t(cx, ty_str)
1321 }
1322
1323 pub fn mk_str_slice(cx: &ctxt, r: Region, m: ast::Mutability) -> t {
1324     mk_rptr(cx, r,
1325             mt {
1326                 ty: mk_t(cx, ty_str),
1327                 mutbl: m
1328             })
1329 }
1330
1331 pub fn mk_enum(cx: &ctxt, did: ast::DefId, substs: Substs) -> t {
1332     // take a copy of substs so that we own the vectors inside
1333     mk_t(cx, ty_enum(did, substs))
1334 }
1335
1336 pub fn mk_box(cx: &ctxt, ty: t) -> t { mk_t(cx, ty_box(ty)) }
1337
1338 pub fn mk_uniq(cx: &ctxt, ty: t) -> t { mk_t(cx, ty_uniq(ty)) }
1339
1340 pub fn mk_ptr(cx: &ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
1341
1342 pub fn mk_rptr(cx: &ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
1343
1344 pub fn mk_mut_rptr(cx: &ctxt, r: Region, ty: t) -> t {
1345     mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutMutable})
1346 }
1347 pub fn mk_imm_rptr(cx: &ctxt, r: Region, ty: t) -> t {
1348     mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutImmutable})
1349 }
1350
1351 pub fn mk_mut_ptr(cx: &ctxt, ty: t) -> t {
1352     mk_ptr(cx, mt {ty: ty, mutbl: ast::MutMutable})
1353 }
1354
1355 pub fn mk_imm_ptr(cx: &ctxt, ty: t) -> t {
1356     mk_ptr(cx, mt {ty: ty, mutbl: ast::MutImmutable})
1357 }
1358
1359 pub fn mk_nil_ptr(cx: &ctxt) -> t {
1360     mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::MutImmutable})
1361 }
1362
1363 pub fn mk_vec(cx: &ctxt, tm: mt, sz: Option<uint>) -> t {
1364     mk_t(cx, ty_vec(tm, sz))
1365 }
1366
1367 pub fn mk_slice(cx: &ctxt, r: Region, tm: mt) -> t {
1368     mk_rptr(cx, r,
1369             mt {
1370                 ty: mk_vec(cx, tm, None),
1371                 mutbl: tm.mutbl
1372             })
1373 }
1374
1375 pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
1376
1377 pub fn mk_closure(cx: &ctxt, fty: ClosureTy) -> t {
1378     mk_t(cx, ty_closure(box fty))
1379 }
1380
1381 pub fn mk_bare_fn(cx: &ctxt, fty: BareFnTy) -> t {
1382     mk_t(cx, ty_bare_fn(fty))
1383 }
1384
1385 pub fn mk_ctor_fn(cx: &ctxt,
1386                   binder_id: ast::NodeId,
1387                   input_tys: &[ty::t],
1388                   output: ty::t) -> t {
1389     let input_args = input_tys.iter().map(|t| *t).collect();
1390     mk_bare_fn(cx,
1391                BareFnTy {
1392                    fn_style: ast::NormalFn,
1393                    abi: abi::Rust,
1394                    sig: FnSig {
1395                     binder_id: binder_id,
1396                     inputs: input_args,
1397                     output: output,
1398                     variadic: false
1399                    }
1400                 })
1401 }
1402
1403
1404 pub fn mk_trait(cx: &ctxt,
1405                 did: ast::DefId,
1406                 substs: Substs,
1407                 bounds: BuiltinBounds)
1408              -> t {
1409     // take a copy of substs so that we own the vectors inside
1410     let inner = box TyTrait {
1411         def_id: did,
1412         substs: substs,
1413         bounds: bounds
1414     };
1415     mk_t(cx, ty_trait(inner))
1416 }
1417
1418 pub fn mk_struct(cx: &ctxt, struct_id: ast::DefId, substs: Substs) -> t {
1419     // take a copy of substs so that we own the vectors inside
1420     mk_t(cx, ty_struct(struct_id, substs))
1421 }
1422
1423 pub fn mk_var(cx: &ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
1424
1425 pub fn mk_int_var(cx: &ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }
1426
1427 pub fn mk_float_var(cx: &ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
1428
1429 pub fn mk_infer(cx: &ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
1430
1431 pub fn mk_param(cx: &ctxt, space: subst::ParamSpace, n: uint, k: DefId) -> t {
1432     mk_t(cx, ty_param(ParamTy { space: space, idx: n, def_id: k }))
1433 }
1434
1435 pub fn mk_self_type(cx: &ctxt, did: ast::DefId) -> t {
1436     mk_param(cx, subst::SelfSpace, 0, did)
1437 }
1438
1439 pub fn mk_param_from_def(cx: &ctxt, def: &TypeParameterDef) -> t {
1440     mk_param(cx, def.space, def.index, def.def_id)
1441 }
1442
1443 pub fn walk_ty(ty: t, f: |t|) {
1444     maybe_walk_ty(ty, |t| { f(t); true });
1445 }
1446
1447 pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
1448     if !f(ty) {
1449         return;
1450     }
1451     match get(ty).sty {
1452         ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
1453         ty_str | ty_infer(_) | ty_param(_) | ty_err => {
1454         }
1455         ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
1456         ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_vec(ref tm, _) => {
1457             maybe_walk_ty(tm.ty, f);
1458         }
1459         ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1460         ty_trait(box TyTrait { ref substs, .. }) => {
1461             for subty in (*substs).types.iter() {
1462                 maybe_walk_ty(*subty, |x| f(x));
1463             }
1464         }
1465         ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
1466         ty_bare_fn(ref ft) => {
1467             for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
1468             maybe_walk_ty(ft.sig.output, f);
1469         }
1470         ty_closure(ref ft) => {
1471             for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
1472             maybe_walk_ty(ft.sig.output, f);
1473         }
1474     }
1475 }
1476
1477 // Folds types from the bottom up.
1478 pub fn fold_ty(cx: &ctxt, t0: t, fldop: |t| -> t) -> t {
1479     let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop};
1480     f.fold_ty(t0)
1481 }
1482
1483 pub fn walk_regions_and_ty(cx: &ctxt, ty: t, fldr: |r: Region|, fldt: |t: t|)
1484                            -> t {
1485     ty_fold::RegionFolder::general(cx,
1486                                    |r| { fldr(r); r },
1487                                    |t| { fldt(t); t }).fold_ty(ty)
1488 }
1489
1490 impl ItemSubsts {
1491     pub fn empty() -> ItemSubsts {
1492         ItemSubsts { substs: Substs::empty() }
1493     }
1494
1495     pub fn is_noop(&self) -> bool {
1496         self.substs.is_noop()
1497     }
1498 }
1499
1500 // Type utilities
1501
1502 pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
1503
1504 pub fn type_is_bot(ty: t) -> bool {
1505     (get(ty).flags & (has_ty_bot as uint)) != 0
1506 }
1507
1508 pub fn type_is_error(ty: t) -> bool {
1509     (get(ty).flags & (has_ty_err as uint)) != 0
1510 }
1511
1512 pub fn type_needs_subst(ty: t) -> bool {
1513     tbox_has_flag(get(ty), needs_subst)
1514 }
1515
1516 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
1517     tref.substs.types.any(|&t| type_is_error(t))
1518 }
1519
1520 pub fn type_is_ty_var(ty: t) -> bool {
1521     match get(ty).sty {
1522       ty_infer(TyVar(_)) => true,
1523       _ => false
1524     }
1525 }
1526
1527 pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
1528
1529 pub fn type_is_self(ty: t) -> bool {
1530     match get(ty).sty {
1531         ty_param(ref p) => p.space == subst::SelfSpace,
1532         _ => false
1533     }
1534 }
1535
1536 fn type_is_slice(ty:t) -> bool {
1537     match get(ty).sty {
1538         ty_rptr(_, mt) => match get(mt.ty).sty {
1539             ty_vec(_, None) | ty_str => true,
1540             _ => false,
1541         },
1542         _ => false
1543     }
1544 }
1545
1546 pub fn type_is_structural(ty: t) -> bool {
1547     match get(ty).sty {
1548       ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
1549       ty_vec(_, Some(_)) => true,
1550       _ => type_is_slice(ty) | type_is_trait(ty)
1551     }
1552 }
1553
1554 pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
1555     match get(ty).sty {
1556         ty_struct(did, _) => lookup_simd(cx, did),
1557         _ => false
1558     }
1559 }
1560
1561 pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
1562     match get(ty).sty {
1563         ty_vec(mt, Some(_)) => mt.ty,
1564         ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
1565         ty_box(t) | ty_uniq(t) => match get(t).sty {
1566             ty_vec(mt, None) => mt.ty,
1567             ty_str => mk_mach_uint(ast::TyU8),
1568             _ => cx.sess.bug("sequence_element_type called on non-sequence value"),
1569         },
1570         _ => cx.sess.bug("sequence_element_type called on non-sequence value"),
1571     }
1572 }
1573
1574 pub fn simd_type(cx: &ctxt, ty: t) -> t {
1575     match get(ty).sty {
1576         ty_struct(did, ref substs) => {
1577             let fields = lookup_struct_fields(cx, did);
1578             lookup_field_type(cx, did, fields.get(0).id, substs)
1579         }
1580         _ => fail!("simd_type called on invalid type")
1581     }
1582 }
1583
1584 pub fn simd_size(cx: &ctxt, ty: t) -> uint {
1585     match get(ty).sty {
1586         ty_struct(did, _) => {
1587             let fields = lookup_struct_fields(cx, did);
1588             fields.len()
1589         }
1590         _ => fail!("simd_size called on invalid type")
1591     }
1592 }
1593
1594 pub fn type_is_boxed(ty: t) -> bool {
1595     match get(ty).sty {
1596       ty_box(_) => true,
1597       _ => false
1598     }
1599 }
1600
1601 pub fn type_is_region_ptr(ty: t) -> bool {
1602     match get(ty).sty {
1603         ty_rptr(_, mt) => match get(mt.ty).sty {
1604             // FIXME(nrc, DST) slices weren't regarded as rptrs, so we preserve this
1605             // odd behaviour for now. (But ~[] were unique. I have no idea why).
1606             ty_vec(_, None) | ty_str | ty_trait(..) => false,
1607             _ => true
1608         },
1609         _ => false
1610     }
1611 }
1612
1613 pub fn type_is_unsafe_ptr(ty: t) -> bool {
1614     match get(ty).sty {
1615       ty_ptr(_) => return true,
1616       _ => return false
1617     }
1618 }
1619
1620 pub fn type_is_unique(ty: t) -> bool {
1621     match get(ty).sty {
1622         ty_uniq(_) => match get(ty).sty {
1623             ty_trait(..) => false,
1624             _ => true
1625         },
1626         _ => false
1627     }
1628 }
1629
1630 /*
1631  A scalar type is one that denotes an atomic datum, with no sub-components.
1632  (A ty_ptr is scalar because it represents a non-managed pointer, so its
1633  contents are abstract to rustc.)
1634 */
1635 pub fn type_is_scalar(ty: t) -> bool {
1636     match get(ty).sty {
1637       ty_nil | ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
1638       ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) |
1639       ty_bare_fn(..) | ty_ptr(_) => true,
1640       _ => false
1641     }
1642 }
1643
1644 /// Returns true if this type is a floating point type and false otherwise.
1645 pub fn type_is_floating_point(ty: t) -> bool {
1646     match get(ty).sty {
1647         ty_float(_) => true,
1648         _ => false,
1649     }
1650 }
1651
1652 pub fn type_needs_drop(cx: &ctxt, ty: t) -> bool {
1653     type_contents(cx, ty).needs_drop(cx)
1654 }
1655
1656 // Some things don't need cleanups during unwinding because the
1657 // task can free them all at once later. Currently only things
1658 // that only contain scalars and shared boxes can avoid unwind
1659 // cleanups.
1660 pub fn type_needs_unwind_cleanup(cx: &ctxt, ty: t) -> bool {
1661     match cx.needs_unwind_cleanup_cache.borrow().find(&ty) {
1662         Some(&result) => return result,
1663         None => ()
1664     }
1665
1666     let mut tycache = HashSet::new();
1667     let needs_unwind_cleanup =
1668         type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
1669     cx.needs_unwind_cleanup_cache.borrow_mut().insert(ty, needs_unwind_cleanup);
1670     return needs_unwind_cleanup;
1671 }
1672
1673 fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t,
1674                               tycache: &mut HashSet<t>,
1675                               encountered_box: bool) -> bool {
1676
1677     // Prevent infinite recursion
1678     if !tycache.insert(ty) {
1679         return false;
1680     }
1681
1682     let mut encountered_box = encountered_box;
1683     let mut needs_unwind_cleanup = false;
1684     maybe_walk_ty(ty, |ty| {
1685         let old_encountered_box = encountered_box;
1686         let result = match get(ty).sty {
1687           ty_box(_) => {
1688             encountered_box = true;
1689             true
1690           }
1691           ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1692           ty_tup(_) | ty_ptr(_) => {
1693             true
1694           }
1695           ty_enum(did, ref substs) => {
1696             for v in (*enum_variants(cx, did)).iter() {
1697                 for aty in v.args.iter() {
1698                     let t = aty.subst(cx, substs);
1699                     needs_unwind_cleanup |=
1700                         type_needs_unwind_cleanup_(cx, t, tycache,
1701                                                    encountered_box);
1702                 }
1703             }
1704             !needs_unwind_cleanup
1705           }
1706           ty_uniq(_) => {
1707             // Once we're inside a box, the annihilator will find
1708             // it and destroy it.
1709             if !encountered_box {
1710                 needs_unwind_cleanup = true;
1711                 false
1712             } else {
1713                 true
1714             }
1715           }
1716           _ => {
1717             needs_unwind_cleanup = true;
1718             false
1719           }
1720         };
1721
1722         encountered_box = old_encountered_box;
1723         result
1724     });
1725
1726     return needs_unwind_cleanup;
1727 }
1728
1729 /**
1730  * Type contents is how the type checker reasons about kinds.
1731  * They track what kinds of things are found within a type.  You can
1732  * think of them as kind of an "anti-kind".  They track the kinds of values
1733  * and thinks that are contained in types.  Having a larger contents for
1734  * a type tends to rule that type *out* from various kinds.  For example,
1735  * a type that contains a reference is not sendable.
1736  *
1737  * The reason we compute type contents and not kinds is that it is
1738  * easier for me (nmatsakis) to think about what is contained within
1739  * a type than to think about what is *not* contained within a type.
1740  */
1741 pub struct TypeContents {
1742     pub bits: u64
1743 }
1744
1745 macro_rules! def_type_content_sets(
1746     (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
1747         mod $mname {
1748             use middle::ty::TypeContents;
1749             $(pub static $name: TypeContents = TypeContents { bits: $bits };)+
1750         }
1751     }
1752 )
1753
1754 def_type_content_sets!(
1755     mod TC {
1756         None                                = 0b0000_0000__0000_0000__0000,
1757
1758         // Things that are interior to the value (first nibble):
1759         InteriorUnsized                     = 0b0000_0000__0000_0000__0001,
1760         InteriorUnsafe                      = 0b0000_0000__0000_0000__0010,
1761         // InteriorAll                         = 0b00000000__00000000__1111,
1762
1763         // Things that are owned by the value (second and third nibbles):
1764         OwnsOwned                           = 0b0000_0000__0000_0001__0000,
1765         OwnsDtor                            = 0b0000_0000__0000_0010__0000,
1766         OwnsManaged /* see [1] below */     = 0b0000_0000__0000_0100__0000,
1767         OwnsAffine                          = 0b0000_0000__0000_1000__0000,
1768         OwnsAll                             = 0b0000_0000__1111_1111__0000,
1769
1770         // Things that are reachable by the value in any way (fourth nibble):
1771         ReachesNonsendAnnot                 = 0b0000_0001__0000_0000__0000,
1772         ReachesBorrowed                     = 0b0000_0010__0000_0000__0000,
1773         // ReachesManaged /* see [1] below */  = 0b0000_0100__0000_0000__0000,
1774         ReachesMutable                      = 0b0000_1000__0000_0000__0000,
1775         ReachesNoShare                      = 0b0001_0000__0000_0000__0000,
1776         ReachesAll                          = 0b0001_1111__0000_0000__0000,
1777
1778         // Things that cause values to *move* rather than *copy*
1779         Moves                               = 0b0000_0000__0000_1011__0000,
1780
1781         // Things that mean drop glue is necessary
1782         NeedsDrop                           = 0b0000_0000__0000_0111__0000,
1783
1784         // Things that prevent values from being sent
1785         //
1786         // Note: For checking whether something is sendable, it'd
1787         //       be sufficient to have ReachesManaged. However, we include
1788         //       both ReachesManaged and OwnsManaged so that when
1789         //       a parameter has a bound T:Send, we are able to deduce
1790         //       that it neither reaches nor owns a managed pointer.
1791         Nonsendable                         = 0b0000_0111__0000_0100__0000,
1792
1793         // Things that prevent values from being considered 'static
1794         Nonstatic                           = 0b0000_0010__0000_0000__0000,
1795
1796         // Things that prevent values from being considered sized
1797         Nonsized                            = 0b0000_0000__0000_0000__0001,
1798
1799         // Things that prevent values from being shared
1800         Nonsharable                         = 0b0001_0000__0000_0000__0000,
1801
1802         // Things that make values considered not POD (would be same
1803         // as `Moves`, but for the fact that managed data `@` is
1804         // not considered POD)
1805         Noncopy                              = 0b0000_0000__0000_1111__0000,
1806
1807         // Bits to set when a managed value is encountered
1808         //
1809         // [1] Do not set the bits TC::OwnsManaged or
1810         //     TC::ReachesManaged directly, instead reference
1811         //     TC::Managed to set them both at once.
1812         Managed                             = 0b0000_0100__0000_0100__0000,
1813
1814         // All bits
1815         All                                 = 0b1111_1111__1111_1111__1111
1816     }
1817 )
1818
1819 impl TypeContents {
1820     pub fn meets_bound(&self, cx: &ctxt, bb: BuiltinBound) -> bool {
1821         match bb {
1822             BoundStatic => self.is_static(cx),
1823             BoundSend => self.is_sendable(cx),
1824             BoundSized => self.is_sized(cx),
1825             BoundCopy => self.is_copy(cx),
1826             BoundShare => self.is_sharable(cx),
1827         }
1828     }
1829
1830     pub fn when(&self, cond: bool) -> TypeContents {
1831         if cond {*self} else {TC::None}
1832     }
1833
1834     pub fn intersects(&self, tc: TypeContents) -> bool {
1835         (self.bits & tc.bits) != 0
1836     }
1837
1838     pub fn is_static(&self, _: &ctxt) -> bool {
1839         !self.intersects(TC::Nonstatic)
1840     }
1841
1842     pub fn is_sendable(&self, _: &ctxt) -> bool {
1843         !self.intersects(TC::Nonsendable)
1844     }
1845
1846     pub fn is_sharable(&self, _: &ctxt) -> bool {
1847         !self.intersects(TC::Nonsharable)
1848     }
1849
1850     pub fn owns_managed(&self) -> bool {
1851         self.intersects(TC::OwnsManaged)
1852     }
1853
1854     pub fn owns_owned(&self) -> bool {
1855         self.intersects(TC::OwnsOwned)
1856     }
1857
1858     pub fn is_sized(&self, _: &ctxt) -> bool {
1859         !self.intersects(TC::Nonsized)
1860     }
1861
1862     pub fn is_copy(&self, _: &ctxt) -> bool {
1863         !self.intersects(TC::Noncopy)
1864     }
1865
1866     pub fn interior_unsafe(&self) -> bool {
1867         self.intersects(TC::InteriorUnsafe)
1868     }
1869
1870     pub fn interior_unsized(&self) -> bool {
1871         self.intersects(TC::InteriorUnsized)
1872     }
1873
1874     pub fn moves_by_default(&self, _: &ctxt) -> bool {
1875         self.intersects(TC::Moves)
1876     }
1877
1878     pub fn needs_drop(&self, _: &ctxt) -> bool {
1879         self.intersects(TC::NeedsDrop)
1880     }
1881
1882     pub fn owned_pointer(&self) -> TypeContents {
1883         /*!
1884          * Includes only those bits that still apply
1885          * when indirected through a `Box` pointer
1886          */
1887         TC::OwnsOwned | (
1888             *self & (TC::OwnsAll | TC::ReachesAll))
1889     }
1890
1891     pub fn reference(&self, bits: TypeContents) -> TypeContents {
1892         /*!
1893          * Includes only those bits that still apply
1894          * when indirected through a reference (`&`)
1895          */
1896         bits | (
1897             *self & TC::ReachesAll)
1898     }
1899
1900     pub fn managed_pointer(&self) -> TypeContents {
1901         /*!
1902          * Includes only those bits that still apply
1903          * when indirected through a managed pointer (`@`)
1904          */
1905         TC::Managed | (
1906             *self & TC::ReachesAll)
1907     }
1908
1909     pub fn unsafe_pointer(&self) -> TypeContents {
1910         /*!
1911          * Includes only those bits that still apply
1912          * when indirected through an unsafe pointer (`*`)
1913          */
1914         *self & TC::ReachesAll
1915     }
1916
1917     pub fn union<T>(v: &[T], f: |&T| -> TypeContents) -> TypeContents {
1918         v.iter().fold(TC::None, |tc, t| tc | f(t))
1919     }
1920
1921     pub fn has_dtor(&self) -> bool {
1922         self.intersects(TC::OwnsDtor)
1923     }
1924 }
1925
1926 impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
1927     fn bitor(&self, other: &TypeContents) -> TypeContents {
1928         TypeContents {bits: self.bits | other.bits}
1929     }
1930 }
1931
1932 impl ops::BitAnd<TypeContents,TypeContents> for TypeContents {
1933     fn bitand(&self, other: &TypeContents) -> TypeContents {
1934         TypeContents {bits: self.bits & other.bits}
1935     }
1936 }
1937
1938 impl ops::Sub<TypeContents,TypeContents> for TypeContents {
1939     fn sub(&self, other: &TypeContents) -> TypeContents {
1940         TypeContents {bits: self.bits & !other.bits}
1941     }
1942 }
1943
1944 impl fmt::Show for TypeContents {
1945     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1946         write!(f, "TypeContents({:t})", self.bits)
1947     }
1948 }
1949
1950 pub fn type_is_static(cx: &ctxt, t: ty::t) -> bool {
1951     type_contents(cx, t).is_static(cx)
1952 }
1953
1954 pub fn type_is_sendable(cx: &ctxt, t: ty::t) -> bool {
1955     type_contents(cx, t).is_sendable(cx)
1956 }
1957
1958 pub fn type_interior_is_unsafe(cx: &ctxt, t: ty::t) -> bool {
1959     type_contents(cx, t).interior_unsafe()
1960 }
1961
1962 pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
1963     let ty_id = type_id(ty);
1964
1965     match cx.tc_cache.borrow().find(&ty_id) {
1966         Some(tc) => { return *tc; }
1967         None => {}
1968     }
1969
1970     let mut cache = HashMap::new();
1971     let result = tc_ty(cx, ty, &mut cache);
1972
1973     cx.tc_cache.borrow_mut().insert(ty_id, result);
1974     return result;
1975
1976     fn tc_ty(cx: &ctxt,
1977              ty: t,
1978              cache: &mut HashMap<uint, TypeContents>) -> TypeContents
1979     {
1980         // Subtle: Note that we are *not* using cx.tc_cache here but rather a
1981         // private cache for this walk.  This is needed in the case of cyclic
1982         // types like:
1983         //
1984         //     struct List { next: Box<Option<List>>, ... }
1985         //
1986         // When computing the type contents of such a type, we wind up deeply
1987         // recursing as we go.  So when we encounter the recursive reference
1988         // to List, we temporarily use TC::None as its contents.  Later we'll
1989         // patch up the cache with the correct value, once we've computed it
1990         // (this is basically a co-inductive process, if that helps).  So in
1991         // the end we'll compute TC::OwnsOwned, in this case.
1992         //
1993         // The problem is, as we are doing the computation, we will also
1994         // compute an *intermediate* contents for, e.g., Option<List> of
1995         // TC::None.  This is ok during the computation of List itself, but if
1996         // we stored this intermediate value into cx.tc_cache, then later
1997         // requests for the contents of Option<List> would also yield TC::None
1998         // which is incorrect.  This value was computed based on the crutch
1999         // value for the type contents of list.  The correct value is
2000         // TC::OwnsOwned.  This manifested as issue #4821.
2001         let ty_id = type_id(ty);
2002         match cache.find(&ty_id) {
2003             Some(tc) => { return *tc; }
2004             None => {}
2005         }
2006         match cx.tc_cache.borrow().find(&ty_id) {    // Must check both caches!
2007             Some(tc) => { return *tc; }
2008             None => {}
2009         }
2010         cache.insert(ty_id, TC::None);
2011
2012         let result = match get(ty).sty {
2013             // Scalar and unique types are sendable, and durable
2014             ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
2015             ty_bare_fn(_) | ty::ty_char | ty_str => {
2016                 TC::None
2017             }
2018
2019             ty_closure(ref c) => {
2020                 closure_contents(cx, *c)
2021             }
2022
2023             ty_box(typ) => {
2024                 tc_ty(cx, typ, cache).managed_pointer()
2025             }
2026
2027             ty_uniq(typ) => {
2028                 match get(typ).sty {
2029                     ty_str => TC::OwnsOwned,
2030                     _ => tc_ty(cx, typ, cache).owned_pointer(),
2031                 }
2032             }
2033
2034             ty_trait(box ty::TyTrait { bounds, .. }) => {
2035                 object_contents(cx, bounds)
2036             }
2037
2038             ty_ptr(ref mt) => {
2039                 tc_ty(cx, mt.ty, cache).unsafe_pointer()
2040             }
2041
2042             ty_rptr(r, ref mt) => {
2043                 match get(mt.ty).sty {
2044                     ty_str => borrowed_contents(r, ast::MutImmutable),
2045                     _ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
2046                 }
2047             }
2048
2049             ty_vec(mt, _) => {
2050                 tc_mt(cx, mt, cache)
2051             }
2052
2053             ty_struct(did, ref substs) => {
2054                 let flds = struct_fields(cx, did, substs);
2055                 let mut res =
2056                     TypeContents::union(flds.as_slice(),
2057                                         |f| tc_mt(cx, f.mt, cache));
2058                 if ty::has_dtor(cx, did) {
2059                     res = res | TC::OwnsDtor;
2060                 }
2061                 apply_lang_items(cx, did, res)
2062             }
2063
2064             ty_tup(ref tys) => {
2065                 TypeContents::union(tys.as_slice(),
2066                                     |ty| tc_ty(cx, *ty, cache))
2067             }
2068
2069             ty_enum(did, ref substs) => {
2070                 let variants = substd_enum_variants(cx, did, substs);
2071                 let res =
2072                     TypeContents::union(variants.as_slice(), |variant| {
2073                         TypeContents::union(variant.args.as_slice(),
2074                                             |arg_ty| {
2075                             tc_ty(cx, *arg_ty, cache)
2076                         })
2077                     });
2078                 apply_lang_items(cx, did, res)
2079             }
2080
2081             ty_param(p) => {
2082                 // We only ever ask for the kind of types that are defined in
2083                 // the current crate; therefore, the only type parameters that
2084                 // could be in scope are those defined in the current crate.
2085                 // If this assertion failures, it is likely because of a
2086                 // failure in the cross-crate inlining code to translate a
2087                 // def-id.
2088                 assert_eq!(p.def_id.krate, ast::LOCAL_CRATE);
2089
2090                 let ty_param_defs = cx.ty_param_defs.borrow();
2091                 let tp_def = ty_param_defs.get(&p.def_id.node);
2092                 kind_bounds_to_contents(cx,
2093                                         tp_def.bounds.builtin_bounds,
2094                                         tp_def.bounds.trait_bounds.as_slice())
2095             }
2096
2097             ty_infer(_) => {
2098                 // This occurs during coherence, but shouldn't occur at other
2099                 // times.
2100                 TC::All
2101             }
2102
2103             ty_err => {
2104                 cx.sess.bug("asked to compute contents of error type");
2105             }
2106         };
2107
2108         cache.insert(ty_id, result);
2109         return result;
2110     }
2111
2112     fn tc_mt(cx: &ctxt,
2113              mt: mt,
2114              cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2115     {
2116         let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
2117         mc | tc_ty(cx, mt.ty, cache)
2118     }
2119
2120     fn apply_lang_items(cx: &ctxt,
2121                         did: ast::DefId,
2122                         tc: TypeContents)
2123                         -> TypeContents {
2124         if Some(did) == cx.lang_items.no_send_bound() {
2125             tc | TC::ReachesNonsendAnnot
2126         } else if Some(did) == cx.lang_items.managed_bound() {
2127             tc | TC::Managed
2128         } else if Some(did) == cx.lang_items.no_copy_bound() {
2129             tc | TC::OwnsAffine
2130         } else if Some(did) == cx.lang_items.no_share_bound() {
2131             tc | TC::ReachesNoShare
2132         } else if Some(did) == cx.lang_items.unsafe_type() {
2133             // FIXME(#13231): This shouldn't be needed after
2134             // opt-in built-in bounds are implemented.
2135             (tc | TC::InteriorUnsafe) - TC::Nonsharable
2136         } else {
2137             tc
2138         }
2139     }
2140
2141     fn borrowed_contents(region: ty::Region,
2142                          mutbl: ast::Mutability)
2143                          -> TypeContents {
2144         /*!
2145          * Type contents due to containing a reference
2146          * with the region `region` and borrow kind `bk`
2147          */
2148
2149         let b = match mutbl {
2150             ast::MutMutable => TC::ReachesMutable | TC::OwnsAffine,
2151             ast::MutImmutable => TC::None,
2152         };
2153         b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
2154     }
2155
2156     fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
2157         // Closure contents are just like trait contents, but with potentially
2158         // even more stuff.
2159         let st = object_contents(cx, cty.bounds);
2160
2161         let st = match cty.store {
2162             UniqTraitStore => {
2163                 st.owned_pointer()
2164             }
2165             RegionTraitStore(r, mutbl) => {
2166                 st.reference(borrowed_contents(r, mutbl))
2167             }
2168         };
2169
2170         // This also prohibits "@once fn" from being copied, which allows it to
2171         // be called. Neither way really makes much sense.
2172         let ot = match cty.onceness {
2173             ast::Once => TC::OwnsAffine,
2174             ast::Many => TC::None,
2175         };
2176
2177         st | ot
2178     }
2179
2180     fn object_contents(cx: &ctxt,
2181                        bounds: BuiltinBounds)
2182                        -> TypeContents {
2183         // These are the type contents of the (opaque) interior
2184         kind_bounds_to_contents(cx, bounds, [])
2185     }
2186
2187     fn kind_bounds_to_contents(cx: &ctxt,
2188                                bounds: BuiltinBounds,
2189                                traits: &[Rc<TraitRef>])
2190                                -> TypeContents {
2191         let _i = indenter();
2192         let mut tc = TC::All;
2193         each_inherited_builtin_bound(cx, bounds, traits, |bound| {
2194             tc = tc - match bound {
2195                 BoundStatic => TC::Nonstatic,
2196                 BoundSend => TC::Nonsendable,
2197                 BoundSized => TC::Nonsized,
2198                 BoundCopy => TC::Noncopy,
2199                 BoundShare => TC::Nonsharable,
2200             };
2201         });
2202         return tc;
2203
2204         // Iterates over all builtin bounds on the type parameter def, including
2205         // those inherited from traits with builtin-kind-supertraits.
2206         fn each_inherited_builtin_bound(cx: &ctxt,
2207                                         bounds: BuiltinBounds,
2208                                         traits: &[Rc<TraitRef>],
2209                                         f: |BuiltinBound|) {
2210             for bound in bounds.iter() {
2211                 f(bound);
2212             }
2213
2214             each_bound_trait_and_supertraits(cx, traits, |trait_ref| {
2215                 let trait_def = lookup_trait_def(cx, trait_ref.def_id);
2216                 for bound in trait_def.bounds.iter() {
2217                     f(bound);
2218                 }
2219                 true
2220             });
2221         }
2222     }
2223 }
2224
2225 pub fn type_moves_by_default(cx: &ctxt, ty: t) -> bool {
2226     type_contents(cx, ty).moves_by_default(cx)
2227 }
2228
2229 // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2230 pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
2231     fn type_requires(cx: &ctxt, seen: &mut Vec<DefId>,
2232                      r_ty: t, ty: t) -> bool {
2233         debug!("type_requires({}, {})?",
2234                ::util::ppaux::ty_to_str(cx, r_ty),
2235                ::util::ppaux::ty_to_str(cx, ty));
2236
2237         let r = {
2238             get(r_ty).sty == get(ty).sty ||
2239                 subtypes_require(cx, seen, r_ty, ty)
2240         };
2241
2242         debug!("type_requires({}, {})? {}",
2243                ::util::ppaux::ty_to_str(cx, r_ty),
2244                ::util::ppaux::ty_to_str(cx, ty),
2245                r);
2246         return r;
2247     }
2248
2249     fn subtypes_require(cx: &ctxt, seen: &mut Vec<DefId>,
2250                         r_ty: t, ty: t) -> bool {
2251         debug!("subtypes_require({}, {})?",
2252                ::util::ppaux::ty_to_str(cx, r_ty),
2253                ::util::ppaux::ty_to_str(cx, ty));
2254
2255         let r = match get(ty).sty {
2256             // fixed length vectors need special treatment compared to
2257             // normal vectors, since they don't necessarily have the
2258             // possibility to have length zero.
2259             ty_vec(_, Some(0)) => false, // don't need no contents
2260             ty_vec(mt, Some(_)) => type_requires(cx, seen, r_ty, mt.ty),
2261
2262             ty_nil |
2263             ty_bot |
2264             ty_bool |
2265             ty_char |
2266             ty_int(_) |
2267             ty_uint(_) |
2268             ty_float(_) |
2269             ty_str |
2270             ty_bare_fn(_) |
2271             ty_closure(_) |
2272             ty_infer(_) |
2273             ty_err |
2274             ty_param(_) |
2275             ty_vec(_, None) => {
2276                 false
2277             }
2278             ty_box(typ) | ty_uniq(typ) => {
2279                 type_requires(cx, seen, r_ty, typ)
2280             }
2281             ty_rptr(_, ref mt) => {
2282                 type_requires(cx, seen, r_ty, mt.ty)
2283             }
2284
2285             ty_ptr(..) => {
2286                 false           // unsafe ptrs can always be NULL
2287             }
2288
2289             ty_trait(..) => {
2290                 false
2291             }
2292
2293             ty_struct(ref did, _) if seen.contains(did) => {
2294                 false
2295             }
2296
2297             ty_struct(did, ref substs) => {
2298                 seen.push(did);
2299                 let fields = struct_fields(cx, did, substs);
2300                 let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
2301                 seen.pop().unwrap();
2302                 r
2303             }
2304
2305             ty_tup(ref ts) => {
2306                 ts.iter().any(|t| type_requires(cx, seen, r_ty, *t))
2307             }
2308
2309             ty_enum(ref did, _) if seen.contains(did) => {
2310                 false
2311             }
2312
2313             ty_enum(did, ref substs) => {
2314                 seen.push(did);
2315                 let vs = enum_variants(cx, did);
2316                 let r = !vs.is_empty() && vs.iter().all(|variant| {
2317                     variant.args.iter().any(|aty| {
2318                         let sty = aty.subst(cx, substs);
2319                         type_requires(cx, seen, r_ty, sty)
2320                     })
2321                 });
2322                 seen.pop().unwrap();
2323                 r
2324             }
2325         };
2326
2327         debug!("subtypes_require({}, {})? {}",
2328                ::util::ppaux::ty_to_str(cx, r_ty),
2329                ::util::ppaux::ty_to_str(cx, ty),
2330                r);
2331
2332         return r;
2333     }
2334
2335     let mut seen = Vec::new();
2336     !subtypes_require(cx, &mut seen, r_ty, r_ty)
2337 }
2338
2339 /// Describes whether a type is representable. For types that are not
2340 /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
2341 /// distinguish between types that are recursive with themselves and types that
2342 /// contain a different recursive type. These cases can therefore be treated
2343 /// differently when reporting errors.
2344 #[deriving(PartialEq)]
2345 pub enum Representability {
2346     Representable,
2347     SelfRecursive,
2348     ContainsRecursive,
2349 }
2350
2351 /// Check whether a type is representable. This means it cannot contain unboxed
2352 /// structural recursion. This check is needed for structs and enums.
2353 pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability {
2354
2355     // Iterate until something non-representable is found
2356     fn find_nonrepresentable<It: Iterator<t>>(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
2357                                               mut iter: It) -> Representability {
2358         for ty in iter {
2359             let r = type_structurally_recursive(cx, sp, seen, ty);
2360             if r != Representable {
2361                  return r
2362             }
2363         }
2364         Representable
2365     }
2366
2367     // Does the type `ty` directly (without indirection through a pointer)
2368     // contain any types on stack `seen`?
2369     fn type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
2370                                    ty: t) -> Representability {
2371         debug!("type_structurally_recursive: {}",
2372                ::util::ppaux::ty_to_str(cx, ty));
2373
2374         // Compare current type to previously seen types
2375         match get(ty).sty {
2376             ty_struct(did, _) |
2377             ty_enum(did, _) => {
2378                 for (i, &seen_did) in seen.iter().enumerate() {
2379                     if did == seen_did {
2380                         return if i == 0 { SelfRecursive }
2381                                else { ContainsRecursive }
2382                     }
2383                 }
2384             }
2385             _ => (),
2386         }
2387
2388         // Check inner types
2389         match get(ty).sty {
2390             // Tuples
2391             ty_tup(ref ts) => {
2392                 find_nonrepresentable(cx, sp, seen, ts.iter().map(|t| *t))
2393             }
2394             // Fixed-length vectors.
2395             // FIXME(#11924) Behavior undecided for zero-length vectors.
2396             ty_vec(mt, Some(_)) => {
2397                 type_structurally_recursive(cx, sp, seen, mt.ty)
2398             }
2399
2400             // Push struct and enum def-ids onto `seen` before recursing.
2401             ty_struct(did, ref substs) => {
2402                 seen.push(did);
2403                 let fields = struct_fields(cx, did, substs);
2404                 let r = find_nonrepresentable(cx, sp, seen,
2405                                               fields.iter().map(|f| f.mt.ty));
2406                 seen.pop();
2407                 r
2408             }
2409             ty_enum(did, ref substs) => {
2410                 seen.push(did);
2411                 let vs = enum_variants(cx, did);
2412
2413                 let mut r = Representable;
2414                 for variant in vs.iter() {
2415                     let iter = variant.args.iter().map(|aty| {
2416                         aty.subst_spanned(cx, substs, Some(sp))
2417                     });
2418                     r = find_nonrepresentable(cx, sp, seen, iter);
2419
2420                     if r != Representable { break }
2421                 }
2422
2423                 seen.pop();
2424                 r
2425             }
2426
2427             _ => Representable,
2428         }
2429     }
2430
2431     debug!("is_type_representable: {}",
2432            ::util::ppaux::ty_to_str(cx, ty));
2433
2434     // To avoid a stack overflow when checking an enum variant or struct that
2435     // contains a different, structurally recursive type, maintain a stack
2436     // of seen types and check recursion for each of them (issues #3008, #3779).
2437     let mut seen: Vec<DefId> = Vec::new();
2438     type_structurally_recursive(cx, sp, &mut seen, ty)
2439 }
2440
2441 pub fn type_is_trait(ty: t) -> bool {
2442     match get(ty).sty {
2443         ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) => match get(ty).sty {
2444             ty_trait(..) => true,
2445             _ => false
2446         },
2447         ty_trait(..) => true,
2448         _ => false
2449     }
2450 }
2451
2452 pub fn type_is_integral(ty: t) -> bool {
2453     match get(ty).sty {
2454       ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
2455       _ => false
2456     }
2457 }
2458
2459 pub fn type_is_uint(ty: t) -> bool {
2460     match get(ty).sty {
2461       ty_infer(IntVar(_)) | ty_uint(ast::TyU) => true,
2462       _ => false
2463     }
2464 }
2465
2466 pub fn type_is_char(ty: t) -> bool {
2467     match get(ty).sty {
2468         ty_char => true,
2469         _ => false
2470     }
2471 }
2472
2473 pub fn type_is_bare_fn(ty: t) -> bool {
2474     match get(ty).sty {
2475         ty_bare_fn(..) => true,
2476         _ => false
2477     }
2478 }
2479
2480 pub fn type_is_fp(ty: t) -> bool {
2481     match get(ty).sty {
2482       ty_infer(FloatVar(_)) | ty_float(_) => true,
2483       _ => false
2484     }
2485 }
2486
2487 pub fn type_is_numeric(ty: t) -> bool {
2488     return type_is_integral(ty) || type_is_fp(ty);
2489 }
2490
2491 pub fn type_is_signed(ty: t) -> bool {
2492     match get(ty).sty {
2493       ty_int(_) => true,
2494       _ => false
2495     }
2496 }
2497
2498 pub fn type_is_machine(ty: t) -> bool {
2499     match get(ty).sty {
2500         ty_int(ast::TyI) | ty_uint(ast::TyU) => false,
2501         ty_int(..) | ty_uint(..) | ty_float(..) => true,
2502         _ => false
2503     }
2504 }
2505
2506 // Is the type's representation size known at compile time?
2507 #[allow(dead_code)] // leaving in for DST
2508 pub fn type_is_sized(cx: &ctxt, ty: ty::t) -> bool {
2509     type_contents(cx, ty).is_sized(cx)
2510 }
2511
2512 // Whether a type is enum like, that is an enum type with only nullary
2513 // constructors
2514 pub fn type_is_c_like_enum(cx: &ctxt, ty: t) -> bool {
2515     match get(ty).sty {
2516         ty_enum(did, _) => {
2517             let variants = enum_variants(cx, did);
2518             if variants.len() == 0 {
2519                 false
2520             } else {
2521                 variants.iter().all(|v| v.args.len() == 0)
2522             }
2523         }
2524         _ => false
2525     }
2526 }
2527
2528 // Returns the type and mutability of *t.
2529 //
2530 // The parameter `explicit` indicates if this is an *explicit* dereference.
2531 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
2532 pub fn deref(t: t, explicit: bool) -> Option<mt> {
2533     match get(t).sty {
2534         ty_box(typ) | ty_uniq(typ) => match get(typ).sty {
2535             // Don't deref ~[] etc., might need to generalise this to all DST.
2536             ty_vec(_, None) | ty_str | ty_trait(..) => None,
2537             _ => Some(mt {
2538                 ty: typ,
2539                 mutbl: ast::MutImmutable,
2540             }),
2541         },
2542         ty_rptr(_, mt) => match get(mt.ty).sty {
2543             // Don't deref &[], might need to generalise this to all DST.
2544             ty_vec(_, None) | ty_str | ty_trait(..) => None,
2545             _ => Some(mt),
2546         },
2547         ty_ptr(mt) if explicit => Some(mt),
2548         _ => None
2549     }
2550 }
2551
2552 // Returns the type of t[i]
2553 pub fn index(t: t) -> Option<mt> {
2554     match get(t).sty {
2555         ty_vec(mt, Some(_)) => Some(mt),
2556         ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
2557         ty_box(t) | ty_uniq(t) => match get(t).sty {
2558             ty_vec(mt, None) => Some(mt),
2559             ty_str => Some(mt {ty: mk_u8(), mutbl: ast::MutImmutable}),
2560             _ => None,
2561         },
2562         _ => None
2563     }
2564 }
2565
2566 pub fn node_id_to_trait_ref(cx: &ctxt, id: ast::NodeId) -> Rc<ty::TraitRef> {
2567     match cx.trait_refs.borrow().find(&id) {
2568         Some(t) => t.clone(),
2569         None => cx.sess.bug(
2570             format!("node_id_to_trait_ref: no trait ref for node `{}`",
2571                     cx.map.node_to_str(id)).as_slice())
2572     }
2573 }
2574
2575 pub fn try_node_id_to_type(cx: &ctxt, id: ast::NodeId) -> Option<t> {
2576     cx.node_types.borrow().find_copy(&(id as uint))
2577 }
2578
2579 pub fn node_id_to_type(cx: &ctxt, id: ast::NodeId) -> t {
2580     match try_node_id_to_type(cx, id) {
2581        Some(t) => t,
2582        None => cx.sess.bug(
2583            format!("node_id_to_type: no type for node `{}`",
2584                    cx.map.node_to_str(id)).as_slice())
2585     }
2586 }
2587
2588 pub fn node_id_to_type_opt(cx: &ctxt, id: ast::NodeId) -> Option<t> {
2589     match cx.node_types.borrow().find(&(id as uint)) {
2590        Some(&t) => Some(t),
2591        None => None
2592     }
2593 }
2594
2595 pub fn node_id_item_substs(cx: &ctxt, id: ast::NodeId) -> ItemSubsts {
2596     match cx.item_substs.borrow().find(&id) {
2597       None => ItemSubsts::empty(),
2598       Some(ts) => ts.clone(),
2599     }
2600 }
2601
2602 pub fn fn_is_variadic(fty: t) -> bool {
2603     match get(fty).sty {
2604         ty_bare_fn(ref f) => f.sig.variadic,
2605         ty_closure(ref f) => f.sig.variadic,
2606         ref s => {
2607             fail!("fn_is_variadic() called on non-fn type: {:?}", s)
2608         }
2609     }
2610 }
2611
2612 pub fn ty_fn_sig(fty: t) -> FnSig {
2613     match get(fty).sty {
2614         ty_bare_fn(ref f) => f.sig.clone(),
2615         ty_closure(ref f) => f.sig.clone(),
2616         ref s => {
2617             fail!("ty_fn_sig() called on non-fn type: {:?}", s)
2618         }
2619     }
2620 }
2621
2622 // Type accessors for substructures of types
2623 pub fn ty_fn_args(fty: t) -> Vec<t> {
2624     match get(fty).sty {
2625         ty_bare_fn(ref f) => f.sig.inputs.clone(),
2626         ty_closure(ref f) => f.sig.inputs.clone(),
2627         ref s => {
2628             fail!("ty_fn_args() called on non-fn type: {:?}", s)
2629         }
2630     }
2631 }
2632
2633 pub fn ty_closure_store(fty: t) -> TraitStore {
2634     match get(fty).sty {
2635         ty_closure(ref f) => f.store,
2636         ref s => {
2637             fail!("ty_closure_store() called on non-closure type: {:?}", s)
2638         }
2639     }
2640 }
2641
2642 pub fn ty_fn_ret(fty: t) -> t {
2643     match get(fty).sty {
2644         ty_bare_fn(ref f) => f.sig.output,
2645         ty_closure(ref f) => f.sig.output,
2646         ref s => {
2647             fail!("ty_fn_ret() called on non-fn type: {:?}", s)
2648         }
2649     }
2650 }
2651
2652 pub fn is_fn_ty(fty: t) -> bool {
2653     match get(fty).sty {
2654         ty_bare_fn(_) => true,
2655         ty_closure(_) => true,
2656         _ => false
2657     }
2658 }
2659
2660 pub fn ty_region(tcx: &ctxt,
2661                  span: Span,
2662                  ty: t) -> Region {
2663     match get(ty).sty {
2664         ty_rptr(r, _) => r,
2665         ref s => {
2666             tcx.sess.span_bug(
2667                 span,
2668                 format!("ty_region() invoked on in appropriate ty: {:?}",
2669                         s).as_slice());
2670         }
2671     }
2672 }
2673
2674 pub fn free_region_from_def(free_id: ast::NodeId, def: &RegionParameterDef)
2675     -> ty::Region
2676 {
2677     ty::ReFree(ty::FreeRegion { scope_id: free_id,
2678                                 bound_region: ty::BrNamed(def.def_id,
2679                                                           def.name) })
2680 }
2681
2682 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
2683 // doesn't provide type parameter substitutions.
2684 pub fn pat_ty(cx: &ctxt, pat: &ast::Pat) -> t {
2685     return node_id_to_type(cx, pat.id);
2686 }
2687
2688
2689 // Returns the type of an expression as a monotype.
2690 //
2691 // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
2692 // some cases, we insert `AutoAdjustment` annotations such as auto-deref or
2693 // auto-ref.  The type returned by this function does not consider such
2694 // adjustments.  See `expr_ty_adjusted()` instead.
2695 //
2696 // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
2697 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
2698 // instead of "fn(t) -> T with T = int".
2699 pub fn expr_ty(cx: &ctxt, expr: &ast::Expr) -> t {
2700     return node_id_to_type(cx, expr.id);
2701 }
2702
2703 pub fn expr_ty_opt(cx: &ctxt, expr: &ast::Expr) -> Option<t> {
2704     return node_id_to_type_opt(cx, expr.id);
2705 }
2706
2707 pub fn expr_ty_adjusted(cx: &ctxt, expr: &ast::Expr) -> t {
2708     /*!
2709      *
2710      * Returns the type of `expr`, considering any `AutoAdjustment`
2711      * entry recorded for that expression.
2712      *
2713      * It would almost certainly be better to store the adjusted ty in with
2714      * the `AutoAdjustment`, but I opted not to do this because it would
2715      * require serializing and deserializing the type and, although that's not
2716      * hard to do, I just hate that code so much I didn't want to touch it
2717      * unless it was to fix it properly, which seemed a distraction from the
2718      * task at hand! -nmatsakis
2719      */
2720
2721     adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr),
2722               cx.adjustments.borrow().find(&expr.id),
2723               |method_call| cx.method_map.borrow().find(&method_call).map(|method| method.ty))
2724 }
2725
2726 pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
2727     match cx.map.find(id) {
2728         Some(ast_map::NodeExpr(e)) => {
2729             e.span
2730         }
2731         Some(f) => {
2732             cx.sess.bug(format!("Node id {} is not an expr: {:?}",
2733                                 id,
2734                                 f).as_slice());
2735         }
2736         None => {
2737             cx.sess.bug(format!("Node id {} is not present \
2738                                 in the node map", id).as_slice());
2739         }
2740     }
2741 }
2742
2743 pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
2744     match cx.map.find(id) {
2745         Some(ast_map::NodeLocal(pat)) => {
2746             match pat.node {
2747                 ast::PatIdent(_, ref path, _) => {
2748                     token::get_ident(ast_util::path_to_ident(path))
2749                 }
2750                 _ => {
2751                     cx.sess.bug(
2752                         format!("Variable id {} maps to {:?}, not local",
2753                                 id,
2754                                 pat).as_slice());
2755                 }
2756             }
2757         }
2758         r => {
2759             cx.sess.bug(format!("Variable id {} maps to {:?}, not local",
2760                                 id,
2761                                 r).as_slice());
2762         }
2763     }
2764 }
2765
2766 pub fn adjust_ty(cx: &ctxt,
2767                  span: Span,
2768                  expr_id: ast::NodeId,
2769                  unadjusted_ty: ty::t,
2770                  adjustment: Option<&AutoAdjustment>,
2771                  method_type: |typeck::MethodCall| -> Option<ty::t>)
2772                  -> ty::t {
2773     /*! See `expr_ty_adjusted` */
2774
2775     return match adjustment {
2776         Some(adjustment) => {
2777             match *adjustment {
2778                 AutoAddEnv(store) => {
2779                     match ty::get(unadjusted_ty).sty {
2780                         ty::ty_bare_fn(ref b) => {
2781                             ty::mk_closure(
2782                                 cx,
2783                                 ty::ClosureTy {fn_style: b.fn_style,
2784                                                onceness: ast::Many,
2785                                                store: store,
2786                                                bounds: ty::all_builtin_bounds(),
2787                                                sig: b.sig.clone()})
2788                         }
2789                         ref b => {
2790                             cx.sess.bug(
2791                                 format!("add_env adjustment on non-bare-fn: \
2792                                          {:?}",
2793                                         b).as_slice());
2794                         }
2795                     }
2796                 }
2797
2798                 AutoDerefRef(ref adj) => {
2799                     let mut adjusted_ty = unadjusted_ty;
2800
2801                     if !ty::type_is_error(adjusted_ty) {
2802                         for i in range(0, adj.autoderefs) {
2803                             let method_call = typeck::MethodCall::autoderef(expr_id, i);
2804                             match method_type(method_call) {
2805                                 Some(method_ty) => {
2806                                     adjusted_ty = ty_fn_ret(method_ty);
2807                                 }
2808                                 None => {}
2809                             }
2810                             match deref(adjusted_ty, true) {
2811                                 Some(mt) => { adjusted_ty = mt.ty; }
2812                                 None => {
2813                                     cx.sess.span_bug(
2814                                         span,
2815                                         format!("the {}th autoderef failed: \
2816                                                 {}",
2817                                                 i,
2818                                                 ty_to_str(cx, adjusted_ty))
2819                                                           .as_slice());
2820                                 }
2821                             }
2822                         }
2823                     }
2824
2825                     match adj.autoref {
2826                         None => adjusted_ty,
2827                         Some(ref autoref) => {
2828                             match *autoref {
2829                                 AutoPtr(r, m) => {
2830                                     mk_rptr(cx, r, mt {
2831                                         ty: adjusted_ty,
2832                                         mutbl: m
2833                                     })
2834                                 }
2835
2836                                 AutoBorrowVec(r, m) => {
2837                                     borrow_vec(cx, span, r, m, adjusted_ty)
2838                                 }
2839
2840                                 AutoBorrowVecRef(r, m) => {
2841                                     adjusted_ty = borrow_vec(cx,
2842                                                              span,
2843                                                              r,
2844                                                              m,
2845                                                              adjusted_ty);
2846                                     mk_rptr(cx, r, mt {
2847                                         ty: adjusted_ty,
2848                                         mutbl: ast::MutImmutable
2849                                     })
2850                                 }
2851
2852                                 AutoUnsafe(m) => {
2853                                     mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
2854                                 }
2855
2856                                 AutoBorrowObj(r, m) => {
2857                                     borrow_obj(cx, span, r, m, adjusted_ty)
2858                                 }
2859                             }
2860                         }
2861                     }
2862                 }
2863
2864                 AutoObject(store, bounds, def_id, ref substs) => {
2865
2866                     let tr = mk_trait(cx, def_id, substs.clone(), bounds);
2867                     match store {
2868                         UniqTraitStore => {
2869                             mk_uniq(cx, tr)
2870                         }
2871                         RegionTraitStore(r, m) => {
2872                             mk_rptr(cx, r, mt {
2873                                 ty: tr,
2874                                 mutbl: m
2875                             })
2876                         }
2877                     }
2878                 }
2879             }
2880         }
2881         None => unadjusted_ty
2882     };
2883
2884     fn borrow_vec(cx: &ctxt,
2885                   span: Span,
2886                   r: Region,
2887                   m: ast::Mutability,
2888                   ty: ty::t) -> ty::t {
2889         match get(ty).sty {
2890             ty_uniq(t) | ty_ptr(mt{ty: t, ..}) |
2891             ty_rptr(_, mt{ty: t, ..}) => match get(t).sty {
2892                 ty::ty_vec(mt, None) => ty::mk_slice(cx, r, ty::mt {ty: mt.ty, mutbl: m}),
2893                 ty::ty_str => ty::mk_str_slice(cx, r, m),
2894                 _ => {
2895                     cx.sess.span_bug(
2896                         span,
2897                         format!("borrow-vec associated with bad sty: {:?}",
2898                                 get(ty).sty).as_slice());
2899                 }
2900             },
2901             ty_vec(mt, Some(_)) => ty::mk_slice(cx, r, ty::mt {ty: mt.ty, mutbl: m}),
2902
2903             ref s => {
2904                 cx.sess.span_bug(
2905                     span,
2906                     format!("borrow-vec associated with bad sty: {:?}",
2907                             s).as_slice());
2908             }
2909         }
2910     }
2911
2912     fn borrow_obj(cx: &ctxt, span: Span, r: Region,
2913                   m: ast::Mutability, ty: ty::t) -> ty::t {
2914         match get(ty).sty {
2915             ty_uniq(t) | ty_rptr(_, mt{ty: t, ..}) => match get(t).sty {
2916                 ty_trait(box ty::TyTrait {def_id, ref substs, bounds, .. }) => {
2917                     mk_rptr(cx, r, mt {
2918                         ty: ty::mk_trait(cx, def_id, substs.clone(), bounds),
2919                         mutbl: m
2920                     })
2921                 }
2922                 _ => {
2923                     cx.sess.span_bug(
2924                         span,
2925                         format!("borrow-trait-obj associated with bad sty: {:?}",
2926                                 get(ty).sty).as_slice());
2927                 }
2928             },
2929             ref s => {
2930                 cx.sess.span_bug(
2931                     span,
2932                     format!("borrow-trait-obj associated with bad sty: {:?}",
2933                             s).as_slice());
2934             }
2935         }
2936     }
2937 }
2938
2939 impl AutoRef {
2940     pub fn map_region(&self, f: |Region| -> Region) -> AutoRef {
2941         match *self {
2942             ty::AutoPtr(r, m) => ty::AutoPtr(f(r), m),
2943             ty::AutoBorrowVec(r, m) => ty::AutoBorrowVec(f(r), m),
2944             ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(f(r), m),
2945             ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
2946             ty::AutoBorrowObj(r, m) => ty::AutoBorrowObj(f(r), m),
2947         }
2948     }
2949 }
2950
2951 pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
2952                                    -> VecPerParamSpace<TypeParameterDef> {
2953     match origin {
2954         typeck::MethodStatic(did) => {
2955             ty::lookup_item_type(tcx, did).generics.types.clone()
2956         }
2957         typeck::MethodParam(typeck::MethodParam{trait_id: trt_id,
2958                                                 method_num: n_mth, ..}) |
2959         typeck::MethodObject(typeck::MethodObject{trait_id: trt_id,
2960                                                   method_num: n_mth, ..}) => {
2961             ty::trait_method(tcx, trt_id, n_mth).generics.types.clone()
2962         }
2963     }
2964 }
2965
2966 pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
2967     match tcx.def_map.borrow().find(&expr.id) {
2968         Some(&def) => def,
2969         None => {
2970             tcx.sess.span_bug(expr.span, format!(
2971                 "no def-map entry for expr {:?}", expr.id).as_slice());
2972         }
2973     }
2974 }
2975
2976 pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
2977     match expr_kind(tcx, e) {
2978         LvalueExpr => true,
2979         RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
2980     }
2981 }
2982
2983 /// We categorize expressions into three kinds.  The distinction between
2984 /// lvalue/rvalue is fundamental to the language.  The distinction between the
2985 /// two kinds of rvalues is an artifact of trans which reflects how we will
2986 /// generate code for that kind of expression.  See trans/expr.rs for more
2987 /// information.
2988 pub enum ExprKind {
2989     LvalueExpr,
2990     RvalueDpsExpr,
2991     RvalueDatumExpr,
2992     RvalueStmtExpr
2993 }
2994
2995 pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
2996     if tcx.method_map.borrow().contains_key(&typeck::MethodCall::expr(expr.id)) {
2997         // Overloaded operations are generally calls, and hence they are
2998         // generated via DPS, but there are two exceptions:
2999         return match expr.node {
3000             // `a += b` has a unit result.
3001             ast::ExprAssignOp(..) => RvalueStmtExpr,
3002
3003             // the deref method invoked for `*a` always yields an `&T`
3004             ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
3005
3006             // in the general case, result could be any type, use DPS
3007             _ => RvalueDpsExpr
3008         };
3009     }
3010
3011     match expr.node {
3012         ast::ExprPath(..) => {
3013             match resolve_expr(tcx, expr) {
3014                 def::DefVariant(tid, vid, _) => {
3015                     let variant_info = enum_variant_with_id(tcx, tid, vid);
3016                     if variant_info.args.len() > 0u {
3017                         // N-ary variant.
3018                         RvalueDatumExpr
3019                     } else {
3020                         // Nullary variant.
3021                         RvalueDpsExpr
3022                     }
3023                 }
3024
3025                 def::DefStruct(_) => {
3026                     match get(expr_ty(tcx, expr)).sty {
3027                         ty_bare_fn(..) => RvalueDatumExpr,
3028                         _ => RvalueDpsExpr
3029                     }
3030                 }
3031
3032                 // Fn pointers are just scalar values.
3033                 def::DefFn(..) | def::DefStaticMethod(..) => RvalueDatumExpr,
3034
3035                 // Note: there is actually a good case to be made that
3036                 // DefArg's, particularly those of immediate type, ought to
3037                 // considered rvalues.
3038                 def::DefStatic(..) |
3039                 def::DefBinding(..) |
3040                 def::DefUpvar(..) |
3041                 def::DefArg(..) |
3042                 def::DefLocal(..) => LvalueExpr,
3043
3044                 def => {
3045                     tcx.sess.span_bug(
3046                         expr.span,
3047                         format!("uncategorized def for expr {:?}: {:?}",
3048                                 expr.id,
3049                                 def).as_slice());
3050                 }
3051             }
3052         }
3053
3054         ast::ExprUnary(ast::UnDeref, _) |
3055         ast::ExprField(..) |
3056         ast::ExprIndex(..) => {
3057             LvalueExpr
3058         }
3059
3060         ast::ExprCall(..) |
3061         ast::ExprMethodCall(..) |
3062         ast::ExprStruct(..) |
3063         ast::ExprTup(..) |
3064         ast::ExprIf(..) |
3065         ast::ExprMatch(..) |
3066         ast::ExprFnBlock(..) |
3067         ast::ExprProc(..) |
3068         ast::ExprBlock(..) |
3069         ast::ExprRepeat(..) |
3070         ast::ExprVstore(_, ast::ExprVstoreSlice) |
3071         ast::ExprVstore(_, ast::ExprVstoreMutSlice) |
3072         ast::ExprVec(..) => {
3073             RvalueDpsExpr
3074         }
3075
3076         ast::ExprLit(lit) if lit_is_str(lit) => {
3077             RvalueDpsExpr
3078         }
3079
3080         ast::ExprCast(..) => {
3081             match tcx.node_types.borrow().find(&(expr.id as uint)) {
3082                 Some(&t) => {
3083                     if type_is_trait(t) {
3084                         RvalueDpsExpr
3085                     } else {
3086                         RvalueDatumExpr
3087                     }
3088                 }
3089                 None => {
3090                     // Technically, it should not happen that the expr is not
3091                     // present within the table.  However, it DOES happen
3092                     // during type check, because the final types from the
3093                     // expressions are not yet recorded in the tcx.  At that
3094                     // time, though, we are only interested in knowing lvalue
3095                     // vs rvalue.  It would be better to base this decision on
3096                     // the AST type in cast node---but (at the time of this
3097                     // writing) it's not easy to distinguish casts to traits
3098                     // from other casts based on the AST.  This should be
3099                     // easier in the future, when casts to traits
3100                     // would like @Foo, Box<Foo>, or &Foo.
3101                     RvalueDatumExpr
3102                 }
3103             }
3104         }
3105
3106         ast::ExprBreak(..) |
3107         ast::ExprAgain(..) |
3108         ast::ExprRet(..) |
3109         ast::ExprWhile(..) |
3110         ast::ExprLoop(..) |
3111         ast::ExprAssign(..) |
3112         ast::ExprInlineAsm(..) |
3113         ast::ExprAssignOp(..) => {
3114             RvalueStmtExpr
3115         }
3116
3117         ast::ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
3118
3119         ast::ExprLit(_) | // Note: LitStr is carved out above
3120         ast::ExprUnary(..) |
3121         ast::ExprAddrOf(..) |
3122         ast::ExprBinary(..) |
3123         ast::ExprVstore(_, ast::ExprVstoreUniq) => {
3124             RvalueDatumExpr
3125         }
3126
3127         ast::ExprBox(place, _) => {
3128             // Special case `Box<T>`/`Gc<T>` for now:
3129             let definition = match tcx.def_map.borrow().find(&place.id) {
3130                 Some(&def) => def,
3131                 None => fail!("no def for place"),
3132             };
3133             let def_id = definition.def_id();
3134             if tcx.lang_items.exchange_heap() == Some(def_id) ||
3135                tcx.lang_items.managed_heap() == Some(def_id) {
3136                 RvalueDatumExpr
3137             } else {
3138                 RvalueDpsExpr
3139             }
3140         }
3141
3142         ast::ExprParen(ref e) => expr_kind(tcx, &**e),
3143
3144         ast::ExprMac(..) => {
3145             tcx.sess.span_bug(
3146                 expr.span,
3147                 "macro expression remains after expansion");
3148         }
3149     }
3150 }
3151
3152 pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId {
3153     match s.node {
3154       ast::StmtDecl(_, id) | StmtExpr(_, id) | StmtSemi(_, id) => {
3155         return id;
3156       }
3157       ast::StmtMac(..) => fail!("unexpanded macro in trans")
3158     }
3159 }
3160
3161 pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
3162                      -> uint {
3163     let mut i = 0u;
3164     for f in fields.iter() { if f.ident.name == name { return i; } i += 1u; }
3165     tcx.sess.bug(format!(
3166         "no field named `{}` found in the list of fields `{:?}`",
3167         token::get_name(name),
3168         fields.iter()
3169               .map(|f| token::get_ident(f.ident).get().to_string())
3170               .collect::<Vec<String>>()).as_slice());
3171 }
3172
3173 pub fn method_idx(id: ast::Ident, meths: &[Rc<Method>]) -> Option<uint> {
3174     meths.iter().position(|m| m.ident == id)
3175 }
3176
3177 /// Returns a vector containing the indices of all type parameters that appear
3178 /// in `ty`.  The vector may contain duplicates.  Probably should be converted
3179 /// to a bitset or some other representation.
3180 pub fn param_tys_in_type(ty: t) -> Vec<ParamTy> {
3181     let mut rslt = Vec::new();
3182     walk_ty(ty, |ty| {
3183         match get(ty).sty {
3184           ty_param(p) => {
3185             rslt.push(p);
3186           }
3187           _ => ()
3188         }
3189     });
3190     rslt
3191 }
3192
3193 pub fn ty_sort_str(cx: &ctxt, t: t) -> String {
3194     match get(t).sty {
3195         ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
3196         ty_uint(_) | ty_float(_) | ty_str => {
3197             ::util::ppaux::ty_to_str(cx, t)
3198         }
3199
3200         ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
3201         ty_box(_) => "Gc-ptr".to_string(),
3202         ty_uniq(_) => "box".to_string(),
3203         ty_vec(_, _) => "vector".to_string(),
3204         ty_ptr(_) => "*-ptr".to_string(),
3205         ty_rptr(_, _) => "&-ptr".to_string(),
3206         ty_bare_fn(_) => "extern fn".to_string(),
3207         ty_closure(_) => "fn".to_string(),
3208         ty_trait(ref inner) => {
3209             format!("trait {}", item_path_str(cx, inner.def_id))
3210         }
3211         ty_struct(id, _) => {
3212             format!("struct {}", item_path_str(cx, id))
3213         }
3214         ty_tup(_) => "tuple".to_string(),
3215         ty_infer(TyVar(_)) => "inferred type".to_string(),
3216         ty_infer(IntVar(_)) => "integral variable".to_string(),
3217         ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
3218         ty_param(ref p) => {
3219             if p.space == subst::SelfSpace {
3220                 "Self".to_string()
3221             } else {
3222                 "type parameter".to_string()
3223             }
3224         }
3225         ty_err => "type error".to_string(),
3226     }
3227 }
3228
3229 pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> String {
3230     /*!
3231      *
3232      * Explains the source of a type err in a short,
3233      * human readable way.  This is meant to be placed in
3234      * parentheses after some larger message.  You should
3235      * also invoke `note_and_explain_type_err()` afterwards
3236      * to present additional details, particularly when
3237      * it comes to lifetime-related errors. */
3238
3239     fn tstore_to_closure(s: &TraitStore) -> String {
3240         match s {
3241             &UniqTraitStore => "proc".to_string(),
3242             &RegionTraitStore(..) => "closure".to_string()
3243         }
3244     }
3245
3246     match *err {
3247         terr_mismatch => "types differ".to_string(),
3248         terr_fn_style_mismatch(values) => {
3249             format!("expected {} fn but found {} fn",
3250                     values.expected.to_str(),
3251                     values.found.to_str())
3252         }
3253         terr_abi_mismatch(values) => {
3254             format!("expected {} fn but found {} fn",
3255                     values.expected.to_str(),
3256                     values.found.to_str())
3257         }
3258         terr_onceness_mismatch(values) => {
3259             format!("expected {} fn but found {} fn",
3260                     values.expected.to_str(),
3261                     values.found.to_str())
3262         }
3263         terr_sigil_mismatch(values) => {
3264             format!("expected {}, found {}",
3265                     tstore_to_closure(&values.expected),
3266                     tstore_to_closure(&values.found))
3267         }
3268         terr_mutability => "values differ in mutability".to_string(),
3269         terr_box_mutability => {
3270             "boxed values differ in mutability".to_string()
3271         }
3272         terr_vec_mutability => "vectors differ in mutability".to_string(),
3273         terr_ptr_mutability => "pointers differ in mutability".to_string(),
3274         terr_ref_mutability => "references differ in mutability".to_string(),
3275         terr_ty_param_size(values) => {
3276             format!("expected a type with {} type params \
3277                      but found one with {} type params",
3278                     values.expected,
3279                     values.found)
3280         }
3281         terr_tuple_size(values) => {
3282             format!("expected a tuple with {} elements \
3283                      but found one with {} elements",
3284                     values.expected,
3285                     values.found)
3286         }
3287         terr_record_size(values) => {
3288             format!("expected a record with {} fields \
3289                      but found one with {} fields",
3290                     values.expected,
3291                     values.found)
3292         }
3293         terr_record_mutability => {
3294             "record elements differ in mutability".to_string()
3295         }
3296         terr_record_fields(values) => {
3297             format!("expected a record with field `{}` but found one \
3298                      with field `{}`",
3299                     token::get_ident(values.expected),
3300                     token::get_ident(values.found))
3301         }
3302         terr_arg_count => {
3303             "incorrect number of function parameters".to_string()
3304         }
3305         terr_regions_does_not_outlive(..) => {
3306             "lifetime mismatch".to_string()
3307         }
3308         terr_regions_not_same(..) => {
3309             "lifetimes are not the same".to_string()
3310         }
3311         terr_regions_no_overlap(..) => {
3312             "lifetimes do not intersect".to_string()
3313         }
3314         terr_regions_insufficiently_polymorphic(br, _) => {
3315             format!("expected bound lifetime parameter {}, \
3316                      but found concrete lifetime",
3317                     bound_region_ptr_to_str(cx, br))
3318         }
3319         terr_regions_overly_polymorphic(br, _) => {
3320             format!("expected concrete lifetime, \
3321                      but found bound lifetime parameter {}",
3322                     bound_region_ptr_to_str(cx, br))
3323         }
3324         terr_trait_stores_differ(_, ref values) => {
3325             format!("trait storage differs: expected `{}` but found `{}`",
3326                     trait_store_to_str(cx, (*values).expected),
3327                     trait_store_to_str(cx, (*values).found))
3328         }
3329         terr_sorts(values) => {
3330             format!("expected {} but found {}",
3331                     ty_sort_str(cx, values.expected),
3332                     ty_sort_str(cx, values.found))
3333         }
3334         terr_traits(values) => {
3335             format!("expected trait `{}` but found trait `{}`",
3336                     item_path_str(cx, values.expected),
3337                     item_path_str(cx, values.found))
3338         }
3339         terr_builtin_bounds(values) => {
3340             if values.expected.is_empty() {
3341                 format!("expected no bounds but found `{}`",
3342                         values.found.user_string(cx))
3343             } else if values.found.is_empty() {
3344                 format!("expected bounds `{}` but found no bounds",
3345                         values.expected.user_string(cx))
3346             } else {
3347                 format!("expected bounds `{}` but found bounds `{}`",
3348                         values.expected.user_string(cx),
3349                         values.found.user_string(cx))
3350             }
3351         }
3352         terr_integer_as_char => {
3353             "expected an integral type but found `char`".to_string()
3354         }
3355         terr_int_mismatch(ref values) => {
3356             format!("expected `{}` but found `{}`",
3357                     values.expected.to_str(),
3358                     values.found.to_str())
3359         }
3360         terr_float_mismatch(ref values) => {
3361             format!("expected `{}` but found `{}`",
3362                     values.expected.to_str(),
3363                     values.found.to_str())
3364         }
3365         terr_variadic_mismatch(ref values) => {
3366             format!("expected {} fn but found {} function",
3367                     if values.expected { "variadic" } else { "non-variadic" },
3368                     if values.found { "variadic" } else { "non-variadic" })
3369         }
3370     }
3371 }
3372
3373 pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) {
3374     match *err {
3375         terr_regions_does_not_outlive(subregion, superregion) => {
3376             note_and_explain_region(cx, "", subregion, "...");
3377             note_and_explain_region(cx, "...does not necessarily outlive ",
3378                                     superregion, "");
3379         }
3380         terr_regions_not_same(region1, region2) => {
3381             note_and_explain_region(cx, "", region1, "...");
3382             note_and_explain_region(cx, "...is not the same lifetime as ",
3383                                     region2, "");
3384         }
3385         terr_regions_no_overlap(region1, region2) => {
3386             note_and_explain_region(cx, "", region1, "...");
3387             note_and_explain_region(cx, "...does not overlap ",
3388                                     region2, "");
3389         }
3390         terr_regions_insufficiently_polymorphic(_, conc_region) => {
3391             note_and_explain_region(cx,
3392                                     "concrete lifetime that was found is ",
3393                                     conc_region, "");
3394         }
3395         terr_regions_overly_polymorphic(_, conc_region) => {
3396             note_and_explain_region(cx,
3397                                     "expected concrete lifetime is ",
3398                                     conc_region, "");
3399         }
3400         _ => {}
3401     }
3402 }
3403
3404 pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
3405     cx.provided_method_sources.borrow().find(&id).map(|x| *x)
3406 }
3407
3408 pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
3409     if is_local(id) {
3410         match cx.map.find(id.node) {
3411             Some(ast_map::NodeItem(item)) => {
3412                 match item.node {
3413                     ItemTrait(_, _, _, ref ms) => {
3414                         let (_, p) = ast_util::split_trait_methods(ms.as_slice());
3415                         p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
3416                     }
3417                     _ => {
3418                         cx.sess.bug(format!("provided_trait_methods: `{}` is \
3419                                              not a trait",
3420                                             id).as_slice())
3421                     }
3422                 }
3423             }
3424             _ => {
3425                 cx.sess.bug(format!("provided_trait_methods: `{}` is not a \
3426                                      trait",
3427                                     id).as_slice())
3428             }
3429         }
3430     } else {
3431         csearch::get_provided_trait_methods(cx, id)
3432     }
3433 }
3434
3435 pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<TraitRef>>> {
3436     // Check the cache.
3437     match cx.supertraits.borrow().find(&id) {
3438         Some(trait_refs) => { return trait_refs.clone(); }
3439         None => {}  // Continue.
3440     }
3441
3442     // Not in the cache. It had better be in the metadata, which means it
3443     // shouldn't be local.
3444     assert!(!is_local(id));
3445
3446     // Get the supertraits out of the metadata and create the
3447     // TraitRef for each.
3448     let result = Rc::new(csearch::get_supertraits(cx, id));
3449     cx.supertraits.borrow_mut().insert(id, result.clone());
3450     result
3451 }
3452
3453 pub fn trait_ref_supertraits(cx: &ctxt, trait_ref: &ty::TraitRef) -> Vec<Rc<TraitRef>> {
3454     let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
3455     supertrait_refs.iter().map(
3456         |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs)).collect()
3457 }
3458
3459 fn lookup_locally_or_in_crate_store<V:Clone>(
3460                                     descr: &str,
3461                                     def_id: ast::DefId,
3462                                     map: &mut DefIdMap<V>,
3463                                     load_external: || -> V) -> V {
3464     /*!
3465      * Helper for looking things up in the various maps
3466      * that are populated during typeck::collect (e.g.,
3467      * `cx.methods`, `cx.tcache`, etc).  All of these share
3468      * the pattern that if the id is local, it should have
3469      * been loaded into the map by the `typeck::collect` phase.
3470      * If the def-id is external, then we have to go consult
3471      * the crate loading code (and cache the result for the future).
3472      */
3473
3474     match map.find_copy(&def_id) {
3475         Some(v) => { return v; }
3476         None => { }
3477     }
3478
3479     if def_id.krate == ast::LOCAL_CRATE {
3480         fail!("No def'n found for {:?} in tcx.{}", def_id, descr);
3481     }
3482     let v = load_external();
3483     map.insert(def_id, v.clone());
3484     v
3485 }
3486
3487 pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> Rc<Method> {
3488     let method_def_id = *ty::trait_method_def_ids(cx, trait_did).get(idx);
3489     ty::method(cx, method_def_id)
3490 }
3491
3492
3493 pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> Rc<Vec<Rc<Method>>> {
3494     let mut trait_methods = cx.trait_methods_cache.borrow_mut();
3495     match trait_methods.find_copy(&trait_did) {
3496         Some(methods) => methods,
3497         None => {
3498             let def_ids = ty::trait_method_def_ids(cx, trait_did);
3499             let methods: Rc<Vec<Rc<Method>>> = Rc::new(def_ids.iter().map(|d| {
3500                 ty::method(cx, *d)
3501             }).collect());
3502             trait_methods.insert(trait_did, methods.clone());
3503             methods
3504         }
3505     }
3506 }
3507
3508 pub fn method(cx: &ctxt, id: ast::DefId) -> Rc<Method> {
3509     lookup_locally_or_in_crate_store("methods", id,
3510                                      &mut *cx.methods.borrow_mut(), || {
3511         Rc::new(csearch::get_method(cx, id))
3512     })
3513 }
3514
3515 pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> Rc<Vec<DefId>> {
3516     lookup_locally_or_in_crate_store("trait_method_def_ids",
3517                                      id,
3518                                      &mut *cx.trait_method_def_ids.borrow_mut(),
3519                                      || {
3520         Rc::new(csearch::get_trait_method_def_ids(&cx.sess.cstore, id))
3521     })
3522 }
3523
3524 pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<Rc<TraitRef>> {
3525     match cx.impl_trait_cache.borrow().find(&id) {
3526         Some(ret) => { return ret.clone(); }
3527         None => {}
3528     }
3529
3530     let ret = if id.krate == ast::LOCAL_CRATE {
3531         debug!("(impl_trait_ref) searching for trait impl {:?}", id);
3532         match cx.map.find(id.node) {
3533             Some(ast_map::NodeItem(item)) => {
3534                 match item.node {
3535                     ast::ItemImpl(_, ref opt_trait, _, _) => {
3536                         match opt_trait {
3537                             &Some(ref t) => {
3538                                 Some(ty::node_id_to_trait_ref(cx, t.ref_id))
3539                             }
3540                             &None => None
3541                         }
3542                     }
3543                     _ => None
3544                 }
3545             }
3546             _ => None
3547         }
3548     } else {
3549         csearch::get_impl_trait(cx, id)
3550     };
3551
3552     cx.impl_trait_cache.borrow_mut().insert(id, ret.clone());
3553     ret
3554 }
3555
3556 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
3557     let def = *tcx.def_map.borrow()
3558                      .find(&tr.ref_id)
3559                      .expect("no def-map entry for trait");
3560     def.def_id()
3561 }
3562
3563 pub fn try_add_builtin_trait(tcx: &ctxt,
3564                              trait_def_id: ast::DefId,
3565                              builtin_bounds: &mut BuiltinBounds) -> bool {
3566     //! Checks whether `trait_ref` refers to one of the builtin
3567     //! traits, like `Send`, and adds the corresponding
3568     //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
3569     //! is a builtin trait.
3570
3571     match tcx.lang_items.to_builtin_kind(trait_def_id) {
3572         Some(bound) => { builtin_bounds.add(bound); true }
3573         None => false
3574     }
3575 }
3576
3577 pub fn ty_to_def_id(ty: t) -> Option<ast::DefId> {
3578     match get(ty).sty {
3579         ty_trait(box TyTrait { def_id: id, .. }) |
3580         ty_struct(id, _) |
3581         ty_enum(id, _) => Some(id),
3582         _ => None
3583     }
3584 }
3585
3586 // Enum information
3587 #[deriving(Clone)]
3588 pub struct VariantInfo {
3589     pub args: Vec<t>,
3590     pub arg_names: Option<Vec<ast::Ident> >,
3591     pub ctor_ty: t,
3592     pub name: ast::Ident,
3593     pub id: ast::DefId,
3594     pub disr_val: Disr,
3595     pub vis: Visibility
3596 }
3597
3598 impl VariantInfo {
3599
3600     /// Creates a new VariantInfo from the corresponding ast representation.
3601     ///
3602     /// Does not do any caching of the value in the type context.
3603     pub fn from_ast_variant(cx: &ctxt,
3604                             ast_variant: &ast::Variant,
3605                             discriminant: Disr) -> VariantInfo {
3606         let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
3607
3608         match ast_variant.node.kind {
3609             ast::TupleVariantKind(ref args) => {
3610                 let arg_tys = if args.len() > 0 {
3611                     ty_fn_args(ctor_ty).iter().map(|a| *a).collect()
3612                 } else {
3613                     Vec::new()
3614                 };
3615
3616                 return VariantInfo {
3617                     args: arg_tys,
3618                     arg_names: None,
3619                     ctor_ty: ctor_ty,
3620                     name: ast_variant.node.name,
3621                     id: ast_util::local_def(ast_variant.node.id),
3622                     disr_val: discriminant,
3623                     vis: ast_variant.node.vis
3624                 };
3625             },
3626             ast::StructVariantKind(ref struct_def) => {
3627
3628                 let fields: &[StructField] = struct_def.fields.as_slice();
3629
3630                 assert!(fields.len() > 0);
3631
3632                 let arg_tys = ty_fn_args(ctor_ty).iter().map(|a| *a).collect();
3633                 let arg_names = fields.iter().map(|field| {
3634                     match field.node.kind {
3635                         NamedField(ident, _) => ident,
3636                         UnnamedField(..) => cx.sess.bug(
3637                             "enum_variants: all fields in struct must have a name")
3638                     }
3639                 }).collect();
3640
3641                 return VariantInfo {
3642                     args: arg_tys,
3643                     arg_names: Some(arg_names),
3644                     ctor_ty: ctor_ty,
3645                     name: ast_variant.node.name,
3646                     id: ast_util::local_def(ast_variant.node.id),
3647                     disr_val: discriminant,
3648                     vis: ast_variant.node.vis
3649                 };
3650             }
3651         }
3652     }
3653 }
3654
3655 pub fn substd_enum_variants(cx: &ctxt,
3656                             id: ast::DefId,
3657                             substs: &Substs)
3658                          -> Vec<Rc<VariantInfo>> {
3659     enum_variants(cx, id).iter().map(|variant_info| {
3660         let substd_args = variant_info.args.iter()
3661             .map(|aty| aty.subst(cx, substs)).collect();
3662
3663         let substd_ctor_ty = variant_info.ctor_ty.subst(cx, substs);
3664
3665         Rc::new(VariantInfo {
3666             args: substd_args,
3667             ctor_ty: substd_ctor_ty,
3668             ..(**variant_info).clone()
3669         })
3670     }).collect()
3671 }
3672
3673 pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String {
3674     with_path(cx, id, |path| ast_map::path_to_str(path)).to_string()
3675 }
3676
3677 pub enum DtorKind {
3678     NoDtor,
3679     TraitDtor(DefId, bool)
3680 }
3681
3682 impl DtorKind {
3683     pub fn is_not_present(&self) -> bool {
3684         match *self {
3685             NoDtor => true,
3686             _ => false
3687         }
3688     }
3689
3690     pub fn is_present(&self) -> bool {
3691         !self.is_not_present()
3692     }
3693
3694     pub fn has_drop_flag(&self) -> bool {
3695         match self {
3696             &NoDtor => false,
3697             &TraitDtor(_, flag) => flag
3698         }
3699     }
3700 }
3701
3702 /* If struct_id names a struct with a dtor, return Some(the dtor's id).
3703    Otherwise return none. */
3704 pub fn ty_dtor(cx: &ctxt, struct_id: DefId) -> DtorKind {
3705     match cx.destructor_for_type.borrow().find(&struct_id) {
3706         Some(&method_def_id) => {
3707             let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
3708
3709             TraitDtor(method_def_id, flag)
3710         }
3711         None => NoDtor,
3712     }
3713 }
3714
3715 pub fn has_dtor(cx: &ctxt, struct_id: DefId) -> bool {
3716     ty_dtor(cx, struct_id).is_present()
3717 }
3718
3719 pub fn with_path<T>(cx: &ctxt, id: ast::DefId, f: |ast_map::PathElems| -> T) -> T {
3720     if id.krate == ast::LOCAL_CRATE {
3721         cx.map.with_path(id.node, f)
3722     } else {
3723         f(ast_map::Values(csearch::get_item_path(cx, id).iter()).chain(None))
3724     }
3725 }
3726
3727 pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool {
3728     enum_variants(cx, id).len() == 1
3729 }
3730
3731 pub fn type_is_empty(cx: &ctxt, t: t) -> bool {
3732     match ty::get(t).sty {
3733        ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
3734        _ => false
3735      }
3736 }
3737
3738 pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
3739     match cx.enum_var_cache.borrow().find(&id) {
3740         Some(variants) => return variants.clone(),
3741         _ => { /* fallthrough */ }
3742     }
3743
3744     let result = if ast::LOCAL_CRATE != id.krate {
3745         Rc::new(csearch::get_enum_variants(cx, id))
3746     } else {
3747         /*
3748           Although both this code and check_enum_variants in typeck/check
3749           call eval_const_expr, it should never get called twice for the same
3750           expr, since check_enum_variants also updates the enum_var_cache
3751          */
3752         match cx.map.get(id.node) {
3753             ast_map::NodeItem(item) => {
3754                 match item.node {
3755                     ast::ItemEnum(ref enum_definition, _) => {
3756                         let mut last_discriminant: Option<Disr> = None;
3757                         Rc::new(enum_definition.variants.iter().map(|&variant| {
3758
3759                             let mut discriminant = match last_discriminant {
3760                                 Some(val) => val + 1,
3761                                 None => INITIAL_DISCRIMINANT_VALUE
3762                             };
3763
3764                             match variant.node.disr_expr {
3765                                 Some(ref e) => match const_eval::eval_const_expr_partial(cx, &**e) {
3766                                     Ok(const_eval::const_int(val)) => {
3767                                         discriminant = val as Disr
3768                                     }
3769                                     Ok(const_eval::const_uint(val)) => {
3770                                         discriminant = val as Disr
3771                                     }
3772                                     Ok(_) => {
3773                                         cx.sess
3774                                           .span_err(e.span,
3775                                                     "expected signed integer constant");
3776                                     }
3777                                     Err(ref err) => {
3778                                         cx.sess
3779                                           .span_err(e.span,
3780                                                     format!("expected constant: {}",
3781                                                             *err).as_slice());
3782                                     }
3783                                 },
3784                                 None => {}
3785                             };
3786
3787                             last_discriminant = Some(discriminant);
3788                             Rc::new(VariantInfo::from_ast_variant(cx, &*variant,
3789                                                                   discriminant))
3790                         }).collect())
3791                     }
3792                     _ => {
3793                         cx.sess.bug("enum_variants: id not bound to an enum")
3794                     }
3795                 }
3796             }
3797             _ => cx.sess.bug("enum_variants: id not bound to an enum")
3798         }
3799     };
3800
3801     cx.enum_var_cache.borrow_mut().insert(id, result.clone());
3802     result
3803 }
3804
3805
3806 // Returns information about the enum variant with the given ID:
3807 pub fn enum_variant_with_id(cx: &ctxt,
3808                             enum_id: ast::DefId,
3809                             variant_id: ast::DefId)
3810                          -> Rc<VariantInfo> {
3811     enum_variants(cx, enum_id).iter()
3812                               .find(|variant| variant.id == variant_id)
3813                               .expect("enum_variant_with_id(): no variant exists with that ID")
3814                               .clone()
3815 }
3816
3817
3818 // If the given item is in an external crate, looks up its type and adds it to
3819 // the type cache. Returns the type parameters and type.
3820 pub fn lookup_item_type(cx: &ctxt,
3821                         did: ast::DefId)
3822                      -> Polytype {
3823     lookup_locally_or_in_crate_store(
3824         "tcache", did, &mut *cx.tcache.borrow_mut(),
3825         || csearch::get_type(cx, did))
3826 }
3827
3828 pub fn lookup_impl_vtables(cx: &ctxt,
3829                            did: ast::DefId)
3830                            -> typeck::vtable_res {
3831     lookup_locally_or_in_crate_store(
3832         "impl_vtables", did, &mut *cx.impl_vtables.borrow_mut(),
3833         || csearch::get_impl_vtables(cx, did) )
3834 }
3835
3836 /// Given the did of a trait, returns its canonical trait ref.
3837 pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc<ty::TraitDef> {
3838     let mut trait_defs = cx.trait_defs.borrow_mut();
3839     match trait_defs.find_copy(&did) {
3840         Some(trait_def) => {
3841             // The item is in this crate. The caller should have added it to the
3842             // type cache already
3843             trait_def
3844         }
3845         None => {
3846             assert!(did.krate != ast::LOCAL_CRATE);
3847             let trait_def = Rc::new(csearch::get_trait_def(cx, did));
3848             trait_defs.insert(did, trait_def.clone());
3849             trait_def
3850         }
3851     }
3852 }
3853
3854 /// Iterate over attributes of a definition.
3855 // (This should really be an iterator, but that would require csearch and
3856 // decoder to use iterators instead of higher-order functions.)
3857 pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool {
3858     if is_local(did) {
3859         let item = tcx.map.expect_item(did.node);
3860         item.attrs.iter().advance(|attr| f(attr))
3861     } else {
3862         info!("getting foreign attrs");
3863         let mut cont = true;
3864         csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| {
3865             if cont {
3866                 cont = attrs.iter().advance(|attr| f(attr));
3867             }
3868         });
3869         info!("done");
3870         cont
3871     }
3872 }
3873
3874 /// Determine whether an item is annotated with an attribute
3875 pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
3876     let mut found = false;
3877     each_attr(tcx, did, |item| {
3878         if item.check_name(attr) {
3879             found = true;
3880             false
3881         } else {
3882             true
3883         }
3884     });
3885     found
3886 }
3887
3888 /// Determine whether an item is annotated with `#[packed]`
3889 pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool {
3890     has_attr(tcx, did, "packed")
3891 }
3892
3893 /// Determine whether an item is annotated with `#[simd]`
3894 pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
3895     has_attr(tcx, did, "simd")
3896 }
3897
3898 // Obtain the representation annotation for a definition.
3899 pub fn lookup_repr_hint(tcx: &ctxt, did: DefId) -> attr::ReprAttr {
3900     let mut acc = attr::ReprAny;
3901     ty::each_attr(tcx, did, |meta| {
3902         acc = attr::find_repr_attr(tcx.sess.diagnostic(), meta, acc);
3903         true
3904     });
3905     return acc;
3906 }
3907
3908 // Look up a field ID, whether or not it's local
3909 // Takes a list of type substs in case the struct is generic
3910 pub fn lookup_field_type(tcx: &ctxt,
3911                          struct_id: DefId,
3912                          id: DefId,
3913                          substs: &Substs)
3914                       -> ty::t {
3915     let t = if id.krate == ast::LOCAL_CRATE {
3916         node_id_to_type(tcx, id.node)
3917     } else {
3918         let mut tcache = tcx.tcache.borrow_mut();
3919         match tcache.find(&id) {
3920            Some(&Polytype {ty, ..}) => ty,
3921            None => {
3922                let tpt = csearch::get_field_type(tcx, struct_id, id);
3923                tcache.insert(id, tpt.clone());
3924                tpt.ty
3925            }
3926         }
3927     };
3928     t.subst(tcx, substs)
3929 }
3930
3931 // Lookup all ancestor structs of a struct indicated by did. That is the reflexive,
3932 // transitive closure of doing a single lookup in cx.superstructs.
3933 fn each_super_struct(cx: &ctxt, mut did: ast::DefId, f: |ast::DefId|) {
3934     let superstructs = cx.superstructs.borrow();
3935
3936     loop {
3937         f(did);
3938         match superstructs.find(&did) {
3939             Some(&Some(def_id)) => {
3940                 did = def_id;
3941             },
3942             Some(&None) => break,
3943             None => {
3944                 cx.sess.bug(
3945                     format!("ID not mapped to super-struct: {}",
3946                             cx.map.node_to_str(did.node)).as_slice());
3947             }
3948         }
3949     }
3950 }
3951
3952 // Look up the list of field names and IDs for a given struct.
3953 // Fails if the id is not bound to a struct.
3954 pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
3955     if did.krate == ast::LOCAL_CRATE {
3956         // We store the fields which are syntactically in each struct in cx. So
3957         // we have to walk the inheritance chain of the struct to get all the
3958         // structs (explicit and inherited) for a struct. If this is expensive
3959         // we could cache the whole list of fields here.
3960         let struct_fields = cx.struct_fields.borrow();
3961         let mut results: SmallVector<&[field_ty]> = SmallVector::zero();
3962         each_super_struct(cx, did, |s| {
3963             match struct_fields.find(&s) {
3964                 Some(fields) => results.push(fields.as_slice()),
3965                 _ => {
3966                     cx.sess.bug(
3967                         format!("ID not mapped to struct fields: {}",
3968                                 cx.map.node_to_str(did.node)).as_slice());
3969                 }
3970             }
3971         });
3972
3973         let len = results.as_slice().iter().map(|x| x.len()).sum();
3974         let mut result: Vec<field_ty> = Vec::with_capacity(len);
3975         result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|&f| f)));
3976         assert!(result.len() == len);
3977         result
3978     } else {
3979         csearch::get_struct_fields(&cx.sess.cstore, did)
3980     }
3981 }
3982
3983 pub fn lookup_struct_field(cx: &ctxt,
3984                            parent: ast::DefId,
3985                            field_id: ast::DefId)
3986                         -> field_ty {
3987     let r = lookup_struct_fields(cx, parent);
3988     match r.iter().find(|f| f.id.node == field_id.node) {
3989         Some(t) => *t,
3990         None => cx.sess.bug("struct ID not found in parent's fields")
3991     }
3992 }
3993
3994 // Returns a list of fields corresponding to the struct's items. trans uses
3995 // this. Takes a list of substs with which to instantiate field types.
3996 pub fn struct_fields(cx: &ctxt, did: ast::DefId, substs: &Substs)
3997                      -> Vec<field> {
3998     lookup_struct_fields(cx, did).iter().map(|f| {
3999        field {
4000             // FIXME #6993: change type of field to Name and get rid of new()
4001             ident: ast::Ident::new(f.name),
4002             mt: mt {
4003                 ty: lookup_field_type(cx, did, f.id, substs),
4004                 mutbl: MutImmutable
4005             }
4006         }
4007     }).collect()
4008 }
4009
4010 pub fn is_binopable(cx: &ctxt, ty: t, op: ast::BinOp) -> bool {
4011     static tycat_other: int = 0;
4012     static tycat_bool: int = 1;
4013     static tycat_char: int = 2;
4014     static tycat_int: int = 3;
4015     static tycat_float: int = 4;
4016     static tycat_bot: int = 5;
4017     static tycat_raw_ptr: int = 6;
4018
4019     static opcat_add: int = 0;
4020     static opcat_sub: int = 1;
4021     static opcat_mult: int = 2;
4022     static opcat_shift: int = 3;
4023     static opcat_rel: int = 4;
4024     static opcat_eq: int = 5;
4025     static opcat_bit: int = 6;
4026     static opcat_logic: int = 7;
4027     static opcat_mod: int = 8;
4028
4029     fn opcat(op: ast::BinOp) -> int {
4030         match op {
4031           ast::BiAdd => opcat_add,
4032           ast::BiSub => opcat_sub,
4033           ast::BiMul => opcat_mult,
4034           ast::BiDiv => opcat_mult,
4035           ast::BiRem => opcat_mod,
4036           ast::BiAnd => opcat_logic,
4037           ast::BiOr => opcat_logic,
4038           ast::BiBitXor => opcat_bit,
4039           ast::BiBitAnd => opcat_bit,
4040           ast::BiBitOr => opcat_bit,
4041           ast::BiShl => opcat_shift,
4042           ast::BiShr => opcat_shift,
4043           ast::BiEq => opcat_eq,
4044           ast::BiNe => opcat_eq,
4045           ast::BiLt => opcat_rel,
4046           ast::BiLe => opcat_rel,
4047           ast::BiGe => opcat_rel,
4048           ast::BiGt => opcat_rel
4049         }
4050     }
4051
4052     fn tycat(cx: &ctxt, ty: t) -> int {
4053         if type_is_simd(cx, ty) {
4054             return tycat(cx, simd_type(cx, ty))
4055         }
4056         match get(ty).sty {
4057           ty_char => tycat_char,
4058           ty_bool => tycat_bool,
4059           ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4060           ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
4061           ty_bot => tycat_bot,
4062           ty_ptr(_) => tycat_raw_ptr,
4063           _ => tycat_other
4064         }
4065     }
4066
4067     static t: bool = true;
4068     static f: bool = false;
4069
4070     let tbl = [
4071     //           +, -, *, shift, rel, ==, bit, logic, mod
4072     /*other*/   [f, f, f, f,     f,   f,  f,   f,     f],
4073     /*bool*/    [f, f, f, f,     t,   t,  t,   t,     f],
4074     /*char*/    [f, f, f, f,     t,   t,  f,   f,     f],
4075     /*int*/     [t, t, t, t,     t,   t,  t,   f,     t],
4076     /*float*/   [t, t, t, f,     t,   t,  f,   f,     f],
4077     /*bot*/     [t, t, t, t,     t,   t,  t,   t,     t],
4078     /*raw ptr*/ [f, f, f, f,     t,   t,  f,   f,     f]];
4079
4080     return tbl[tycat(cx, ty) as uint ][opcat(op) as uint];
4081 }
4082
4083 /// Returns an equivalent type with all the typedefs and self regions removed.
4084 pub fn normalize_ty(cx: &ctxt, t: t) -> t {
4085     let u = TypeNormalizer(cx).fold_ty(t);
4086     return u;
4087
4088     struct TypeNormalizer<'a>(&'a ctxt);
4089
4090     impl<'a> TypeFolder for TypeNormalizer<'a> {
4091         fn tcx<'a>(&'a self) -> &'a ctxt { let TypeNormalizer(c) = *self; c }
4092
4093         fn fold_ty(&mut self, t: ty::t) -> ty::t {
4094             match self.tcx().normalized_cache.borrow().find_copy(&t) {
4095                 None => {}
4096                 Some(u) => return u
4097             }
4098
4099             let t_norm = ty_fold::super_fold_ty(self, t);
4100             self.tcx().normalized_cache.borrow_mut().insert(t, t_norm);
4101             return t_norm;
4102         }
4103
4104         fn fold_region(&mut self, _: ty::Region) -> ty::Region {
4105             ty::ReStatic
4106         }
4107
4108         fn fold_substs(&mut self,
4109                        substs: &subst::Substs)
4110                        -> subst::Substs {
4111             subst::Substs { regions: subst::ErasedRegions,
4112                             types: substs.types.fold_with(self) }
4113         }
4114
4115         fn fold_sig(&mut self,
4116                     sig: &ty::FnSig)
4117                     -> ty::FnSig {
4118             // The binder-id is only relevant to bound regions, which
4119             // are erased at trans time.
4120             ty::FnSig {
4121                 binder_id: ast::DUMMY_NODE_ID,
4122                 inputs: sig.inputs.fold_with(self),
4123                 output: sig.output.fold_with(self),
4124                 variadic: sig.variadic,
4125             }
4126         }
4127     }
4128 }
4129
4130 pub trait ExprTyProvider {
4131     fn expr_ty(&self, ex: &ast::Expr) -> t;
4132     fn ty_ctxt<'a>(&'a self) -> &'a ctxt;
4133 }
4134
4135 impl ExprTyProvider for ctxt {
4136     fn expr_ty(&self, ex: &ast::Expr) -> t {
4137         expr_ty(self, ex)
4138     }
4139
4140     fn ty_ctxt<'a>(&'a self) -> &'a ctxt {
4141         self
4142     }
4143 }
4144
4145 // Returns the repeat count for a repeating vector expression.
4146 pub fn eval_repeat_count<T: ExprTyProvider>(tcx: &T, count_expr: &ast::Expr) -> uint {
4147     match const_eval::eval_const_expr_partial(tcx, count_expr) {
4148       Ok(ref const_val) => match *const_val {
4149         const_eval::const_int(count) => if count < 0 {
4150             tcx.ty_ctxt().sess.span_err(count_expr.span,
4151                                         "expected positive integer for \
4152                                          repeat count but found negative integer");
4153             return 0;
4154         } else {
4155             return count as uint
4156         },
4157         const_eval::const_uint(count) => return count as uint,
4158         const_eval::const_float(count) => {
4159             tcx.ty_ctxt().sess.span_err(count_expr.span,
4160                                         "expected positive integer for \
4161                                          repeat count but found float");
4162             return count as uint;
4163         }
4164         const_eval::const_str(_) => {
4165             tcx.ty_ctxt().sess.span_err(count_expr.span,
4166                                         "expected positive integer for \
4167                                          repeat count but found string");
4168             return 0;
4169         }
4170         const_eval::const_bool(_) => {
4171             tcx.ty_ctxt().sess.span_err(count_expr.span,
4172                                         "expected positive integer for \
4173                                          repeat count but found boolean");
4174             return 0;
4175         }
4176         const_eval::const_binary(_) => {
4177             tcx.ty_ctxt().sess.span_err(count_expr.span,
4178                                         "expected positive integer for \
4179                                          repeat count but found binary array");
4180             return 0;
4181         }
4182         const_eval::const_nil => {
4183             tcx.ty_ctxt().sess.span_err(count_expr.span,
4184                                         "expected positive integer for \
4185                                          repeat count but found ()");
4186             return 0;
4187         }
4188       },
4189       Err(..) => {
4190         tcx.ty_ctxt().sess.span_err(count_expr.span,
4191                                     "expected constant integer for repeat count \
4192                                      but found variable");
4193         return 0;
4194       }
4195     }
4196 }
4197
4198 // Iterate over a type parameter's bounded traits and any supertraits
4199 // of those traits, ignoring kinds.
4200 // Here, the supertraits are the transitive closure of the supertrait
4201 // relation on the supertraits from each bounded trait's constraint
4202 // list.
4203 pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
4204                                         bounds: &[Rc<TraitRef>],
4205                                         f: |Rc<TraitRef>| -> bool)
4206                                         -> bool {
4207     for bound_trait_ref in bounds.iter() {
4208         let mut supertrait_set = HashMap::new();
4209         let mut trait_refs = Vec::new();
4210         let mut i = 0;
4211
4212         // Seed the worklist with the trait from the bound
4213         supertrait_set.insert(bound_trait_ref.def_id, ());
4214         trait_refs.push(bound_trait_ref.clone());
4215
4216         // Add the given trait ty to the hash map
4217         while i < trait_refs.len() {
4218             debug!("each_bound_trait_and_supertraits(i={:?}, trait_ref={})",
4219                    i, trait_refs.get(i).repr(tcx));
4220
4221             if !f(trait_refs.get(i).clone()) {
4222                 return false;
4223             }
4224
4225             // Add supertraits to supertrait_set
4226             let supertrait_refs = trait_ref_supertraits(tcx,
4227                                                         &**trait_refs.get(i));
4228             for supertrait_ref in supertrait_refs.iter() {
4229                 debug!("each_bound_trait_and_supertraits(supertrait_ref={})",
4230                        supertrait_ref.repr(tcx));
4231
4232                 let d_id = supertrait_ref.def_id;
4233                 if !supertrait_set.contains_key(&d_id) {
4234                     // FIXME(#5527) Could have same trait multiple times
4235                     supertrait_set.insert(d_id, ());
4236                     trait_refs.push(supertrait_ref.clone());
4237                 }
4238             }
4239
4240             i += 1;
4241         }
4242     }
4243     return true;
4244 }
4245
4246 pub fn get_tydesc_ty(tcx: &ctxt) -> Result<t, String> {
4247     tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| {
4248         tcx.intrinsic_defs.borrow().find_copy(&tydesc_lang_item)
4249             .expect("Failed to resolve TyDesc")
4250     })
4251 }
4252
4253 pub fn get_opaque_ty(tcx: &ctxt) -> Result<t, String> {
4254     tcx.lang_items.require(OpaqueStructLangItem).map(|opaque_lang_item| {
4255         tcx.intrinsic_defs.borrow().find_copy(&opaque_lang_item)
4256             .expect("Failed to resolve Opaque")
4257     })
4258 }
4259
4260 pub fn visitor_object_ty(tcx: &ctxt,
4261                          region: ty::Region) -> Result<(Rc<TraitRef>, t), String> {
4262     let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
4263         Ok(id) => id,
4264         Err(s) => { return Err(s); }
4265     };
4266     let substs = Substs::empty();
4267     let trait_ref = Rc::new(TraitRef { def_id: trait_lang_item, substs: substs });
4268     Ok((trait_ref.clone(),
4269         mk_rptr(tcx, region, mt {mutbl: ast::MutMutable,
4270                                  ty: mk_trait(tcx,
4271                                               trait_ref.def_id,
4272                                               trait_ref.substs.clone(),
4273                                               empty_builtin_bounds()) })))
4274 }
4275
4276 pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
4277     lookup_locally_or_in_crate_store(
4278         "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
4279         || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
4280 }
4281
4282 /// Records a trait-to-implementation mapping.
4283 pub fn record_trait_implementation(tcx: &ctxt,
4284                                    trait_def_id: DefId,
4285                                    impl_def_id: DefId) {
4286     match tcx.trait_impls.borrow().find(&trait_def_id) {
4287         Some(impls_for_trait) => {
4288             impls_for_trait.borrow_mut().push(impl_def_id);
4289             return;
4290         }
4291         None => {}
4292     }
4293     tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
4294 }
4295
4296 /// Populates the type context with all the implementations for the given type
4297 /// if necessary.
4298 pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
4299                                                       type_id: ast::DefId) {
4300     if type_id.krate == LOCAL_CRATE {
4301         return
4302     }
4303     if tcx.populated_external_types.borrow().contains(&type_id) {
4304         return
4305     }
4306
4307     csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
4308             |impl_def_id| {
4309         let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
4310
4311         // Record the trait->implementation mappings, if applicable.
4312         let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
4313         for trait_ref in associated_traits.iter() {
4314             record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
4315         }
4316
4317         // For any methods that use a default implementation, add them to
4318         // the map. This is a bit unfortunate.
4319         for &method_def_id in methods.iter() {
4320             for &source in ty::method(tcx, method_def_id).provided_source.iter() {
4321                 tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
4322             }
4323         }
4324
4325         // Store the implementation info.
4326         tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
4327
4328         // If this is an inherent implementation, record it.
4329         if associated_traits.is_none() {
4330             match tcx.inherent_impls.borrow().find(&type_id) {
4331                 Some(implementation_list) => {
4332                     implementation_list.borrow_mut().push(impl_def_id);
4333                     return;
4334                 }
4335                 None => {}
4336             }
4337             tcx.inherent_impls.borrow_mut().insert(type_id,
4338                                                    Rc::new(RefCell::new(vec!(impl_def_id))));
4339         }
4340     });
4341
4342     tcx.populated_external_types.borrow_mut().insert(type_id);
4343 }
4344
4345 /// Populates the type context with all the implementations for the given
4346 /// trait if necessary.
4347 pub fn populate_implementations_for_trait_if_necessary(
4348         tcx: &ctxt,
4349         trait_id: ast::DefId) {
4350     if trait_id.krate == LOCAL_CRATE {
4351         return
4352     }
4353     if tcx.populated_external_traits.borrow().contains(&trait_id) {
4354         return
4355     }
4356
4357     csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
4358             |implementation_def_id| {
4359         let methods = csearch::get_impl_methods(&tcx.sess.cstore, implementation_def_id);
4360
4361         // Record the trait->implementation mapping.
4362         record_trait_implementation(tcx, trait_id, implementation_def_id);
4363
4364         // For any methods that use a default implementation, add them to
4365         // the map. This is a bit unfortunate.
4366         for &method_def_id in methods.iter() {
4367             for &source in ty::method(tcx, method_def_id).provided_source.iter() {
4368                 tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
4369             }
4370         }
4371
4372         // Store the implementation info.
4373         tcx.impl_methods.borrow_mut().insert(implementation_def_id, methods);
4374     });
4375
4376     tcx.populated_external_traits.borrow_mut().insert(trait_id);
4377 }
4378
4379 /// Given the def_id of an impl, return the def_id of the trait it implements.
4380 /// If it implements no trait, return `None`.
4381 pub fn trait_id_of_impl(tcx: &ctxt,
4382                         def_id: ast::DefId) -> Option<ast::DefId> {
4383     let node = match tcx.map.find(def_id.node) {
4384         Some(node) => node,
4385         None => return None
4386     };
4387     match node {
4388         ast_map::NodeItem(item) => {
4389             match item.node {
4390                 ast::ItemImpl(_, Some(ref trait_ref), _, _) => {
4391                     Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id)
4392                 }
4393                 _ => None
4394             }
4395         }
4396         _ => None
4397     }
4398 }
4399
4400 /// If the given def ID describes a method belonging to an impl, return the
4401 /// ID of the impl that the method belongs to. Otherwise, return `None`.
4402 pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
4403                        -> Option<ast::DefId> {
4404     if def_id.krate != LOCAL_CRATE {
4405         return match csearch::get_method(tcx, def_id).container {
4406             TraitContainer(_) => None,
4407             ImplContainer(def_id) => Some(def_id),
4408         };
4409     }
4410     match tcx.methods.borrow().find_copy(&def_id) {
4411         Some(method) => {
4412             match method.container {
4413                 TraitContainer(_) => None,
4414                 ImplContainer(def_id) => Some(def_id),
4415             }
4416         }
4417         None => None
4418     }
4419 }
4420
4421 /// If the given def ID describes a method belonging to a trait (either a
4422 /// default method or an implementation of a trait method), return the ID of
4423 /// the trait that the method belongs to. Otherwise, return `None`.
4424 pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
4425                        -> Option<ast::DefId> {
4426     if def_id.krate != LOCAL_CRATE {
4427         return csearch::get_trait_of_method(&tcx.sess.cstore, def_id, tcx);
4428     }
4429     match tcx.methods.borrow().find_copy(&def_id) {
4430         Some(method) => {
4431             match method.container {
4432                 TraitContainer(def_id) => Some(def_id),
4433                 ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
4434             }
4435         }
4436         None => None
4437     }
4438 }
4439
4440 /// If the given def ID describes a method belonging to a trait, (either a
4441 /// default method or an implementation of a trait method), return the ID of
4442 /// the method inside trait definition (this means that if the given def ID
4443 /// is already that of the original trait method, then the return value is
4444 /// the same).
4445 /// Otherwise, return `None`.
4446 pub fn trait_method_of_method(tcx: &ctxt,
4447                               def_id: ast::DefId) -> Option<ast::DefId> {
4448     let method = match tcx.methods.borrow().find(&def_id) {
4449         Some(m) => m.clone(),
4450         None => return None,
4451     };
4452     let name = method.ident.name;
4453     match trait_of_method(tcx, def_id) {
4454         Some(trait_did) => {
4455             let trait_methods = ty::trait_methods(tcx, trait_did);
4456             trait_methods.iter()
4457                 .position(|m| m.ident.name == name)
4458                 .map(|idx| ty::trait_method(tcx, trait_did, idx).def_id)
4459         }
4460         None => None
4461     }
4462 }
4463
4464 /// Creates a hash of the type `t` which will be the same no matter what crate
4465 /// context it's calculated within. This is used by the `type_id` intrinsic.
4466 pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
4467     let mut state = sip::SipState::new();
4468     macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } );
4469     macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } );
4470
4471     let region = |_state: &mut sip::SipState, r: Region| {
4472         match r {
4473             ReStatic => {}
4474
4475             ReEmpty |
4476             ReEarlyBound(..) |
4477             ReLateBound(..) |
4478             ReFree(..) |
4479             ReScope(..) |
4480             ReInfer(..) => {
4481                 tcx.sess.bug("non-static region found when hashing a type")
4482             }
4483         }
4484     };
4485     let did = |state: &mut sip::SipState, did: DefId| {
4486         let h = if ast_util::is_local(did) {
4487             svh.clone()
4488         } else {
4489             tcx.sess.cstore.get_crate_hash(did.krate)
4490         };
4491         h.as_str().hash(state);
4492         did.node.hash(state);
4493     };
4494     let mt = |state: &mut sip::SipState, mt: mt| {
4495         mt.mutbl.hash(state);
4496     };
4497     ty::walk_ty(t, |t| {
4498         match ty::get(t).sty {
4499             ty_nil => byte!(0),
4500             ty_bot => byte!(1),
4501             ty_bool => byte!(2),
4502             ty_char => byte!(3),
4503             ty_int(i) => {
4504                 byte!(4);
4505                 hash!(i);
4506             }
4507             ty_uint(u) => {
4508                 byte!(5);
4509                 hash!(u);
4510             }
4511             ty_float(f) => {
4512                 byte!(6);
4513                 hash!(f);
4514             }
4515             ty_str => {
4516                 byte!(7);
4517             }
4518             ty_enum(d, _) => {
4519                 byte!(8);
4520                 did(&mut state, d);
4521             }
4522             ty_box(_) => {
4523                 byte!(9);
4524             }
4525             ty_uniq(_) => {
4526                 byte!(10);
4527             }
4528             ty_vec(m, Some(n)) => {
4529                 byte!(11);
4530                 mt(&mut state, m);
4531                 n.hash(&mut state);
4532                 1u8.hash(&mut state);
4533             }
4534             ty_vec(m, None) => {
4535                 byte!(11);
4536                 mt(&mut state, m);
4537                 0u8.hash(&mut state);
4538             }
4539             ty_ptr(m) => {
4540                 byte!(12);
4541                 mt(&mut state, m);
4542             }
4543             ty_rptr(r, m) => {
4544                 byte!(13);
4545                 region(&mut state, r);
4546                 mt(&mut state, m);
4547             }
4548             ty_bare_fn(ref b) => {
4549                 byte!(14);
4550                 hash!(b.fn_style);
4551                 hash!(b.abi);
4552             }
4553             ty_closure(ref c) => {
4554                 byte!(15);
4555                 hash!(c.fn_style);
4556                 hash!(c.onceness);
4557                 hash!(c.bounds);
4558                 match c.store {
4559                     UniqTraitStore => byte!(0),
4560                     RegionTraitStore(r, m) => {
4561                         byte!(1)
4562                         region(&mut state, r);
4563                         assert_eq!(m, ast::MutMutable);
4564                     }
4565                 }
4566             }
4567             ty_trait(box ty::TyTrait { def_id: d, bounds, .. }) => {
4568                 byte!(17);
4569                 did(&mut state, d);
4570                 hash!(bounds);
4571             }
4572             ty_struct(d, _) => {
4573                 byte!(18);
4574                 did(&mut state, d);
4575             }
4576             ty_tup(ref inner) => {
4577                 byte!(19);
4578                 hash!(inner.len());
4579             }
4580             ty_param(p) => {
4581                 byte!(20);
4582                 hash!(p.idx);
4583                 did(&mut state, p.def_id);
4584             }
4585             ty_infer(_) => unreachable!(),
4586             ty_err => byte!(23),
4587         }
4588     });
4589
4590     state.result()
4591 }
4592
4593 impl Variance {
4594     pub fn to_str(self) -> &'static str {
4595         match self {
4596             Covariant => "+",
4597             Contravariant => "-",
4598             Invariant => "o",
4599             Bivariant => "*",
4600         }
4601     }
4602 }
4603
4604 pub fn construct_parameter_environment(
4605     tcx: &ctxt,
4606     generics: &ty::Generics,
4607     free_id: ast::NodeId)
4608     -> ParameterEnvironment
4609 {
4610     /*! See `ParameterEnvironment` struct def'n for details */
4611
4612     //
4613     // Construct the free substs.
4614     //
4615
4616     // map T => T
4617     let mut types = VecPerParamSpace::empty();
4618     for &space in subst::ParamSpace::all().iter() {
4619         push_types_from_defs(tcx, &mut types, space,
4620                              generics.types.get_vec(space));
4621     }
4622
4623     // map bound 'a => free 'a
4624     let mut regions = VecPerParamSpace::empty();
4625     for &space in subst::ParamSpace::all().iter() {
4626         push_region_params(&mut regions, space, free_id,
4627                            generics.regions.get_vec(space));
4628     }
4629
4630     let free_substs = Substs {
4631         types: types,
4632         regions: subst::NonerasedRegions(regions)
4633     };
4634
4635     //
4636     // Compute the bounds on Self and the type parameters.
4637     //
4638
4639     let mut bounds = VecPerParamSpace::empty();
4640     for &space in subst::ParamSpace::all().iter() {
4641         push_bounds_from_defs(tcx, &mut bounds, space, &free_substs,
4642                               generics.types.get_vec(space));
4643     }
4644
4645     debug!("construct_parameter_environment: free_id={} \
4646            free_subst={} \
4647            bounds={}",
4648            free_id,
4649            free_substs.repr(tcx),
4650            bounds.repr(tcx));
4651
4652     return ty::ParameterEnvironment {
4653         free_substs: free_substs,
4654         bounds: bounds
4655     };
4656
4657     fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
4658                           space: subst::ParamSpace,
4659                           free_id: ast::NodeId,
4660                           region_params: &Vec<RegionParameterDef>)
4661     {
4662         for r in region_params.iter() {
4663             regions.push(space, ty::free_region_from_def(free_id, r));
4664         }
4665     }
4666
4667     fn push_types_from_defs(tcx: &ty::ctxt,
4668                             types: &mut subst::VecPerParamSpace<ty::t>,
4669                             space: subst::ParamSpace,
4670                             defs: &Vec<TypeParameterDef>) {
4671         for (i, def) in defs.iter().enumerate() {
4672             let ty = ty::mk_param(tcx, space, i, def.def_id);
4673             types.push(space, ty);
4674         }
4675     }
4676
4677     fn push_bounds_from_defs(tcx: &ty::ctxt,
4678                              bounds: &mut subst::VecPerParamSpace<ParamBounds>,
4679                              space: subst::ParamSpace,
4680                              free_substs: &subst::Substs,
4681                              defs: &Vec<TypeParameterDef>) {
4682         for def in defs.iter() {
4683             let b = (*def.bounds).subst(tcx, free_substs);
4684             bounds.push(space, b);
4685         }
4686     }
4687 }
4688
4689 impl BorrowKind {
4690     pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
4691         match m {
4692             ast::MutMutable => MutBorrow,
4693             ast::MutImmutable => ImmBorrow,
4694         }
4695     }
4696
4697     pub fn to_user_str(&self) -> &'static str {
4698         match *self {
4699             MutBorrow => "mutable",
4700             ImmBorrow => "immutable",
4701             UniqueImmBorrow => "uniquely immutable",
4702         }
4703     }
4704 }
4705
4706 impl mc::Typer for ty::ctxt {
4707     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
4708         self
4709     }
4710
4711     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
4712         Ok(ty::node_id_to_type(self, id))
4713     }
4714
4715     fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t> {
4716         self.method_map.borrow().find(&method_call).map(|method| method.ty)
4717     }
4718
4719     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
4720         &self.adjustments
4721     }
4722
4723     fn is_method_call(&self, id: ast::NodeId) -> bool {
4724         self.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
4725     }
4726
4727     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
4728         self.region_maps.temporary_scope(rvalue_id)
4729     }
4730
4731     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
4732         self.upvar_borrow_map.borrow().get_copy(&upvar_id)
4733     }
4734 }