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