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