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