ty.rs 140.0 KB
Newer Older
1
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 3 4 5 6 7 8 9 10
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11

P
Patrick Walton 已提交
12 13
use driver::session;
use metadata::csearch;
14 15 16
use metadata;
use middle::const_eval;
use middle::freevars;
P
Patrick Walton 已提交
17
use middle::lint::{get_lint_level, allow};
18 19 20 21
use middle::lint;
use middle::resolve::{Impl, MethodInfo};
use middle::resolve;
use middle::ty;
22
use middle::subst::Subst;
23 24 25
use middle::typeck;
use middle;
use util::ppaux::{note_and_explain_region, bound_region_to_str};
26
use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
27
use util::ppaux::Repr;
28
use util::common::{indenter};
29
use util::enum_set::{EnumSet, CLike};
30

31 32
#[cfg(stage0)]
use core; // NOTE: this can be removed after the next snapshot
33
use core::ptr::to_unsafe_ptr;
34
use core::to_bytes;
35
use core::hashmap::{HashMap, HashSet};
D
Daniel Micay 已提交
36
use std::smallintmap::SmallIntMap;
P
Patrick Walton 已提交
37
use syntax::ast::*;
T
Tim Chevalier 已提交
38
use syntax::ast_util::is_local;
39
use syntax::ast_util;
40
use syntax::attr;
41
use syntax::codemap::span;
J
John Clements 已提交
42
use syntax::codemap;
43
use syntax::parse::token::special_idents;
44
use syntax::{ast, ast_map};
45 46
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
47
use syntax::abi::AbiSet;
48
use syntax;
49

50
// Data types
51

52
#[deriving(Eq, IterBytes)]
53
pub struct arg {
54 55
    ty: t
}
56

57
#[deriving(Eq)]
58
pub struct field {
59 60 61
    ident: ast::ident,
    mt: mt
}
62

63
pub struct method {
64
    ident: ast::ident,
65
    generics: ty::Generics,
66
    transformed_self_ty: Option<ty::t>,
67
    fty: BareFnTy,
68 69 70
    self_ty: ast::self_ty_,
    vis: ast::visibility,
    def_id: ast::def_id
71
}
72

73
#[deriving(Eq)]
74
pub struct mt {
75 76 77
    ty: t,
    mutbl: ast::mutability,
}
78

79 80
#[auto_encode]
#[auto_decode]
81
#[deriving(Eq)]
82
pub enum vstore {
83 84 85
    vstore_fixed(uint),
    vstore_uniq,
    vstore_box,
86
    vstore_slice(Region)
87 88
}

89 90
#[auto_encode]
#[auto_decode]
91
#[deriving(Eq, IterBytes)]
92 93 94 95 96 97
pub enum TraitStore {
    BoxTraitStore,              // @Trait
    UniqTraitStore,             // ~Trait
    RegionTraitStore(Region),   // &Trait
}

98 99 100 101 102 103 104 105 106 107
// XXX: This should probably go away at some point. Maybe after destructors
// do?
#[auto_encode]
#[auto_decode]
#[deriving(Eq)]
pub enum SelfMode {
    ByCopy,
    ByRef,
}

108
pub struct field_ty {
109 110 111
    ident: ident,
    id: def_id,
    vis: ast::visibility,
112
}
T
Tim Chevalier 已提交
113

114 115
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
116
#[deriving(Eq)]
117
pub struct creader_cache_key {
118 119 120
    cnum: int,
    pos: uint,
    len: uint
121
}
122

123
type creader_cache = @mut HashMap<creader_cache_key, t>;
124

125
#[cfg(stage0)]
126
impl to_bytes::IterBytes for creader_cache_key {
127
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
128 129 130
        to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f);
    }
}
131 132 133 134 135 136
#[cfg(not(stage0))]
impl to_bytes::IterBytes for creader_cache_key {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f)
    }
}
137

138 139 140
struct intern_key {
    sty: *sty,
}
141

142
// NB: Do not replace this with #[deriving(Eq)]. The automatically-derived
143 144
// implementation will not recurse through sty and you will get stack
// exhaustion.
145
impl cmp::Eq for intern_key {
146
    fn eq(&self, other: &intern_key) -> bool {
147
        unsafe {
148
            *self.sty == *other.sty
149
        }
150
    }
151
    fn ne(&self, other: &intern_key) -> bool {
152 153
        !self.eq(other)
    }
154
}
155

156
#[cfg(stage0)]
157
impl to_bytes::IterBytes for intern_key {
158
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
159
        unsafe {
160
            (*self.sty).iter_bytes(lsb0, f);
161
        }
162 163
    }
}
164 165 166 167 168 169 170 171
#[cfg(not(stage0))]
impl to_bytes::IterBytes for intern_key {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        unsafe {
            (*self.sty).iter_bytes(lsb0, f)
        }
    }
}
172

173
pub enum ast_ty_to_ty_cache_entry {
174
    atttce_unresolved,  /* not resolved yet */
175
    atttce_resolved(t)  /* resolved to a type, irrespective of region */
176 177
}

178
pub type opt_region_variance = Option<region_variance>;
179

180 181
#[auto_encode]
#[auto_decode]
182
#[deriving(Eq)]
183
pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant }
184

185 186
#[auto_encode]
#[auto_decode]
187 188 189 190 191 192 193 194
pub enum AutoAdjustment {
    AutoAddEnv(ty::Region, ast::Sigil),
    AutoDerefRef(AutoDerefRef)
}

#[auto_encode]
#[auto_decode]
pub struct AutoDerefRef {
195 196
    autoderefs: uint,
    autoref: Option<AutoRef>
197
}
198

199 200
#[auto_encode]
#[auto_decode]
N
Niko Matsakis 已提交
201
pub enum AutoRef {
202
    /// Convert from T to &T
N
Niko Matsakis 已提交
203
    AutoPtr(Region, ast::mutability),
204

205
    /// Convert from @[]/~[]/&[] to &[] (or str)
N
Niko Matsakis 已提交
206
    AutoBorrowVec(Region, ast::mutability),
207

208
    /// Convert from @[]/~[]/&[] to &&[] (or str)
N
Niko Matsakis 已提交
209
    AutoBorrowVecRef(Region, ast::mutability),
210

211
    /// Convert from @fn()/~fn()/&fn() to &fn()
N
Niko Matsakis 已提交
212 213 214 215
    AutoBorrowFn(Region),

    /// Convert from T to *T
    AutoUnsafe(ast::mutability)
216 217
}

218 219 220 221 222 223
// Stores information about provided methods (a.k.a. default methods) in
// implementations.
//
// This is a map from ID of each implementation to the method info and trait
// method ID of each of the default methods belonging to the trait that that
// implementation implements.
224
pub type ProvidedMethodsMap = @mut HashMap<def_id,@mut ~[@ProvidedMethodInfo]>;
225 226 227

// Stores the method info and definition ID of the associated trait method for
// each instantiation of each provided method.
228
pub struct ProvidedMethodInfo {
229 230 231 232
    method_info: @MethodInfo,
    trait_method_def_id: def_id
}

233
pub struct ProvidedMethodSource {
234 235 236 237
    method_id: ast::def_id,
    impl_id: ast::def_id
}

238 239 240
pub type ctxt = @ctxt_;

struct ctxt_ {
241
    diag: @syntax::diagnostic::span_handler,
242
    interner: @mut HashMap<intern_key, ~t_box_>,
243
    next_id: @mut uint,
244 245
    vecs_implicitly_copyable: bool,
    legacy_modes: bool,
246
    cstore: @mut metadata::cstore::CStore,
247 248 249
    sess: session::Session,
    def_map: resolve::DefMap,

250
    region_maps: @mut middle::region::RegionMaps,
251 252 253 254 255 256 257 258 259 260 261
    region_paramd_items: middle::region::region_paramd_items,

    // Stores the types for various nodes in the AST.  Note that this table
    // is not guaranteed to be populated until after typeck.  See
    // typeck::check::fn_ctxt for details.
    node_types: node_type_table,

    // Stores the type parameters which were substituted to obtain the type
    // of this node.  This only applies to nodes that refer to entities
    // parameterized by type parameters, such as generic fns, types, or
    // other items.
262
    node_type_substs: @mut HashMap<node_id, ~[t]>,
263

264 265 266 267 268 269 270 271 272
    // Maps from a method to the method "descriptor"
    methods: @mut HashMap<def_id, @method>,

    // Maps from a trait def-id to a list of the def-ids of its methods
    trait_method_def_ids: @mut HashMap<def_id, @~[def_id]>,

    // A cache for the trait_methods() routine
    trait_methods_cache: @mut HashMap<def_id, @~[@method]>,

273 274 275
    trait_refs: @mut HashMap<node_id, @TraitRef>,
    trait_defs: @mut HashMap<def_id, @TraitDef>,

276
    items: ast_map::map,
277
    intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
278
    intrinsic_traits: @mut HashMap<ast::ident, @TraitRef>,
279 280 281 282
    freevars: freevars::freevar_map,
    tcache: type_cache,
    rcache: creader_cache,
    ccache: constness_cache,
283 284 285 286 287
    short_names_cache: @mut HashMap<t, @~str>,
    needs_unwind_cleanup_cache: @mut HashMap<t, bool>,
    tc_cache: @mut HashMap<uint, TypeContents>,
    ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
    enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
288
    ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
289 290
    adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
    normalized_cache: @mut HashMap<t, t>,
291 292 293 294 295
    lang_items: middle::lang_items::LanguageItems,
    // A mapping from an implementation ID to the method info and trait
    // method ID of the provided (a.k.a. default) methods in the traits that
    // that implementation implements.
    provided_methods: ProvidedMethodsMap,
296
    provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>,
297
    supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
298 299 300 301 302

    // A mapping from the def ID of an enum or struct type to the def ID
    // of the method that implements its destructor. If the type is not
    // present in this map, it does not have a destructor. This map is
    // populated during the coherence phase of typechecking.
303
    destructor_for_type: @mut HashMap<ast::def_id, ast::def_id>,
304 305

    // A method will be in this list if and only if it is a destructor.
306
    destructors: @mut HashSet<ast::def_id>,
307 308

    // Maps a trait onto a mapping from self-ty to impl
309 310 311 312 313
    trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @Impl>>,

    // Set of used unsafe nodes (functions or blocks). Unsafe nodes not
    // present in this set can be warned about.
    used_unsafe: @mut HashSet<ast::node_id>,
314 315 316 317 318

    // Set of nodes which mark locals as mutable which end up getting used at
    // some point. Local variable definitions not in this set can be warned
    // about.
    used_mut_nodes: @mut HashSet<ast::node_id>,
319
}
320

321
pub enum tbox_flag {
322 323 324 325
    has_params = 1,
    has_self = 2,
    needs_infer = 4,
    has_regions = 8,
326
    has_ty_err = 16,
T
Tim Chevalier 已提交
327
    has_ty_bot = 32,
328 329 330 331 332 333

    // a meta-flag: subst may be required if the type has parameters, a self
    // type, or references bound regions
    needs_subst = 1 | 2 | 8
}

334
pub type t_box = &'static t_box_;
335

336
pub struct t_box_ {
337 338 339 340
    sty: sty,
    id: uint,
    flags: uint,
}
341

342 343 344 345 346 347
// To reduce refcounting cost, we're representing types as unsafe pointers
// throughout the compiler. These are simply casted t_box values. Use ty::get
// to cast them back to a box. (Without the cast, compiler performance suffers
// ~15%.) This does mean that a t value relies on the ctxt to keep its box
// alive, and using ty::get is unsafe when the ctxt is no longer alive.
enum t_opaque {}
348
pub type t = *t_opaque;
349

350
pub fn get(t: t) -> t_box {
351
    unsafe {
352 353
        let t2: t_box = cast::transmute(t);
        t2
354
    }
355 356
}

357
pub fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
358 359
    (tb.flags & (flag as uint)) != 0u
}
360
pub fn type_has_params(t: t) -> bool {
P
Patrick Walton 已提交
361 362
    tbox_has_flag(get(t), has_params)
}
363 364
pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
pub fn type_needs_infer(t: t) -> bool {
365 366
    tbox_has_flag(get(t), needs_infer)
}
367
pub fn type_has_regions(t: t) -> bool {
368 369
    tbox_has_flag(get(t), has_regions)
}
370
pub fn type_id(t: t) -> uint { get(t).id }
371

372
#[deriving(Eq)]
373 374
pub struct BareFnTy {
    purity: ast::purity,
375
    abis: AbiSet,
376 377 378
    sig: FnSig
}

379
#[deriving(Eq)]
380
pub struct ClosureTy {
381
    purity: ast::purity,
382
    sigil: ast::Sigil,
383
    onceness: ast::Onceness,
384
    region: Region,
385
    sig: FnSig
386 387 388 389 390 391
}

/**
 * Signature of a function type, which I have arbitrarily
 * decided to use to refer to the input/output types.
 *
392
 * - `lifetimes` is the list of region names bound in this fn.
393 394
 * - `inputs` is the list of arguments and their modes.
 * - `output` is the return type. */
395
#[deriving(Eq)]
396
pub struct FnSig {
397
    bound_lifetime_names: OptVec<ast::ident>,
398 399
    inputs: ~[arg],
    output: t
400 401
}

402
#[cfg(stage0)]
403
impl to_bytes::IterBytes for BareFnTy {
404
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
405
        to_bytes::iter_bytes_3(&self.purity, &self.abis, &self.sig, lsb0, f)
406
    }
407
}
408 409 410 411 412 413
#[cfg(not(stage0))]
impl to_bytes::IterBytes for BareFnTy {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        to_bytes::iter_bytes_3(&self.purity, &self.abis, &self.sig, lsb0, f)
    }
}
414

415
#[cfg(stage0)]
416
impl to_bytes::IterBytes for ClosureTy {
417
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
418 419
        to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness,
                               &self.region, &self.sig, lsb0, f)
420
    }
421
}
422 423 424 425 426 427 428
#[cfg(not(stage0))]
impl to_bytes::IterBytes for ClosureTy {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness,
                               &self.region, &self.sig, lsb0, f)
    }
}
429

430
#[deriving(Eq, IterBytes)]
431
pub struct param_ty {
432 433
    idx: uint,
    def_id: def_id
434
}
435

436
/// Representation of regions:
437 438
#[auto_encode]
#[auto_decode]
439
#[deriving(Eq, IterBytes)]
440
pub enum Region {
441 442 443 444 445 446 447 448 449
    /// Bound regions are found (primarily) in function types.  They indicate
    /// region parameters that have yet to be replaced with actual regions
    /// (analogous to type parameters, except that due to the monomorphic
    /// nature of our type system, bound type parameters are always replaced
    /// with fresh type variables whenever an item is referenced, so type
    /// parameters only appear "free" in types.  Regions in contrast can
    /// appear free or bound.).  When a function is called, all bound regions
    /// tied to that function's node-id are replaced with fresh region
    /// variables whose value is then inferred.
N
Niko Matsakis 已提交
450
    re_bound(bound_region),
451 452 453 454

    /// When checking a function body, the types of all arguments and so forth
    /// that refer to bound region parameters are modified to refer to free
    /// region parameters.
455
    re_free(FreeRegion),
456 457

    /// A concrete region naming some expression within the current function.
N
Niko Matsakis 已提交
458
    re_scope(node_id),
459

N
Niko Matsakis 已提交
460
    /// Static data that has an "infinite" lifetime. Top in the region lattice.
461 462 463
    re_static,

    /// A region variable.  Should not exist after typeck.
N
Niko Matsakis 已提交
464 465 466 467 468 469 470 471 472 473
    re_infer(InferRegion),

    /// Empty lifetime is for data that is never accessed.
    /// Bottom in the region lattice. We treat re_empty somewhat
    /// specially; at least right now, we do not generate instances of
    /// it during the GLB computations, but rather
    /// generate an error instead. This is to improve error messages.
    /// The only way to get an instance of re_empty is to have a region
    /// variable with no constraints.
    re_empty,
N
Niko Matsakis 已提交
474 475
}

476 477 478 479 480 481 482 483 484
pub impl Region {
    fn is_bound(&self) -> bool {
        match self {
            &re_bound(*) => true,
            _ => false
        }
    }
}

485 486
#[auto_encode]
#[auto_decode]
487 488 489 490 491 492 493 494 495
#[deriving(Eq, IterBytes)]
pub struct FreeRegion {
    scope_id: node_id,
    bound_region: bound_region
}

#[auto_encode]
#[auto_decode]
#[deriving(Eq, IterBytes)]
496
pub enum bound_region {
497
    /// The self region for structs, impls (&T in a type defn or &'self T)
498 499
    br_self,

500 501
    /// An anonymous region parameter for a given fn (&T)
    br_anon(uint),
502

503
    /// Named region parameters for functions (a in &'a T)
504 505
    br_named(ast::ident),

506 507 508
    /// Fresh bound identifiers created during GLB computations.
    br_fresh(uint),

509 510 511 512 513 514 515 516 517
    /**
     * Handles capture-avoiding substitution in a rather subtle case.  If you
     * have a closure whose argument types are being inferred based on the
     * expected type, and the expected type includes bound regions, then we
     * will wrap those bound regions in a br_cap_avoid() with the id of the
     * fn expression.  This ensures that the names are not "captured" by the
     * enclosing scope, which may define the same names.  For an example of
     * where this comes up, see src/test/compile-fail/regions-ret-borrowed.rs
     * and regions-ret-borrowed-1.rs. */
518
    br_cap_avoid(ast::node_id, @bound_region),
519 520
}

521
type opt_region = Option<Region>;
522

523 524 525 526 527 528 529 530 531
/**
 * The type substs represents the kinds of things that can be substituted to
 * convert a polytype into a monotype.  Note however that substituting bound
 * regions other than `self` is done through a different mechanism:
 *
 * - `tps` represents the type parameters in scope.  They are indexed
 *   according to the order in which they were declared.
 *
 * - `self_r` indicates the region parameter `self` that is present on nominal
532
 *   types (enums, structs) declared as having a region parameter.  `self_r`
533 534 535 536 537 538 539
 *   should always be none for types that are not region-parameterized and
 *   Some(_) for types that are.  The only bound region parameter that should
 *   appear within a region-parameterized type is `self`.
 *
 * - `self_ty` is the type to which `self` should be remapped, if any.  The
 *   `self` type is rather funny in that it can only appear on traits and is
 *   always substituted away to the implementing type for a trait. */
540
#[deriving(Eq)]
541
pub struct substs {
542
    self_r: opt_region,
B
Brian Anderson 已提交
543
    self_ty: Option<ty::t>,
544
    tps: ~[t]
545
}
546

547
mod primitives {
548
    use super::t_box_;
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593

    use syntax::ast;

    macro_rules! def_prim_ty(
        ($name:ident, $sty:expr, $id:expr) => (
            pub static $name: t_box_ = t_box_ {
                sty: $sty,
                id: $id,
                flags: 0,
            };
        )
    )

    def_prim_ty!(TY_NIL,    super::ty_nil,                  0)
    def_prim_ty!(TY_BOOL,   super::ty_bool,                 1)
    def_prim_ty!(TY_INT,    super::ty_int(ast::ty_i),       2)
    def_prim_ty!(TY_CHAR,   super::ty_int(ast::ty_char),    3)
    def_prim_ty!(TY_I8,     super::ty_int(ast::ty_i8),      4)
    def_prim_ty!(TY_I16,    super::ty_int(ast::ty_i16),     5)
    def_prim_ty!(TY_I32,    super::ty_int(ast::ty_i32),     6)
    def_prim_ty!(TY_I64,    super::ty_int(ast::ty_i64),     7)
    def_prim_ty!(TY_UINT,   super::ty_uint(ast::ty_u),      8)
    def_prim_ty!(TY_U8,     super::ty_uint(ast::ty_u8),     9)
    def_prim_ty!(TY_U16,    super::ty_uint(ast::ty_u16),    10)
    def_prim_ty!(TY_U32,    super::ty_uint(ast::ty_u32),    11)
    def_prim_ty!(TY_U64,    super::ty_uint(ast::ty_u64),    12)
    def_prim_ty!(TY_FLOAT,  super::ty_float(ast::ty_f),     13)
    def_prim_ty!(TY_F32,    super::ty_float(ast::ty_f32),   14)
    def_prim_ty!(TY_F64,    super::ty_float(ast::ty_f64),   15)

    pub static TY_BOT: t_box_ = t_box_ {
        sty: super::ty_bot,
        id: 16,
        flags: super::has_ty_bot as uint,
    };

    pub static TY_ERR: t_box_ = t_box_ {
        sty: super::ty_err,
        id: 17,
        flags: super::has_ty_err as uint,
    };

    pub static LAST_PRIMITIVE_ID: uint = 18;
}

594
// NB: If you change this, you'll probably want to change the corresponding
595
// AST structure in libsyntax/ast.rs as well.
596
#[deriving(Eq)]
597
pub enum sty {
P
Patrick Walton 已提交
598 599 600 601 602 603
    ty_nil,
    ty_bot,
    ty_bool,
    ty_int(ast::int_ty),
    ty_uint(ast::uint_ty),
    ty_float(ast::float_ty),
604
    ty_estr(vstore),
605
    ty_enum(def_id, substs),
P
Patrick Walton 已提交
606 607
    ty_box(mt),
    ty_uniq(mt),
608
    ty_evec(mt, vstore),
P
Patrick Walton 已提交
609
    ty_ptr(mt),
610
    ty_rptr(Region, mt),
611 612
    ty_bare_fn(BareFnTy),
    ty_closure(ClosureTy),
613
    ty_trait(def_id, substs, TraitStore, ast::mutability),
614
    ty_struct(def_id, substs),
615
    ty_tup(~[t]),
P
Patrick Walton 已提交
616

617
    ty_param(param_ty), // type parameter
618 619
    ty_self(def_id), /* special, implicit `self` type parameter;
                      * def_id is the id of the trait */
P
Patrick Walton 已提交
620

621
    ty_infer(InferTy), // something used only during inference/typeck
622 623 624
    ty_err, // Also only used during inference/typeck, to represent
            // the type of an erroneous expression (helps cut down
            // on non-useful type error messages)
625

M
Michael Sullivan 已提交
626
    // "Fake" types, used for trans purposes
P
Patrick Walton 已提交
627
    ty_type, // type_desc*
628
    ty_opaque_box, // used by monomorphizer to represent any @ box
629
    ty_opaque_closure_ptr(Sigil), // ptr to env for &fn, @fn, ~fn
M
Michael Sullivan 已提交
630
    ty_unboxed_vec(mt),
631 632
}

633 634 635 636 637 638
#[deriving(Eq, IterBytes)]
pub struct TraitRef {
    def_id: def_id,
    substs: substs
}

639
#[deriving(Eq)]
640
pub enum IntVarValue {
641 642 643 644
    IntType(ast::int_ty),
    UintType(ast::uint_ty),
}

645
pub enum terr_vstore_kind {
646
    terr_vec, terr_str, terr_fn, terr_trait
647 648
}

649
pub struct expected_found<T> {
650 651
    expected: T,
    found: T
652 653
}

654
// Data structures used in type unification
655
pub enum type_err {
P
Patrick Walton 已提交
656
    terr_mismatch,
657
    terr_purity_mismatch(expected_found<purity>),
658
    terr_onceness_mismatch(expected_found<Onceness>),
659
    terr_abi_mismatch(expected_found<AbiSet>),
660
    terr_mutability,
661
    terr_sigil_mismatch(expected_found<ast::Sigil>),
P
Patrick Walton 已提交
662
    terr_box_mutability,
M
Marijn Haverbeke 已提交
663
    terr_ptr_mutability,
664
    terr_ref_mutability,
P
Patrick Walton 已提交
665
    terr_vec_mutability,
666 667 668
    terr_tuple_size(expected_found<uint>),
    terr_ty_param_size(expected_found<uint>),
    terr_record_size(expected_found<uint>),
P
Patrick Walton 已提交
669
    terr_record_mutability,
670
    terr_record_fields(expected_found<ident>),
P
Patrick Walton 已提交
671
    terr_arg_count,
672 673 674
    terr_regions_does_not_outlive(Region, Region),
    terr_regions_not_same(Region, Region),
    terr_regions_no_overlap(Region, Region),
675 676
    terr_regions_insufficiently_polymorphic(bound_region, Region),
    terr_regions_overly_polymorphic(bound_region, Region),
677
    terr_vstores_differ(terr_vstore_kind, expected_found<vstore>),
678
    terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
B
Brian Anderson 已提交
679
    terr_in_field(@type_err, ast::ident),
680
    terr_sorts(expected_found<t>),
681
    terr_self_substs,
682
    terr_integer_as_char,
683
    terr_int_mismatch(expected_found<IntVarValue>),
684 685
    terr_float_mismatch(expected_found<ast::float_ty>),
    terr_traits(expected_found<ast::def_id>),
686 687
}

688
#[deriving(Eq, IterBytes)]
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714
pub struct ParamBounds {
    builtin_bounds: BuiltinBounds,
    trait_bounds: ~[@TraitRef]
}

pub type BuiltinBounds = EnumSet<BuiltinBound>;

#[deriving(Eq, IterBytes)]
pub enum BuiltinBound {
    BoundCopy,
    BoundStatic,
    BoundOwned,
    BoundConst,
}

pub fn EmptyBuiltinBounds() -> BuiltinBounds {
    EnumSet::empty()
}

impl CLike for BuiltinBound {
    pub fn to_uint(&self) -> uint {
        *self as uint
    }
    pub fn from_uint(v: uint) -> BuiltinBound {
        unsafe { cast::transmute(v) }
    }
715 716
}

717
#[deriving(Eq)]
718
pub struct TyVid(uint);
719

720
#[deriving(Eq)]
721
pub struct IntVid(uint);
722

723
#[deriving(Eq)]
724
pub struct FloatVid(uint);
725

726
#[deriving(Eq)]
727 728
#[auto_encode]
#[auto_decode]
729 730 731
pub struct RegionVid {
    id: uint
}
N
Niko Matsakis 已提交
732

733
#[deriving(Eq)]
734
pub enum InferTy {
735
    TyVar(TyVid),
736 737
    IntVar(IntVid),
    FloatVar(FloatVid)
738 739
}

740
#[cfg(stage0)]
741
impl to_bytes::IterBytes for InferTy {
742
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
743 744 745
        match *self {
          TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
          IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f),
746
          FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f),
747 748 749
        }
    }
}
750 751 752 753 754 755 756 757 758 759
#[cfg(not(stage0))]
impl to_bytes::IterBytes for InferTy {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
          TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
          IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f),
          FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f),
        }
    }
}
760

761 762
#[auto_encode]
#[auto_decode]
763
pub enum InferRegion {
764 765 766 767
    ReVar(RegionVid),
    ReSkolemized(uint, bound_region)
}

768
#[cfg(stage0)]
769
impl to_bytes::IterBytes for InferRegion {
770
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
771 772 773 774 775 776
        match *self {
            ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f),
            ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f)
        }
    }
}
777 778 779 780 781 782 783 784 785
#[cfg(not(stage0))]
impl to_bytes::IterBytes for InferRegion {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
            ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f),
            ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f)
        }
    }
}
786

787
impl cmp::Eq for InferRegion {
788
    fn eq(&self, other: &InferRegion) -> bool {
789 790 791 792 793 794 795 796 797 798
        match ((*self), *other) {
            (ReVar(rva), ReVar(rvb)) => {
                rva == rvb
            }
            (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
                rva == rvb
            }
            _ => false
        }
    }
799
    fn ne(&self, other: &InferRegion) -> bool {
800 801
        !((*self) == (*other))
    }
802 803
}

804
pub trait Vid {
805
    fn to_uint(&self) -> uint;
N
Niko Matsakis 已提交
806 807
}

808
impl Vid for TyVid {
809
    fn to_uint(&self) -> uint { **self }
810 811
}

812
impl ToStr for TyVid {
813
    fn to_str(&self) -> ~str { fmt!("<V%u>", self.to_uint()) }
N
Niko Matsakis 已提交
814 815
}

816
impl Vid for IntVid {
817
    fn to_uint(&self) -> uint { **self }
818 819
}

820
impl ToStr for IntVid {
821
    fn to_str(&self) -> ~str { fmt!("<VI%u>", self.to_uint()) }
822 823
}

824
impl Vid for FloatVid {
825
    fn to_uint(&self) -> uint { **self }
826 827
}

828
impl ToStr for FloatVid {
829
    fn to_str(&self) -> ~str { fmt!("<VF%u>", self.to_uint()) }
830 831
}

832
impl Vid for RegionVid {
833
    fn to_uint(&self) -> uint { self.id }
N
Niko Matsakis 已提交
834 835
}

836
impl ToStr for RegionVid {
837
    fn to_str(&self) -> ~str { fmt!("%?", self.id) }
838
}
839

840
impl ToStr for FnSig {
841
    fn to_str(&self) -> ~str {
842 843
        // grr, without tcx not much we can do.
        return ~"(...)";
844 845 846
    }
}

847
impl ToStr for InferTy {
848
    fn to_str(&self) -> ~str {
849
        match *self {
850 851 852 853
            TyVar(ref v) => v.to_str(),
            IntVar(ref v) => v.to_str(),
            FloatVar(ref v) => v.to_str()
        }
N
Niko Matsakis 已提交
854 855 856
    }
}

857
impl ToStr for IntVarValue {
858
    fn to_str(&self) -> ~str {
859
        match *self {
860 861 862
            IntType(ref v) => v.to_str(),
            UintType(ref v) => v.to_str(),
        }
863 864
    }
}
865

866
#[cfg(stage0)]
867
impl to_bytes::IterBytes for TyVid {
868
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
869
        self.to_uint().iter_bytes(lsb0, f)
870 871
    }
}
872 873 874 875 876 877
#[cfg(not(stage0))]
impl to_bytes::IterBytes for TyVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
878

879
#[cfg(stage0)]
880
impl to_bytes::IterBytes for IntVid {
881
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
882
        self.to_uint().iter_bytes(lsb0, f)
883 884
    }
}
885 886 887 888 889 890
#[cfg(not(stage0))]
impl to_bytes::IterBytes for IntVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
891

892
#[cfg(stage0)]
893
impl to_bytes::IterBytes for FloatVid {
894
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
895
        self.to_uint().iter_bytes(lsb0, f)
896 897
    }
}
898 899 900 901 902 903
#[cfg(not(stage0))]
impl to_bytes::IterBytes for FloatVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
904

905
#[cfg(stage0)]
906
impl to_bytes::IterBytes for RegionVid {
907
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
908
        self.to_uint().iter_bytes(lsb0, f)
909 910
    }
}
911 912 913 914 915 916
#[cfg(not(stage0))]
impl to_bytes::IterBytes for RegionVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
917

918 919
pub struct TypeParameterDef {
    def_id: ast::def_id,
920
    bounds: @ParamBounds
921 922
}

923 924 925
/// Information about the type/lifetime parametesr associated with an item.
/// Analogous to ast::Generics.
pub struct Generics {
926
    type_param_defs: @~[TypeParameterDef],
927 928 929
    region_param: Option<region_variance>,
}

930 931 932 933 934 935
pub impl Generics {
    fn has_type_params(&self) -> bool {
        !self.type_param_defs.is_empty()
    }
}

936 937 938 939 940 941 942 943 944 945
/// A polytype.
///
/// - `bounds`: The list of bounds for each type parameter.  The length of the
///   list also tells you how many type parameters there are.
///
/// - `rp`: true if the type is region-parameterized.  Types can have at
///   most one region parameter, always called `&self`.
///
/// - `ty`: the base type.  May have reference to the (unsubstituted) bound
///   region `&self` or to (unsubstituted) ty_param types
946
pub struct ty_param_bounds_and_ty {
947
    generics: Generics,
948 949
    ty: t
}
950

951 952 953 954 955 956
/// As `ty_param_bounds_and_ty` but for a trait ref.
pub struct TraitDef {
    generics: Generics,
    trait_ref: @ty::TraitRef,
}

957 958 959 960
pub struct ty_param_substs_and_ty {
    substs: ty::substs,
    ty: ty::t
}
961

962
type type_cache = @mut HashMap<ast::def_id, ty_param_bounds_and_ty>;
963

964
type constness_cache = @mut HashMap<ast::def_id, const_eval::constness>;
965

D
Daniel Micay 已提交
966
pub type node_type_table = @mut SmallIntMap<t>;
967

968
fn mk_rcache() -> creader_cache {
969
    return @mut HashMap::new();
970
}
971

972 973
pub fn new_ty_hash<V:Copy>() -> @mut HashMap<t, V> {
    @mut HashMap::new()
974
}
975

976 977 978 979
pub fn mk_ctxt(s: session::Session,
               dm: resolve::DefMap,
               amap: ast_map::map,
               freevars: freevars::freevar_map,
980
               region_maps: @mut middle::region::RegionMaps,
981
               region_paramd_items: middle::region::region_paramd_items,
982
               lang_items: middle::lang_items::LanguageItems,
983 984
               crate: @ast::crate)
            -> ctxt {
985 986 987
    let mut legacy_modes = false;
    for crate.node.attrs.each |attribute| {
        match attribute.node.value.node {
988
            ast::meta_word(w) if *w == ~"legacy_modes" => {
989 990 991 992 993 994
                legacy_modes = true;
            }
            _ => {}
        }
    }

995
    let vecs_implicitly_copyable =
996 997
        get_lint_level(s.lint_settings.default_settings,
                       lint::vecs_implicitly_copyable) == allow;
998 999
    @ctxt_ {
        diag: s.diagnostic(),
1000
        interner: @mut HashMap::new(),
1001
        next_id: @mut primitives::LAST_PRIMITIVE_ID,
1002 1003 1004 1005 1006
        vecs_implicitly_copyable: vecs_implicitly_copyable,
        legacy_modes: legacy_modes,
        cstore: s.cstore,
        sess: s,
        def_map: dm,
1007
        region_maps: region_maps,
1008
        region_paramd_items: region_paramd_items,
D
Daniel Micay 已提交
1009
        node_types: @mut SmallIntMap::new(),
1010
        node_type_substs: @mut HashMap::new(),
1011 1012 1013
        trait_refs: @mut HashMap::new(),
        trait_defs: @mut HashMap::new(),
        intrinsic_traits: @mut HashMap::new(),
1014
        items: amap,
1015
        intrinsic_defs: @mut HashMap::new(),
1016
        freevars: freevars,
1017
        tcache: @mut HashMap::new(),
1018
        rcache: mk_rcache(),
1019
        ccache: @mut HashMap::new(),
1020 1021
        short_names_cache: new_ty_hash(),
        needs_unwind_cleanup_cache: new_ty_hash(),
1022 1023 1024
        tc_cache: @mut HashMap::new(),
        ast_ty_to_ty_cache: @mut HashMap::new(),
        enum_var_cache: @mut HashMap::new(),
1025 1026 1027
        methods: @mut HashMap::new(),
        trait_method_def_ids: @mut HashMap::new(),
        trait_methods_cache: @mut HashMap::new(),
1028
        ty_param_defs: @mut HashMap::new(),
1029
        adjustments: @mut HashMap::new(),
1030
        normalized_cache: new_ty_hash(),
L
Luqman Aden 已提交
1031
        lang_items: lang_items,
1032 1033 1034 1035 1036
        provided_methods: @mut HashMap::new(),
        provided_method_sources: @mut HashMap::new(),
        supertraits: @mut HashMap::new(),
        destructor_for_type: @mut HashMap::new(),
        destructors: @mut HashSet::new(),
1037 1038
        trait_impls: @mut HashMap::new(),
        used_unsafe: @mut HashSet::new(),
1039
        used_mut_nodes: @mut HashSet::new(),
1040
     }
1041
}
1042

1043
// Type constructors
1044 1045 1046

// Interns a type/name combination, stores the resulting box in cx.interner,
// and returns the box as cast to an unsafe ptr (see comments for t above).
1047
fn mk_t(cx: ctxt, st: sty) -> t {
1048 1049
    // Check for primitive types.
    match st {
T
Tim Chevalier 已提交
1050 1051 1052 1053 1054 1055
        ty_nil => return mk_nil(),
        ty_err => return mk_err(),
        ty_bool => return mk_bool(),
        ty_int(i) => return mk_mach_int(i),
        ty_uint(u) => return mk_mach_uint(u),
        ty_float(f) => return mk_mach_float(f),
1056 1057 1058
        _ => {}
    };

1059
    let key = intern_key { sty: to_unsafe_ptr(&st) };
1060
    match cx.interner.find(&key) {
1061
      Some(t) => unsafe { return cast::transmute(&t.sty); },
B
Brian Anderson 已提交
1062
      _ => ()
1063
    }
1064

1065
    let mut flags = 0u;
1066
    fn rflags(r: Region) -> uint {
1067
        (has_regions as uint) | {
1068
            match r {
1069
              ty::re_infer(_) => needs_infer as uint,
B
Brian Anderson 已提交
1070
              _ => 0u
1071
            }
N
Niko Matsakis 已提交
1072 1073
        }
    }
N
Niko Matsakis 已提交
1074
    fn sflags(substs: &substs) -> uint {
1075
        let mut f = 0u;
1076
        for substs.tps.each |tt| { f |= get(*tt).flags; }
1077
        for substs.self_r.each |r| { f |= rflags(*r) }
B
Brian Anderson 已提交
1078
        return f;
N
Niko Matsakis 已提交
1079
    }
1080 1081
    match &st {
      &ty_estr(vstore_slice(r)) => {
1082
        flags |= rflags(r);
1083
      }
1084
      &ty_evec(ref mt, vstore_slice(r)) => {
1085 1086
        flags |= rflags(r);
        flags |= get(mt.ty).flags;
1087
      }
T
Tim Chevalier 已提交
1088
      &ty_nil | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
1089
      &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
1090
      &ty_opaque_box => (),
T
Tim Chevalier 已提交
1091 1092 1093 1094 1095 1096 1097 1098
      // You might think that we could just return ty_err for
      // any type containing ty_err as a component, and get
      // rid of the has_ty_err flag -- likewise for ty_bot (with
      // the exception of function types that return bot).
      // But doing so caused sporadic memory corruption, and
      // neither I (tjc) nor nmatsakis could figure out why,
      // so we're doing it this way.
      &ty_bot => flags |= has_ty_bot as uint,
1099
      &ty_err => flags |= has_ty_err as uint,
1100 1101
      &ty_param(_) => flags |= has_params as uint,
      &ty_infer(_) => flags |= needs_infer as uint,
1102
      &ty_self(_) => flags |= has_self as uint,
1103
      &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
1104
      &ty_trait(_, ref substs, _, _) => {
1105
        flags |= sflags(substs);
1106
      }
1107 1108
      &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
      &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
1109
        flags |= get(m.ty).flags;
1110
      }
1111
      &ty_rptr(r, ref m) => {
1112 1113
        flags |= rflags(r);
        flags |= get(m.ty).flags;
M
Marijn Haverbeke 已提交
1114
      }
1115
      &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
1116 1117
      &ty_bare_fn(ref f) => {
        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
T
Tim Chevalier 已提交
1118 1119 1120
         flags |= get(f.sig.output).flags;
         // T -> _|_ is *not* _|_ !
         flags &= !(has_ty_bot as uint);
1121 1122 1123
      }
      &ty_closure(ref f) => {
        flags |= rflags(f.region);
1124 1125
        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
        flags |= get(f.sig.output).flags;
T
Tim Chevalier 已提交
1126 1127
        // T -> _|_ is *not* _|_ !
        flags &= !(has_ty_bot as uint);
M
Marijn Haverbeke 已提交
1128
      }
1129
    }
1130

1131
    let t = ~t_box_ {
1132
        sty: st,
1133
        id: *cx.next_id,
1134 1135
        flags: flags,
    };
1136 1137 1138

    let sty_ptr = to_unsafe_ptr(&t.sty);

1139
    let key = intern_key {
1140
        sty: sty_ptr,
1141
    };
1142

L
Luqman Aden 已提交
1143
    cx.interner.insert(key, t);
1144

1145
    *cx.next_id += 1;
1146 1147 1148 1149

    unsafe {
        cast::transmute::<*sty, t>(sty_ptr)
    }
1150 1151
}

1152
#[inline(always)]
T
Tim Chevalier 已提交
1153
pub fn mk_prim_t(primitive: &'static t_box_) -> t {
1154 1155 1156 1157
    unsafe {
        cast::transmute::<&'static t_box_, t>(primitive)
    }
}
P
Patrick Walton 已提交
1158

1159
#[inline(always)]
T
Tim Chevalier 已提交
1160
pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) }
1161

1162
#[inline(always)]
T
Tim Chevalier 已提交
1163
pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) }
1164

1165
#[inline(always)]
T
Tim Chevalier 已提交
1166
pub fn mk_bot() -> t { mk_prim_t(&primitives::TY_BOT) }
1167

1168
#[inline(always)]
T
Tim Chevalier 已提交
1169
pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) }
1170

1171
#[inline(always)]
T
Tim Chevalier 已提交
1172
pub fn mk_int() -> t { mk_prim_t(&primitives::TY_INT) }
1173

1174
#[inline(always)]
T
Tim Chevalier 已提交
1175
pub fn mk_i8() -> t { mk_prim_t(&primitives::TY_I8) }
1176

1177
#[inline(always)]
T
Tim Chevalier 已提交
1178
pub fn mk_i16() -> t { mk_prim_t(&primitives::TY_I16) }
1179

1180
#[inline(always)]
T
Tim Chevalier 已提交
1181
pub fn mk_i32() -> t { mk_prim_t(&primitives::TY_I32) }
1182

1183
#[inline(always)]
T
Tim Chevalier 已提交
1184
pub fn mk_i64() -> t { mk_prim_t(&primitives::TY_I64) }
1185

1186
#[inline(always)]
T
Tim Chevalier 已提交
1187
pub fn mk_float() -> t { mk_prim_t(&primitives::TY_FLOAT) }
1188

1189
#[inline(always)]
T
Tim Chevalier 已提交
1190
pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) }
1191

1192
#[inline(always)]
T
Tim Chevalier 已提交
1193
pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
1194

1195
#[inline(always)]
T
Tim Chevalier 已提交
1196
pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
1197

1198
#[inline(always)]
T
Tim Chevalier 已提交
1199
pub fn mk_u8() -> t { mk_prim_t(&primitives::TY_U8) }
1200

1201
#[inline(always)]
T
Tim Chevalier 已提交
1202
pub fn mk_u16() -> t { mk_prim_t(&primitives::TY_U16) }
1203

1204
#[inline(always)]
T
Tim Chevalier 已提交
1205
pub fn mk_u32() -> t { mk_prim_t(&primitives::TY_U32) }
1206

1207
#[inline(always)]
T
Tim Chevalier 已提交
1208
pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) }
1209

T
Tim Chevalier 已提交
1210
pub fn mk_mach_int(tm: ast::int_ty) -> t {
1211
    match tm {
T
Tim Chevalier 已提交
1212 1213 1214 1215 1216 1217
        ast::ty_i    => mk_int(),
        ast::ty_char => mk_char(),
        ast::ty_i8   => mk_i8(),
        ast::ty_i16  => mk_i16(),
        ast::ty_i32  => mk_i32(),
        ast::ty_i64  => mk_i64(),
1218 1219
    }
}
1220

T
Tim Chevalier 已提交
1221
pub fn mk_mach_uint(tm: ast::uint_ty) -> t {
1222
    match tm {
T
Tim Chevalier 已提交
1223 1224 1225 1226 1227
        ast::ty_u    => mk_uint(),
        ast::ty_u8   => mk_u8(),
        ast::ty_u16  => mk_u16(),
        ast::ty_u32  => mk_u32(),
        ast::ty_u64  => mk_u64(),
1228 1229
    }
}
1230

T
Tim Chevalier 已提交
1231
pub fn mk_mach_float(tm: ast::float_ty) -> t {
1232
    match tm {
T
Tim Chevalier 已提交
1233 1234 1235
        ast::ty_f    => mk_float(),
        ast::ty_f32  => mk_f32(),
        ast::ty_f64  => mk_f64(),
1236
    }
1237
}
1238

1239
#[inline(always)]
T
Tim Chevalier 已提交
1240
pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
1241

1242
pub fn mk_estr(cx: ctxt, t: vstore) -> t {
1243 1244 1245
    mk_t(cx, ty_estr(t))
}

1246
pub fn mk_enum(cx: ctxt, did: ast::def_id, substs: substs) -> t {
N
Niko Matsakis 已提交
1247
    // take a copy of substs so that we own the vectors inside
1248
    mk_t(cx, ty_enum(did, substs))
1249
}
1250

1251
pub fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) }
1252

1253
pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
1254 1255
    mk_box(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1256

1257
pub fn mk_uniq(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_uniq(tm)) }
1258

1259
pub fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
1260 1261
    mk_uniq(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1262

1263
pub fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
1264

1265
pub fn mk_rptr(cx: ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
1266

1267
pub fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1268
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_mutbl})
1269
}
1270
pub fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1271
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_imm})
1272 1273
}

1274
pub fn mk_mut_ptr(cx: ctxt, ty: t) -> t {
1275 1276
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_mutbl})
}
1277

1278
pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
1279
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_imm})
1280 1281
}

1282
pub fn mk_nil_ptr(cx: ctxt) -> t {
T
Tim Chevalier 已提交
1283
    mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::m_imm})
1284 1285
}

1286
pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
1287 1288 1289
    mk_t(cx, ty_evec(tm, t))
}

1290
pub fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
M
Michael Sullivan 已提交
1291 1292
    mk_t(cx, ty_unboxed_vec(tm))
}
1293
pub fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
1294
    mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::m_imm}))
1295
}
M
Michael Sullivan 已提交
1296

1297
pub fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
1298

1299
pub fn mk_closure(cx: ctxt, fty: ClosureTy) -> t {
1300 1301 1302
    mk_t(cx, ty_closure(fty))
}

1303
pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
1304 1305 1306 1307
    mk_t(cx, ty_bare_fn(fty))
}

pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
1308
    let input_args = input_tys.map(|t| arg { ty: *t });
1309 1310 1311
    mk_bare_fn(cx,
               BareFnTy {
                   purity: ast::pure_fn,
1312
                   abis: AbiSet::Rust(),
1313 1314 1315 1316 1317 1318
                   sig: FnSig {
                    bound_lifetime_names: opt_vec::Empty,
                    inputs: input_args,
                    output: output
                   }
                })
1319 1320
}

1321

1322 1323
pub fn mk_trait(cx: ctxt,
                did: ast::def_id,
1324
                substs: substs,
1325 1326
                store: TraitStore,
                mutability: ast::mutability)
1327
             -> t {
N
Niko Matsakis 已提交
1328
    // take a copy of substs so that we own the vectors inside
1329
    mk_t(cx, ty_trait(did, substs, store, mutability))
1330 1331
}

1332
pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, substs: substs) -> t {
N
Niko Matsakis 已提交
1333
    // take a copy of substs so that we own the vectors inside
1334
    mk_t(cx, ty_struct(struct_id, substs))
T
Tim Chevalier 已提交
1335 1336
}

1337
pub fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
1338

1339
pub fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }
1340

1341
pub fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
1342

1343
pub fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
1344

1345
pub fn mk_self(cx: ctxt, did: ast::def_id) -> t { mk_t(cx, ty_self(did)) }
M
Marijn Haverbeke 已提交
1346

1347
pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
1348
    mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
1349
}
1350

1351
pub fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
1352

1353 1354
pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
    mk_t(cx, ty_opaque_closure_ptr(sigil))
1355 1356
}

1357
pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
1358

1359
pub fn walk_ty(ty: t, f: &fn(t)) {
B
Brian Anderson 已提交
1360
    maybe_walk_ty(ty, |t| { f(t); true });
1361 1362
}

1363
pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
1364 1365 1366
    if !f(ty) {
        return;
    }
1367
    match get(ty).sty {
1368
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1369
      ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
1370
      ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1371
      }
1372 1373
      ty_box(ref tm) | ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) |
      ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
1374
        maybe_walk_ty(tm.ty, f);
1375
      }
1376
      ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1377
      ty_trait(_, ref substs, _, _) => {
1378
        for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); }
1379
      }
1380
      ty_tup(ref ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
1381 1382 1383 1384 1385
      ty_bare_fn(ref ft) => {
        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
        maybe_walk_ty(ft.sig.output, f);
      }
      ty_closure(ref ft) => {
1386 1387
        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
        maybe_walk_ty(ft.sig.output, f);
M
Marijn Haverbeke 已提交
1388
      }
1389 1390 1391
    }
}

1392
pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
N
Niko Matsakis 已提交
1393
    mk_t(tcx, fold_sty(sty, foldop))
1394
}
1395

1396
pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
1397
    let args = do sig.inputs.map |arg| {
1398 1399 1400
        arg {
            ty: fldop(arg.ty)
        }
1401 1402 1403
    };

    FnSig {
1404
        bound_lifetime_names: copy sig.bound_lifetime_names,
L
Luqman Aden 已提交
1405
        inputs: args,
1406 1407 1408 1409
        output: fldop(sig.output)
    }
}

1410 1411 1412 1413 1414 1415
pub fn fold_bare_fn_ty(fty: &BareFnTy, fldop: &fn(t) -> t) -> BareFnTy {
    BareFnTy {sig: fold_sig(&fty.sig, fldop),
              abis: fty.abis,
              purity: fty.purity}
}

1416 1417
fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
    fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
1418 1419 1420
        substs {self_r: substs.self_r,
                self_ty: substs.self_ty.map(|t| fldop(*t)),
                tps: substs.tps.map(|t| fldop(*t))}
1421 1422
    }

1423 1424
    match *sty {
        ty_box(ref tm) => {
1425
            ty_box(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1426
        }
1427
        ty_uniq(ref tm) => {
1428
            ty_uniq(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1429
        }
1430
        ty_ptr(ref tm) => {
1431
            ty_ptr(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1432
        }
1433
        ty_unboxed_vec(ref tm) => {
1434
            ty_unboxed_vec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1435
        }
1436
        ty_evec(ref tm, vst) => {
1437
            ty_evec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
1438 1439 1440 1441
        }
        ty_enum(tid, ref substs) => {
            ty_enum(tid, fold_substs(substs, fldop))
        }
1442 1443
        ty_trait(did, ref substs, st, mutbl) => {
            ty_trait(did, fold_substs(substs, fldop), st, mutbl)
1444
        }
1445 1446
        ty_tup(ref ts) => {
            let new_ts = ts.map(|tt| fldop(*tt));
1447 1448
            ty_tup(new_ts)
        }
1449
        ty_bare_fn(ref f) => {
1450
            ty_bare_fn(fold_bare_fn_ty(f, fldop))
1451 1452
        }
        ty_closure(ref f) => {
1453
            let sig = fold_sig(&f.sig, fldop);
1454
            ty_closure(ClosureTy {sig: sig, ..copy *f})
1455
        }
1456
        ty_rptr(r, ref tm) => {
1457
            ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1458
        }
1459 1460
        ty_struct(did, ref substs) => {
            ty_struct(did, fold_substs(substs, fldop))
1461 1462
        }
        ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1463
        ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1464
        ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
1465
            /*bad*/copy *sty
1466
        }
N
Niko Matsakis 已提交
1467 1468
    }
}
1469

N
Niko Matsakis 已提交
1470
// Folds types from the bottom up.
1471
pub fn fold_ty(cx: ctxt, t0: t, fldop: &fn(t) -> t) -> t {
1472
    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
N
Niko Matsakis 已提交
1473 1474
    fldop(mk_t(cx, sty))
}
1475

1476
pub fn walk_regions_and_ty(
1477 1478
    cx: ctxt,
    ty: t,
1479 1480
    walkr: &fn(r: Region),
    walkt: &fn(t: t) -> bool) {
1481 1482 1483 1484

    if (walkt(ty)) {
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1485
            |r| { walkr(r); r },
1486 1487
            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t },
            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t });
1488 1489 1490
    }
}

1491
pub fn fold_regions_and_ty(
1492 1493
    cx: ctxt,
    ty: t,
1494 1495 1496
    fldr: &fn(r: Region) -> Region,
    fldfnt: &fn(t: t) -> t,
    fldt: &fn(t: t) -> t) -> t {
1497 1498

    fn fold_substs(
N
Niko Matsakis 已提交
1499
        substs: &substs,
1500 1501
        fldr: &fn(r: Region) -> Region,
        fldt: &fn(t: t) -> t)
1502 1503 1504 1505 1506 1507
     -> substs {
        substs {
            self_r: substs.self_r.map(|r| fldr(*r)),
            self_ty: substs.self_ty.map(|t| fldt(*t)),
            tps: substs.tps.map(|t| fldt(*t))
        }
1508 1509 1510
    }

    let tb = ty::get(ty);
1511
    match tb.sty {
B
Brian Anderson 已提交
1512
      ty::ty_rptr(r, mt) => {
1513 1514
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1515
        ty::mk_rptr(cx, m_r, mt {ty: m_t, mutbl: mt.mutbl})
1516
      }
B
Brian Anderson 已提交
1517
      ty_estr(vstore_slice(r)) => {
1518 1519 1520
        let m_r = fldr(r);
        ty::mk_estr(cx, vstore_slice(m_r))
      }
B
Brian Anderson 已提交
1521
      ty_evec(mt, vstore_slice(r)) => {
1522 1523
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1524
        ty::mk_evec(cx, mt {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
1525
      }
N
Niko Matsakis 已提交
1526
      ty_enum(def_id, ref substs) => {
1527 1528
        ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
      }
1529 1530
      ty_struct(def_id, ref substs) => {
        ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1531
      }
1532 1533
      ty_trait(def_id, ref substs, st, mutbl) => {
        ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl)
1534
      }
1535 1536 1537 1538 1539 1540 1541 1542
      ty_bare_fn(ref f) => {
          ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
                                       ..copy *f})
      }
      ty_closure(ref f) => {
          ty::mk_closure(cx, ClosureTy {region: fldr(f.region),
                                        sig: fold_sig(&f.sig, fldfnt),
                                        ..copy *f})
1543
      }
N
Niko Matsakis 已提交
1544
      ref sty => {
B
Brian Anderson 已提交
1545
        fold_sty_to_ty(cx, sty, |t| fldt(t))
1546 1547 1548 1549
      }
    }
}

1550 1551
// n.b. this function is intended to eventually replace fold_region() below,
// that is why its name is so similar.
1552
pub fn fold_regions(
1553 1554
    cx: ctxt,
    ty: t,
1555
    fldr: &fn(r: Region, in_fn: bool) -> Region) -> t {
1556
    fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1557
               fldr: &fn(Region, bool) -> Region) -> t {
1558
        debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
B
Brian Anderson 已提交
1559
        if !type_has_regions(ty) { return ty; }
1560 1561
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1562 1563 1564
            |r| fldr(r, in_fn),
            |t| do_fold(cx, t, true, fldr),
            |t| do_fold(cx, t, in_fn, fldr))
1565 1566 1567 1568
    }
    do_fold(cx, ty, false, fldr)
}

1569
// Substitute *only* type parameters.  Used in trans where regions are erased.
1570
pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
1571
    if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1572
    let tb = ty::get(typ);
1573
    if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1574
    match tb.sty {
1575
        ty_param(p) => tps[p.idx],
1576
        ty_self(_) => {
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
            match self_ty_opt {
                None => cx.sess.bug(~"ty_self unexpected here"),
                Some(self_ty) => {
                    subst_tps(cx, tps, self_ty_opt, self_ty)
                }
            }
        }
        ref sty => {
            fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t))
        }
1587 1588 1589
    }
}

1590
pub fn substs_is_noop(substs: &substs) -> bool {
1591 1592 1593
    substs.tps.len() == 0u &&
        substs.self_r.is_none() &&
        substs.self_ty.is_none()
1594 1595
}

1596
pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
1597
    substs.repr(cx)
1598 1599
}

1600 1601 1602 1603
pub fn subst(cx: ctxt,
             substs: &substs,
             typ: t)
          -> t {
1604
    typ.subst(cx, substs)
1605 1606
}

1607
// Type utilities
1608

1609
pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
1610

T
Tim Chevalier 已提交
1611 1612 1613 1614 1615 1616 1617
pub fn type_is_bot(ty: t) -> bool {
    (get(ty).flags & (has_ty_bot as uint)) != 0
}

pub fn type_is_error(ty: t) -> bool {
    (get(ty).flags & (has_ty_err as uint)) != 0
}
1618

1619 1620 1621 1622
pub fn type_needs_subst(ty: t) -> bool {
    tbox_has_flag(get(ty), needs_subst)
}

1623 1624 1625 1626 1627
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
    tref.substs.self_ty.any(|&t| type_is_error(t)) ||
        tref.substs.tps.any(|&t| type_is_error(t))
}

1628
pub fn type_is_ty_var(ty: t) -> bool {
1629
    match get(ty).sty {
1630
      ty_infer(TyVar(_)) => true,
B
Brian Anderson 已提交
1631
      _ => false
1632 1633 1634
    }
}

1635
pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
1636

1637 1638 1639 1640 1641 1642 1643
pub fn type_is_self(ty: t) -> bool {
    match get(ty).sty {
        ty_self(*) => true,
        _ => false
    }
}

1644
pub fn type_is_structural(ty: t) -> bool {
1645
    match get(ty).sty {
1646
      ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_closure(_) | ty_trait(*) |
1647 1648
      ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
B
Brian Anderson 已提交
1649 1650
      => true,
      _ => false
1651 1652 1653
    }
}

1654
pub fn type_is_sequence(ty: t) -> bool {
1655
    match get(ty).sty {
B
Brian Anderson 已提交
1656 1657
      ty_estr(_) | ty_evec(_, _) => true,
      _ => false
1658 1659 1660
    }
}

S
Seo Sanghyeon 已提交
1661 1662 1663 1664 1665 1666 1667
pub fn type_is_simd(cx: ctxt, ty: t) -> bool {
    match get(ty).sty {
        ty_struct(did, _) => lookup_simd(cx, did),
        _ => false
    }
}

1668
pub fn type_is_str(ty: t) -> bool {
1669
    match get(ty).sty {
B
Brian Anderson 已提交
1670 1671
      ty_estr(_) => true,
      _ => false
1672 1673
    }
}
1674

1675
pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
1676
    match get(ty).sty {
T
Tim Chevalier 已提交
1677
      ty_estr(_) => return mk_mach_uint(ast::ty_u8),
B
Brian Anderson 已提交
1678 1679 1680
      ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
      _ => cx.sess.bug(
          ~"sequence_element_type called on non-sequence value"),
1681 1682 1683
    }
}

S
Seo Sanghyeon 已提交
1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703
pub fn simd_type(cx: ctxt, ty: t) -> t {
    match get(ty).sty {
        ty_struct(did, ref substs) => {
            let fields = lookup_struct_fields(cx, did);
            lookup_field_type(cx, did, fields[0].id, substs)
        }
        _ => fail!(~"simd_type called on invalid type")
    }
}

pub fn simd_size(cx: ctxt, ty: t) -> uint {
    match get(ty).sty {
        ty_struct(did, _) => {
            let fields = lookup_struct_fields(cx, did);
            fields.len()
        }
        _ => fail!(~"simd_size called on invalid type")
    }
}

1704
pub fn get_element_type(ty: t, i: uint) -> t {
1705 1706
    match get(ty).sty {
      ty_tup(ref ts) => return ts[i],
1707
      _ => fail!(~"get_element_type called on invalid type")
1708 1709 1710
    }
}

1711
pub fn type_is_box(ty: t) -> bool {
1712
    match get(ty).sty {
B
Brian Anderson 已提交
1713 1714
      ty_box(_) => return true,
      _ => return false
1715
    }
M
Marijn Haverbeke 已提交
1716 1717
}

1718
pub fn type_is_boxed(ty: t) -> bool {
1719
    match get(ty).sty {
1720
      ty_box(_) | ty_opaque_box |
B
Brian Anderson 已提交
1721 1722
      ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
      _ => false
1723 1724 1725
    }
}

1726
pub fn type_is_region_ptr(ty: t) -> bool {
1727
    match get(ty).sty {
B
Brian Anderson 已提交
1728 1729
      ty_rptr(_, _) => true,
      _ => false
1730 1731 1732
    }
}

1733
pub fn type_is_slice(ty: t) -> bool {
1734
    match get(ty).sty {
B
Brian Anderson 已提交
1735 1736
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
      _ => return false
1737 1738 1739
    }
}

1740
pub fn type_is_unique_box(ty: t) -> bool {
1741
    match get(ty).sty {
B
Brian Anderson 已提交
1742 1743
      ty_uniq(_) => return true,
      _ => return false
1744
    }
M
Marijn Haverbeke 已提交
1745
}
1746

1747
pub fn type_is_unsafe_ptr(ty: t) -> bool {
1748
    match get(ty).sty {
B
Brian Anderson 已提交
1749 1750
      ty_ptr(_) => return true,
      _ => return false
1751 1752 1753
    }
}

1754
pub fn type_is_vec(ty: t) -> bool {
1755
    return match get(ty).sty {
B
Brian Anderson 已提交
1756 1757 1758
          ty_evec(_, _) | ty_unboxed_vec(_) => true,
          ty_estr(_) => true,
          _ => false
B
Brian Anderson 已提交
1759
        };
M
Marijn Haverbeke 已提交
1760 1761
}

1762
pub fn type_is_unique(ty: t) -> bool {
1763
    match get(ty).sty {
1764 1765 1766 1767 1768
        ty_uniq(_) |
        ty_evec(_, vstore_uniq) |
        ty_estr(vstore_uniq) |
        ty_opaque_closure_ptr(ast::OwnedSigil) => true,
        _ => return false
B
Brian Anderson 已提交
1769
    }
1770 1771
}

1772 1773 1774 1775 1776
/*
 A scalar type is one that denotes an atomic datum, with no sub-components.
 (A ty_ptr is scalar because it represents a non-managed pointer, so its
 contents are abstract to rustc.)
*/
1777
pub fn type_is_scalar(ty: t) -> bool {
1778
    match get(ty).sty {
1779
      ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1780
      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
1781
      ty_bare_fn(*) | ty_ptr(_) => true,
B
Brian Anderson 已提交
1782
      _ => false
M
Marijn Haverbeke 已提交
1783
    }
1784 1785
}

1786
pub fn type_is_immediate(ty: t) -> bool {
B
Brian Anderson 已提交
1787
    return type_is_scalar(ty) || type_is_boxed(ty) ||
1788
        type_is_unique(ty) || type_is_region_ptr(ty);
1789 1790
}

1791
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1792
    type_contents(cx, ty).needs_drop(cx)
1793 1794
}

1795 1796 1797 1798
// Some things don't need cleanups during unwinding because the
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
// cleanups.
1799
pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1800
    match cx.needs_unwind_cleanup_cache.find(&ty) {
1801
      Some(&result) => return result,
B
Brian Anderson 已提交
1802
      None => ()
1803 1804
    }

1805
    let mut tycache = HashSet::new();
1806
    let needs_unwind_cleanup =
1807
        type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
1808
    cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
B
Brian Anderson 已提交
1809
    return needs_unwind_cleanup;
1810 1811 1812
}

fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1813
                              tycache: &mut HashSet<t>,
1814 1815
                              encountered_box: bool) -> bool {

1816
    // Prevent infinite recursion
1817 1818
    if !tycache.insert(ty) {
        return false;
1819
    }
1820

1821
    let mut encountered_box = encountered_box;
1822
    let mut needs_unwind_cleanup = false;
B
Brian Anderson 已提交
1823
    do maybe_walk_ty(ty) |ty| {
1824
        let old_encountered_box = encountered_box;
1825
        let result = match get(ty).sty {
B
Brian Anderson 已提交
1826
          ty_box(_) | ty_opaque_box => {
1827 1828 1829
            encountered_box = true;
            true
          }
1830 1831
          ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
          ty_tup(_) | ty_ptr(_) => {
1832 1833
            true
          }
N
Niko Matsakis 已提交
1834
          ty_enum(did, ref substs) => {
1835
            for (*enum_variants(cx, did)).each |v| {
B
Brian Anderson 已提交
1836
                for v.args.each |aty| {
1837
                    let t = subst(cx, substs, *aty);
1838 1839 1840
                    needs_unwind_cleanup |=
                        type_needs_unwind_cleanup_(cx, t, tycache,
                                                   encountered_box);
1841 1842 1843 1844
                }
            }
            !needs_unwind_cleanup
          }
M
Michael Sullivan 已提交
1845
          ty_uniq(_) |
1846 1847 1848 1849
          ty_estr(vstore_uniq) |
          ty_estr(vstore_box) |
          ty_evec(_, vstore_uniq) |
          ty_evec(_, vstore_box)
B
Brian Anderson 已提交
1850
          => {
1851 1852 1853 1854 1855 1856 1857 1858 1859
            // Once we're inside a box, the annihilator will find
            // it and destroy it.
            if !encountered_box {
                needs_unwind_cleanup = true;
                false
            } else {
                true
            }
          }
B
Brian Anderson 已提交
1860
          _ => {
1861 1862 1863
            needs_unwind_cleanup = true;
            false
          }
1864 1865 1866 1867
        };

        encountered_box = old_encountered_box;
        result
1868 1869
    }

B
Brian Anderson 已提交
1870
    return needs_unwind_cleanup;
1871 1872
}

1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
/**
 * Type contents is how the type checker reasons about kinds.
 * They track what kinds of things are found within a type.  You can
 * think of them as kind of an "anti-kind".  They track the kinds of values
 * and thinks that are contained in types.  Having a larger contents for
 * a type tends to rule that type *out* from various kinds.  For example,
 * a type that contains a borrowed pointer is not sendable.
 *
 * The reason we compute type contents and not kinds is that it is
 * easier for me (nmatsakis) to think about what is contained within
 * a type than to think about what is *not* contained within a type.
 */
pub struct TypeContents {
    bits: u32
}
1888

1889
pub impl TypeContents {
1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902
    fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool {
        iter::all(|bb| self.meets_bound(cx, bb), |f| bbs.each(f))
    }

    fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool {
        match bb {
            BoundCopy => self.is_copy(cx),
            BoundStatic => self.is_static(cx),
            BoundConst => self.is_const(cx),
            BoundOwned => self.is_owned(cx)
        }
    }

1903 1904 1905
    fn intersects(&self, tc: TypeContents) -> bool {
        (self.bits & tc.bits) != 0
    }
1906

1907 1908 1909
    fn is_copy(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::noncopyable(cx))
    }
1910

1911
    fn noncopyable(_cx: ctxt) -> TypeContents {
1912 1913 1914
        TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE +
            TC_EMPTY_ENUM
    }
1915

1916 1917
    fn is_static(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonstatic(cx))
1918
    }
1919

1920
    fn nonstatic(_cx: ctxt) -> TypeContents {
1921 1922
        TC_BORROWED_POINTER
    }
1923

1924 1925 1926
    fn is_owned(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonowned(cx))
    }
1927

1928
    fn nonowned(_cx: ctxt) -> TypeContents {
1929
        TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED
1930
    }
1931

1932 1933 1934 1935
    fn contains_managed(&self) -> bool {
        self.intersects(TC_MANAGED)
    }

1936 1937 1938
    fn is_const(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonconst(cx))
    }
1939

1940
    fn nonconst(_cx: ctxt) -> TypeContents {
1941 1942
        TC_MUTABLE
    }
1943

1944 1945 1946
    fn moves_by_default(&self, cx: ctxt) -> bool {
        self.intersects(TypeContents::nonimplicitly_copyable(cx))
    }
1947

1948
    fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
1949
        let base = TypeContents::noncopyable(cx) + TC_OWNED_POINTER;
1950
        if cx.vecs_implicitly_copyable {base} else {base + TC_OWNED_VEC}
1951
    }
1952

1953 1954 1955 1956 1957
    fn needs_drop(&self, cx: ctxt) -> bool {
        let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx);
        self.intersects(tc)
    }

1958
    fn owned(_cx: ctxt) -> TypeContents {
1959 1960
        //! Any kind of owned contents.
        TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC
1961
    }
1962
}
1963

1964
impl ops::Add<TypeContents,TypeContents> for TypeContents {
1965
    fn add(&self, other: &TypeContents) -> TypeContents {
1966 1967
        TypeContents {bits: self.bits | other.bits}
    }
1968 1969
}

1970
impl ops::Sub<TypeContents,TypeContents> for TypeContents {
1971
    fn sub(&self, other: &TypeContents) -> TypeContents {
1972 1973
        TypeContents {bits: self.bits & !other.bits}
    }
1974 1975
}

1976
impl ToStr for TypeContents {
1977
    fn to_str(&self) -> ~str {
1978 1979
        fmt!("TypeContents(%s)", u32::to_str_radix(self.bits, 2))
    }
1980 1981
}

1982
/// Constant for a type containing nothing of interest.
1983
static TC_NONE: TypeContents =             TypeContents{bits: 0b0000_0000_0000};
1984

1985
/// Contains a borrowed value with a lifetime other than static
1986
static TC_BORROWED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0001};
1987

1988
/// Contains an owned pointer (~T) but not slice of some kind
1989
static TC_OWNED_POINTER: TypeContents =    TypeContents{bits: 0b0000_0000_0010};
1990

1991
/// Contains an owned vector ~[] or owned string ~str
1992
static TC_OWNED_VEC: TypeContents =        TypeContents{bits: 0b0000_0000_0100};
1993

1994
/// Contains a ~fn() or a ~Trait, which is non-copyable.
1995
static TC_OWNED_CLOSURE: TypeContents =    TypeContents{bits: 0b0000_0000_1000};
1996

1997
/// Type with a destructor
1998
static TC_DTOR: TypeContents =             TypeContents{bits: 0b0000_0001_0000};
1999

2000
/// Contains a managed value
2001
static TC_MANAGED: TypeContents =          TypeContents{bits: 0b0000_0010_0000};
2002

2003
/// &mut with any region
2004
static TC_BORROWED_MUT: TypeContents =     TypeContents{bits: 0b0000_0100_0000};
2005

2006
/// Mutable content, whether owned or by ref
2007
static TC_MUTABLE: TypeContents =          TypeContents{bits: 0b0000_1000_0000};
2008

2009 2010
/// One-shot closure
static TC_ONCE_CLOSURE: TypeContents =     TypeContents{bits: 0b0001_0000_0000};
2011

2012
/// An enum with no variants.
2013 2014 2015 2016
static TC_EMPTY_ENUM: TypeContents =       TypeContents{bits: 0b0010_0000_0000};

/// Contains a type marked with `#[non_owned]`
static TC_NON_OWNED: TypeContents =        TypeContents{bits: 0b0100_0000_0000};
2017

2018
/// All possible contents.
2019
static TC_ALL: TypeContents =              TypeContents{bits: 0b0111_1111_1111};
2020

2021 2022
pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_copy(cx)
2023 2024
}

2025 2026
pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_static(cx)
2027 2028
}

2029 2030 2031
pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_owned(cx)
}
2032

2033 2034 2035
pub fn type_is_const(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_const(cx)
}
2036

2037 2038 2039 2040 2041
pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
    let ty_id = type_id(ty);
    match cx.tc_cache.find(&ty_id) {
        Some(tc) => { return *tc; }
        None => {}
2042 2043
    }

2044
    let mut cache = HashMap::new();
2045 2046 2047
    let result = tc_ty(cx, ty, &mut cache);
    cx.tc_cache.insert(ty_id, result);
    return result;
M
Marijn Haverbeke 已提交
2048

2049 2050
    fn tc_ty(cx: ctxt,
             ty: t,
2051
             cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078
    {
        // Subtle: Note that we are *not* using cx.tc_cache here but rather a
        // private cache for this walk.  This is needed in the case of cyclic
        // types like:
        //
        //     struct List { next: ~Option<List>, ... }
        //
        // When computing the type contents of such a type, we wind up deeply
        // recursing as we go.  So when we encounter the recursive reference
        // to List, we temporarily use TC_NONE as its contents.  Later we'll
        // patch up the cache with the correct value, once we've computed it
        // (this is basically a co-inductive process, if that helps).  So in
        // the end we'll compute TC_OWNED_POINTER, in this case.
        //
        // The problem is, as we are doing the computation, we will also
        // compute an *intermediate* contents for, e.g., Option<List> of
        // TC_NONE.  This is ok during the computation of List itself, but if
        // we stored this intermediate value into cx.tc_cache, then later
        // requests for the contents of Option<List> would also yield TC_NONE
        // which is incorrect.  This value was computed based on the crutch
        // value for the type contents of list.  The correct value is
        // TC_OWNED_POINTER.  This manifested as issue #4821.
        let ty_id = type_id(ty);
        match cache.find(&ty_id) {
            Some(tc) => { return *tc; }
            None => {}
        }
2079 2080 2081 2082
        match cx.tc_cache.find(&ty_id) {    // Must check both caches!
            Some(tc) => { return *tc; }
            None => {}
        }
2083 2084 2085 2086
        cache.insert(ty_id, TC_NONE);

        let _i = indenter();

2087
        let result = match get(ty).sty {
2088 2089 2090 2091 2092
            // Scalar and unique types are sendable, constant, and owned
            ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
            ty_bare_fn(_) | ty_ptr(_) => {
                TC_NONE
            }
2093

2094
            ty_estr(vstore_uniq) => {
2095
                TC_OWNED_VEC
2096
            }
M
Marijn Haverbeke 已提交
2097

2098 2099 2100
            ty_closure(ref c) => {
                closure_contents(c)
            }
2101

2102 2103 2104
            ty_box(mt) => {
                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
            }
2105

2106
            ty_trait(_, _, UniqTraitStore, _) => {
2107 2108
                TC_OWNED_CLOSURE
            }
2109

2110 2111 2112 2113 2114
            ty_trait(_, _, BoxTraitStore, mutbl) => {
                match mutbl {
                    ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
                    _ => TC_MANAGED
                }
2115
            }
2116

2117 2118
            ty_trait(_, _, RegionTraitStore(r), mutbl) => {
                borrowed_contents(r, mutbl)
2119
            }
2120

2121 2122 2123 2124
            ty_rptr(r, mt) => {
                borrowed_contents(r, mt.mutbl) +
                    nonowned(tc_mt(cx, mt, cache))
            }
2125

2126 2127 2128
            ty_uniq(mt) => {
                TC_OWNED_POINTER + tc_mt(cx, mt, cache)
            }
2129

2130
            ty_evec(mt, vstore_uniq) => {
2131
                TC_OWNED_VEC + tc_mt(cx, mt, cache)
2132
            }
2133

2134 2135 2136
            ty_evec(mt, vstore_box) => {
                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
            }
2137

2138 2139 2140 2141
            ty_evec(mt, vstore_slice(r)) => {
                borrowed_contents(r, mt.mutbl) +
                    nonowned(tc_mt(cx, mt, cache))
            }
2142

2143 2144 2145
            ty_evec(mt, vstore_fixed(_)) => {
                tc_mt(cx, mt, cache)
            }
2146

2147 2148 2149
            ty_estr(vstore_box) => {
                TC_MANAGED
            }
2150

2151 2152 2153
            ty_estr(vstore_slice(r)) => {
                borrowed_contents(r, m_imm)
            }
2154

2155 2156 2157
            ty_estr(vstore_fixed(_)) => {
                TC_NONE
            }
2158

2159 2160
            ty_struct(did, ref substs) => {
                let flds = struct_fields(cx, did, substs);
2161
                let mut res = flds.foldl(
2162 2163 2164
                    TC_NONE,
                    |tc, f| tc + tc_mt(cx, f.mt, cache));
                if ty::has_dtor(cx, did) {
2165
                    res += TC_DTOR;
2166
                }
D
Daniel Micay 已提交
2167
                apply_tc_attr(cx, did, res)
2168
            }
2169

2170 2171 2172
            ty_tup(ref tys) => {
                tys.foldl(TC_NONE, |tc, ty| *tc + tc_ty(cx, *ty, cache))
            }
2173

2174 2175
            ty_enum(did, ref substs) => {
                let variants = substd_enum_variants(cx, did, substs);
D
Daniel Micay 已提交
2176
                let res = if variants.is_empty() {
2177 2178 2179 2180 2181 2182 2183 2184 2185
                    // we somewhat arbitrary declare that empty enums
                    // are non-copyable
                    TC_EMPTY_ENUM
                } else {
                    variants.foldl(TC_NONE, |tc, variant| {
                        variant.args.foldl(
                            *tc,
                            |tc, arg_ty| *tc + tc_ty(cx, *arg_ty, cache))
                    })
2186
                };
D
Daniel Micay 已提交
2187
                apply_tc_attr(cx, did, res)
2188
            }
2189

2190 2191 2192 2193 2194 2195 2196
            ty_param(p) => {
                // We only ever ask for the kind of types that are defined in
                // the current crate; therefore, the only type parameters that
                // could be in scope are those defined in the current crate.
                // If this assertion failures, it is likely because of a
                // failure in the cross-crate inlining code to translate a
                // def-id.
P
Patrick Walton 已提交
2197
                assert!(p.def_id.crate == ast::local_crate);
2198

2199 2200
                type_param_def_to_contents(
                    cx, cx.ty_param_defs.get(&p.def_id.node))
2201
            }
2202

2203
            ty_self(_) => {
2204 2205 2206 2207 2208 2209 2210
                // Currently, self is not bounded, so we must assume the
                // worst.  But in the future we should examine the super
                // traits.
                //
                // FIXME(#4678)---self should just be a ty param
                TC_ALL
            }
2211

2212 2213 2214 2215 2216 2217
            ty_infer(_) => {
                // This occurs during coherence, but shouldn't occur at other
                // times.
                TC_ALL
            }

2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
            ty_opaque_box => TC_MANAGED,
            ty_unboxed_vec(mt) => tc_mt(cx, mt, cache),
            ty_opaque_closure_ptr(sigil) => {
                match sigil {
                    ast::BorrowedSigil => TC_BORROWED_POINTER,
                    ast::ManagedSigil => TC_MANAGED,
                    ast::OwnedSigil => TC_OWNED_CLOSURE
                }
            }

            ty_type => TC_NONE,

2230 2231
            ty_err => {
                cx.sess.bug(~"Asked to compute contents of fictitious type");
2232
            }
2233 2234 2235 2236 2237
        };

        cache.insert(ty_id, result);
        return result;
    }
2238

2239 2240
    fn tc_mt(cx: ctxt,
             mt: mt,
2241
             cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2242 2243 2244 2245
    {
        let mc = if mt.mutbl == m_mutbl {TC_MUTABLE} else {TC_NONE};
        mc + tc_ty(cx, mt.ty, cache)
    }
2246

D
Daniel Micay 已提交
2247 2248 2249 2250 2251 2252 2253 2254 2255 2256
    fn apply_tc_attr(cx: ctxt, did: def_id, mut tc: TypeContents) -> TypeContents {
        if has_attr(cx, did, "mutable") {
            tc += TC_MUTABLE;
        }
        if has_attr(cx, did, "non_owned") {
            tc += TC_NON_OWNED;
        }
        tc
    }

2257 2258 2259 2260 2261
    fn borrowed_contents(region: ty::Region,
                         mutbl: ast::mutability) -> TypeContents
    {
        let mc = if mutbl == m_mutbl {
            TC_MUTABLE + TC_BORROWED_MUT
2262
        } else {
2263 2264 2265 2266 2267 2268 2269 2270 2271
            TC_NONE
        };
        let rc = if region != ty::re_static {
            TC_BORROWED_POINTER
        } else {
            TC_NONE
        };
        mc + rc
    }
2272

2273 2274 2275 2276 2277 2278 2279 2280
    fn nonowned(pointee: TypeContents) -> TypeContents {
        /*!
         *
         * Given a non-owning pointer to some type `T` with
         * contents `pointee` (like `@T` or
         * `&T`), returns the relevant bits that
         * apply to the owner of the pointer.
         */
2281

2282 2283
        let mask = TC_MUTABLE.bits | TC_BORROWED_POINTER.bits;
        TypeContents {bits: pointee.bits & mask}
2284 2285
    }

2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299
    fn closure_contents(cty: &ClosureTy) -> TypeContents {
        let st = match cty.sigil {
            ast::BorrowedSigil => TC_BORROWED_POINTER,
            ast::ManagedSigil => TC_MANAGED,
            ast::OwnedSigil => TC_OWNED_CLOSURE
        };
        let rt = borrowed_contents(cty.region, m_imm);
        let ot = match cty.onceness {
            ast::Once => TC_ONCE_CLOSURE,
            ast::Many => TC_NONE
        };
        st + rt + ot
    }

2300 2301
    fn type_param_def_to_contents(cx: ctxt,
                                  type_param_def: &TypeParameterDef) -> TypeContents
2302
    {
2303
        debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx));
2304 2305
        let _i = indenter();

2306 2307
        let mut tc = TC_ALL;
        for type_param_def.bounds.builtin_bounds.each |bound| {
2308
            debug!("tc = %s, bound = %?", tc.to_str(), bound);
2309 2310 2311 2312 2313 2314 2315
            tc = tc - match bound {
                BoundCopy => TypeContents::nonimplicitly_copyable(cx),
                BoundStatic => TypeContents::nonstatic(cx),
                BoundOwned => TypeContents::nonowned(cx),
                BoundConst => TypeContents::nonconst(cx),
            };
        }
2316

2317 2318
        debug!("result = %s", tc.to_str());
        return tc;
2319
    }
2320 2321
}

2322 2323 2324 2325
pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool {
    type_contents(cx, ty).moves_by_default(cx)
}

2326
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2327
pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
2328
    fn type_requires(cx: ctxt, seen: &mut ~[def_id],
2329
                     r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2330
        debug!("type_requires(%s, %s)?",
2331 2332
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2333 2334

        let r = {
2335
            get(r_ty).sty == get(ty).sty ||
2336 2337 2338
                subtypes_require(cx, seen, r_ty, ty)
        };

P
Paul Stansifer 已提交
2339
        debug!("type_requires(%s, %s)? %b",
2340 2341
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2342
               r);
B
Brian Anderson 已提交
2343
        return r;
2344 2345
    }

2346
    fn subtypes_require(cx: ctxt, seen: &mut ~[def_id],
2347
                        r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2348
        debug!("subtypes_require(%s, %s)?",
2349 2350
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2351

2352
        let r = match get(ty).sty {
2353 2354 2355 2356 2357 2358
          ty_nil |
          ty_bot |
          ty_bool |
          ty_int(_) |
          ty_uint(_) |
          ty_float(_) |
2359
          ty_estr(_) |
2360 2361
          ty_bare_fn(_) |
          ty_closure(_) |
2362
          ty_infer(_) |
2363
          ty_err |
2364
          ty_param(_) |
2365
          ty_self(_) |
2366 2367 2368
          ty_type |
          ty_opaque_box |
          ty_opaque_closure_ptr(_) |
2369
          ty_evec(_, _) |
B
Brian Anderson 已提交
2370
          ty_unboxed_vec(_) => {
2371 2372
            false
          }
2373 2374 2375
          ty_box(ref mt) |
          ty_uniq(ref mt) |
          ty_rptr(_, ref mt) => {
B
Brian Anderson 已提交
2376
            return type_requires(cx, seen, r_ty, mt.ty);
2377 2378
          }

2379
          ty_ptr(*) => {
2380 2381 2382
            false           // unsafe ptrs can always be NULL
          }

2383
          ty_trait(_, _, _, _) => {
2384 2385 2386
            false
          }

2387
          ty_struct(ref did, _) if vec::contains(*seen, did) => {
2388 2389 2390
            false
          }

2391
          ty_struct(did, ref substs) => {
2392
              seen.push(did);
2393
              let r = vec::any(struct_fields(cx, did, substs),
2394
                               |f| type_requires(cx, seen, r_ty, f.mt.ty));
N
Niko Matsakis 已提交
2395
              seen.pop();
2396 2397 2398
            r
          }

2399 2400
          ty_tup(ref ts) => {
            ts.any(|t| type_requires(cx, seen, r_ty, *t))
2401 2402
          }

N
Niko Matsakis 已提交
2403
          ty_enum(ref did, _) if vec::contains(*seen, did) => {
2404 2405 2406
            false
          }

2407 2408 2409 2410 2411
            ty_enum(did, ref substs) => {
                seen.push(did);
                let vs = enum_variants(cx, did);
                let r = vec::len(*vs) > 0u && vec::all(*vs, |variant| {
                    vec::any(variant.args, |aty| {
N
Niko Matsakis 已提交
2412
                        let sty = subst(cx, substs, *aty);
2413 2414 2415
                        type_requires(cx, seen, r_ty, sty)
                    })
                });
N
Niko Matsakis 已提交
2416
                seen.pop();
2417 2418
                r
            }
2419 2420
        };

P
Paul Stansifer 已提交
2421
        debug!("subtypes_require(%s, %s)? %b",
2422 2423
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2424
               r);
2425

B
Brian Anderson 已提交
2426
        return r;
2427 2428
    }

2429
    let seen = @mut ~[];
2430 2431 2432
    !subtypes_require(cx, seen, r_ty, r_ty)
}

2433 2434
pub fn type_structurally_contains(cx: ctxt,
                                  ty: t,
2435
                                  test: &fn(x: &sty) -> bool)
2436
                               -> bool {
2437
    let sty = &get(ty).sty;
2438 2439
    debug!("type_structurally_contains: %s",
           ::util::ppaux::ty_to_str(cx, ty));
B
Brian Anderson 已提交
2440
    if test(sty) { return true; }
2441
    match *sty {
N
Niko Matsakis 已提交
2442
      ty_enum(did, ref substs) => {
2443
        for (*enum_variants(cx, did)).each |variant| {
B
Brian Anderson 已提交
2444
            for variant.args.each |aty| {
2445
                let sty = subst(cx, substs, *aty);
B
Brian Anderson 已提交
2446
                if type_structurally_contains(cx, sty, test) { return true; }
2447
            }
2448
        }
B
Brian Anderson 已提交
2449
        return false;
M
Marijn Haverbeke 已提交
2450
      }
2451 2452
      ty_struct(did, ref substs) => {
        for lookup_struct_fields(cx, did).each |field| {
2453
            let ft = lookup_field_type(cx, did, field.id, substs);
B
Brian Anderson 已提交
2454
            if type_structurally_contains(cx, ft, test) { return true; }
2455
        }
B
Brian Anderson 已提交
2456
        return false;
2457 2458
      }

2459
      ty_tup(ref ts) => {
B
Brian Anderson 已提交
2460
        for ts.each |tt| {
2461
            if type_structurally_contains(cx, *tt, test) { return true; }
2462
        }
B
Brian Anderson 已提交
2463
        return false;
2464
      }
2465
      ty_evec(ref mt, vstore_fixed(_)) => {
B
Brian Anderson 已提交
2466
        return type_structurally_contains(cx, mt.ty, test);
2467
      }
B
Brian Anderson 已提交
2468
      _ => return false
M
Marijn Haverbeke 已提交
2469 2470 2471
    }
}

2472
pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
2473
    return type_structurally_contains(cx, ty, |sty| {
N
Niko Matsakis 已提交
2474
        match *sty {
2475 2476
          ty_uniq(_) |
          ty_evec(_, vstore_uniq) |
B
Brian Anderson 已提交
2477 2478
          ty_estr(vstore_uniq) => true,
          _ => false,
2479
        }
2480
    });
2481 2482
}

2483
pub fn type_is_integral(ty: t) -> bool {
2484
    match get(ty).sty {
2485
      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
B
Brian Anderson 已提交
2486
      _ => false
M
Marijn Haverbeke 已提交
2487 2488 2489
    }
}

2490
pub fn type_is_char(ty: t) -> bool {
2491 2492 2493 2494 2495 2496
    match get(ty).sty {
        ty_int(ty_char) => true,
        _ => false
    }
}

2497
pub fn type_is_fp(ty: t) -> bool {
2498
    match get(ty).sty {
2499
      ty_infer(FloatVar(_)) | ty_float(_) => true,
B
Brian Anderson 已提交
2500
      _ => false
M
Marijn Haverbeke 已提交
2501 2502 2503
    }
}

2504
pub fn type_is_numeric(ty: t) -> bool {
B
Brian Anderson 已提交
2505
    return type_is_integral(ty) || type_is_fp(ty);
2506 2507
}

2508
pub fn type_is_signed(ty: t) -> bool {
2509
    match get(ty).sty {
B
Brian Anderson 已提交
2510 2511
      ty_int(_) => true,
      _ => false
M
Marijn Haverbeke 已提交
2512 2513 2514
    }
}

S
Seo Sanghyeon 已提交
2515 2516 2517 2518 2519 2520 2521 2522
pub fn type_is_machine(ty: t) -> bool {
    match get(ty).sty {
        ty_int(ast::ty_i) | ty_uint(ast::ty_u) | ty_float(ast::ty_f) => false,
        ty_int(*) | ty_uint(*) | ty_float(*) => true,
        _ => false
    }
}

2523 2524
// Whether a type is Plain Old Data -- meaning it does not contain pointers
// that the cycle collector might care about.
2525
pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
2526
    let mut result = true;
2527
    match get(ty).sty {
B
Brian Anderson 已提交
2528
      // Scalar types
2529
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
2530
      ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
B
Brian Anderson 已提交
2531
      // Boxed types
2532
      ty_box(_) | ty_uniq(_) | ty_closure(_) |
2533 2534
      ty_estr(vstore_uniq) | ty_estr(vstore_box) |
      ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2535
      ty_trait(_, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
B
Brian Anderson 已提交
2536
      // Structural types
N
Niko Matsakis 已提交
2537
      ty_enum(did, ref substs) => {
2538
        let variants = enum_variants(cx, did);
2539
        for (*variants).each |variant| {
2540
            let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
B
Brian Anderson 已提交
2541 2542

            // Perform any type parameter substitutions.
2543
            let tup_ty = subst(cx, substs, tup_ty);
B
Brian Anderson 已提交
2544
            if !type_is_pod(cx, tup_ty) { result = false; }
2545
        }
B
Brian Anderson 已提交
2546
      }
2547
      ty_tup(ref elts) => {
2548
        for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
B
Brian Anderson 已提交
2549
      }
B
Brian Anderson 已提交
2550
      ty_estr(vstore_fixed(_)) => result = true,
2551
      ty_evec(ref mt, vstore_fixed(_)) | ty_unboxed_vec(ref mt) => {
2552 2553
        result = type_is_pod(cx, mt.ty);
      }
B
Brian Anderson 已提交
2554 2555
      ty_param(_) => result = false,
      ty_opaque_closure_ptr(_) => result = true,
2556 2557
      ty_struct(did, ref substs) => {
        result = vec::any(lookup_struct_fields(cx, did), |f| {
2558 2559 2560
            let fty = ty::lookup_item_type(cx, f.id);
            let sty = subst(cx, substs, fty.ty);
            type_is_pod(cx, sty)
2561
        });
2562
      }
2563

B
Brian Anderson 已提交
2564
      ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2565 2566 2567
        result = false;
      }

2568
      ty_infer(*) | ty_self(*) | ty_err => {
2569
        cx.sess.bug(~"non concrete type in type_is_pod");
2570
      }
P
Patrick Walton 已提交
2571 2572
    }

B
Brian Anderson 已提交
2573
    return result;
P
Patrick Walton 已提交
2574 2575
}

2576
pub fn type_is_enum(ty: t) -> bool {
2577
    match get(ty).sty {
B
Brian Anderson 已提交
2578 2579
      ty_enum(_, _) => return true,
      _ => return false
2580 2581 2582
    }
}

P
Patrick Walton 已提交
2583
// Whether a type is enum like, that is a enum type with only nullary
2584
// constructors
2585
pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2586
    match get(ty).sty {
2587 2588 2589 2590 2591 2592 2593 2594 2595
        ty_enum(did, _) => {
            let variants = enum_variants(cx, did);
            if variants.len() == 0 {
                false
            } else {
                variants.all(|v| v.args.len() == 0)
            }
        }
        _ => false
2596 2597 2598
    }
}

2599
pub fn type_param(ty: t) -> Option<uint> {
2600
    match get(ty).sty {
B
Brian Anderson 已提交
2601
      ty_param(p) => return Some(p.idx),
B
Brian Anderson 已提交
2602
      _ => {/* fall through */ }
2603
    }
B
Brian Anderson 已提交
2604
    return None;
2605 2606
}

2607 2608
// Returns the type and mutability of *t.
//
2609 2610
// The parameter `explicit` indicates if this is an *explicit* dereference.
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
2611
pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
2612
    deref_sty(cx, &get(t).sty, explicit)
2613
}
2614

2615
pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
N
Niko Matsakis 已提交
2616
    match *sty {
B
Brian Anderson 已提交
2617
      ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
B
Brian Anderson 已提交
2618
        Some(mt)
2619 2620
      }

2621
      ty_ptr(mt) if explicit => {
B
Brian Anderson 已提交
2622
        Some(mt)
2623 2624
      }

N
Niko Matsakis 已提交
2625
      ty_enum(did, ref substs) => {
2626 2627 2628
        let variants = enum_variants(cx, did);
        if vec::len(*variants) == 1u && vec::len(variants[0].args) == 1u {
            let v_t = subst(cx, substs, variants[0].args[0]);
2629
            Some(mt {ty: v_t, mutbl: ast::m_imm})
2630
        } else {
B
Brian Anderson 已提交
2631
            None
2632 2633 2634
        }
      }

2635 2636
      ty_struct(did, ref substs) => {
        let fields = struct_fields(cx, did, substs);
2637 2638
        if fields.len() == 1 && fields[0].ident ==
                syntax::parse::token::special_idents::unnamed_field {
2639
            Some(mt {ty: fields[0].mt.ty, mutbl: ast::m_imm})
2640 2641 2642 2643 2644
        } else {
            None
        }
      }

B
Brian Anderson 已提交
2645
      _ => None
2646 2647 2648
    }
}

2649
pub fn type_autoderef(cx: ctxt, t: t) -> t {
2650
    let mut t = t;
2651
    loop {
2652
        match deref(cx, t, false) {
B
Brian Anderson 已提交
2653 2654
          None => return t,
          Some(mt) => t = mt.ty
2655 2656
        }
    }
2657 2658 2659
}

// Returns the type and mutability of t[i]
T
Tim Chevalier 已提交
2660 2661
pub fn index(t: t) -> Option<mt> {
    index_sty(&get(t).sty)
2662 2663
}

T
Tim Chevalier 已提交
2664
pub fn index_sty(sty: &sty) -> Option<mt> {
N
Niko Matsakis 已提交
2665
    match *sty {
B
Brian Anderson 已提交
2666
      ty_evec(mt, _) => Some(mt),
T
Tim Chevalier 已提交
2667
      ty_estr(_) => Some(mt {ty: mk_u8(), mutbl: ast::m_imm}),
B
Brian Anderson 已提交
2668
      _ => None
2669
    }
2670 2671
}

2672 2673 2674 2675 2676 2677 2678 2679 2680 2681
/**
 * Enforces an arbitrary but consistent total ordering over
 * free regions.  This is needed for establishing a consistent
 * LUB in region_inference. */
impl cmp::TotalOrd for FreeRegion {
    fn cmp(&self, other: &FreeRegion) -> Ordering {
        cmp::cmp2(&self.scope_id, &self.bound_region,
                  &other.scope_id, &other.bound_region)
    }
}
2682

2683 2684 2685 2686 2687
impl cmp::TotalEq for FreeRegion {
    fn equals(&self, other: &FreeRegion) -> bool {
        *self == *other
    }
}
2688

2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710
/**
 * Enforces an arbitrary but consistent total ordering over
 * bound regions.  This is needed for establishing a consistent
 * LUB in region_inference. */
impl cmp::TotalOrd for bound_region {
    fn cmp(&self, other: &bound_region) -> Ordering {
        match (self, other) {
            (&ty::br_self, &ty::br_self) => cmp::Equal,
            (&ty::br_self, _) => cmp::Less,

            (&ty::br_anon(ref a1), &ty::br_anon(ref a2)) => a1.cmp(a2),
            (&ty::br_anon(*), _) => cmp::Less,

            (&ty::br_named(ref a1), &ty::br_named(ref a2)) => a1.repr.cmp(&a2.repr),
            (&ty::br_named(*), _) => cmp::Less,

            (&ty::br_cap_avoid(ref a1, @ref b1),
             &ty::br_cap_avoid(ref a2, @ref b2)) => cmp::cmp2(a1, b1, a2, b2),
            (&ty::br_cap_avoid(*), _) => cmp::Less,

            (&ty::br_fresh(ref a1), &ty::br_fresh(ref a2)) => a1.cmp(a2),
            (&ty::br_fresh(*), _) => cmp::Less,
2711 2712 2713
        }
    }
}
2714

2715 2716 2717
impl cmp::TotalEq for bound_region {
    fn equals(&self, other: &bound_region) -> bool {
        *self == *other
2718 2719 2720
    }
}

2721
#[cfg(stage0)]
2722
impl to_bytes::IterBytes for vstore {
2723
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735
        match *self {
          vstore_fixed(ref u) =>
          to_bytes::iter_bytes_2(&0u8, u, lsb0, f),

          vstore_uniq => 1u8.iter_bytes(lsb0, f),
          vstore_box => 2u8.iter_bytes(lsb0, f),

          vstore_slice(ref r) =>
          to_bytes::iter_bytes_2(&3u8, r, lsb0, f),
        }
    }
}
2736 2737 2738 2739 2740 2741
#[cfg(not(stage0))]
impl to_bytes::IterBytes for vstore {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
          vstore_fixed(ref u) =>
          to_bytes::iter_bytes_2(&0u8, u, lsb0, f),
2742

2743 2744 2745 2746 2747 2748 2749 2750 2751 2752
          vstore_uniq => 1u8.iter_bytes(lsb0, f),
          vstore_box => 2u8.iter_bytes(lsb0, f),

          vstore_slice(ref r) =>
          to_bytes::iter_bytes_2(&3u8, r, lsb0, f),
        }
    }
}

#[cfg(stage0)]
2753
impl to_bytes::IterBytes for substs {
2754
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2755 2756 2757 2758 2759
          to_bytes::iter_bytes_3(&self.self_r,
                                 &self.self_ty,
                                 &self.tps, lsb0, f)
    }
}
2760 2761 2762 2763 2764 2765 2766 2767
#[cfg(not(stage0))]
impl to_bytes::IterBytes for substs {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
          to_bytes::iter_bytes_3(&self.self_r,
                                 &self.self_ty,
                                 &self.tps, lsb0, f)
    }
}
2768

2769
#[cfg(stage0)]
2770
impl to_bytes::IterBytes for mt {
2771
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2772 2773 2774 2775
          to_bytes::iter_bytes_2(&self.ty,
                                 &self.mutbl, lsb0, f)
    }
}
2776 2777 2778 2779 2780 2781 2782
#[cfg(not(stage0))]
impl to_bytes::IterBytes for mt {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
          to_bytes::iter_bytes_2(&self.ty,
                                 &self.mutbl, lsb0, f)
    }
}
2783

2784
#[cfg(stage0)]
2785
impl to_bytes::IterBytes for field {
2786
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2787 2788 2789 2790
          to_bytes::iter_bytes_2(&self.ident,
                                 &self.mt, lsb0, f)
    }
}
2791 2792 2793 2794 2795 2796 2797
#[cfg(not(stage0))]
impl to_bytes::IterBytes for field {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
          to_bytes::iter_bytes_2(&self.ident,
                                 &self.mt, lsb0, f)
    }
}
2798

2799
#[cfg(stage0)]
2800
impl to_bytes::IterBytes for FnSig {
2801
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2802 2803 2804 2805 2806
        to_bytes::iter_bytes_2(&self.inputs,
                               &self.output,
                               lsb0, f);
    }
}
2807 2808 2809 2810 2811 2812 2813 2814
#[cfg(not(stage0))]
impl to_bytes::IterBytes for FnSig {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        to_bytes::iter_bytes_2(&self.inputs,
                               &self.output,
                               lsb0, f)
    }
}
2815

2816
#[cfg(stage0)]
2817
impl to_bytes::IterBytes for sty {
2818
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842
        match *self {
          ty_nil => 0u8.iter_bytes(lsb0, f),
          ty_bool => 1u8.iter_bytes(lsb0, f),

          ty_int(ref t) =>
          to_bytes::iter_bytes_2(&2u8, t, lsb0, f),

          ty_uint(ref t) =>
          to_bytes::iter_bytes_2(&3u8, t, lsb0, f),

          ty_float(ref t) =>
          to_bytes::iter_bytes_2(&4u8, t, lsb0, f),

          ty_estr(ref v) =>
          to_bytes::iter_bytes_2(&5u8, v, lsb0, f),

          ty_enum(ref did, ref substs) =>
          to_bytes::iter_bytes_3(&6u8, did, substs, lsb0, f),

          ty_box(ref mt) =>
          to_bytes::iter_bytes_2(&7u8, mt, lsb0, f),

          ty_evec(ref mt, ref v) =>
          to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f),
2843 2844 2845 2846 2847 2848 2849

          ty_unboxed_vec(ref mt) =>
          to_bytes::iter_bytes_2(&9u8, mt, lsb0, f),

          ty_tup(ref ts) =>
          to_bytes::iter_bytes_2(&10u8, ts, lsb0, f),

2850
          ty_bare_fn(ref ft) =>
2851
          to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
2852

2853
          ty_self(ref did) => to_bytes::iter_bytes_2(&13u8, did, lsb0, f),
2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869

          ty_infer(ref v) =>
          to_bytes::iter_bytes_2(&14u8, v, lsb0, f),

          ty_param(ref p) =>
          to_bytes::iter_bytes_2(&15u8, p, lsb0, f),

          ty_type => 16u8.iter_bytes(lsb0, f),
          ty_bot => 17u8.iter_bytes(lsb0, f),

          ty_ptr(ref mt) =>
          to_bytes::iter_bytes_2(&18u8, mt, lsb0, f),

          ty_uniq(ref mt) =>
          to_bytes::iter_bytes_2(&19u8, mt, lsb0, f),

2870 2871
          ty_trait(ref did, ref substs, ref v, ref mutbl) =>
          to_bytes::iter_bytes_5(&20u8, did, substs, v, mutbl, lsb0, f),
2872 2873 2874 2875 2876 2877

          ty_opaque_closure_ptr(ref ck) =>
          to_bytes::iter_bytes_2(&21u8, ck, lsb0, f),

          ty_opaque_box => 22u8.iter_bytes(lsb0, f),

2878
          ty_struct(ref did, ref substs) =>
2879 2880 2881 2882
          to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f),

          ty_rptr(ref r, ref mt) =>
          to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),
2883

2884 2885 2886 2887
          ty_err => 25u8.iter_bytes(lsb0, f),

          ty_closure(ref ct) =>
          to_bytes::iter_bytes_2(&26u8, ct, lsb0, f),
2888 2889 2890
        }
    }
}
2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965
#[cfg(not(stage0))]
impl to_bytes::IterBytes for sty {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
          ty_nil => 0u8.iter_bytes(lsb0, f),
          ty_bool => 1u8.iter_bytes(lsb0, f),

          ty_int(ref t) =>
          to_bytes::iter_bytes_2(&2u8, t, lsb0, f),

          ty_uint(ref t) =>
          to_bytes::iter_bytes_2(&3u8, t, lsb0, f),

          ty_float(ref t) =>
          to_bytes::iter_bytes_2(&4u8, t, lsb0, f),

          ty_estr(ref v) =>
          to_bytes::iter_bytes_2(&5u8, v, lsb0, f),

          ty_enum(ref did, ref substs) =>
          to_bytes::iter_bytes_3(&6u8, did, substs, lsb0, f),

          ty_box(ref mt) =>
          to_bytes::iter_bytes_2(&7u8, mt, lsb0, f),

          ty_evec(ref mt, ref v) =>
          to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f),

          ty_unboxed_vec(ref mt) =>
          to_bytes::iter_bytes_2(&9u8, mt, lsb0, f),

          ty_tup(ref ts) =>
          to_bytes::iter_bytes_2(&10u8, ts, lsb0, f),

          ty_bare_fn(ref ft) =>
          to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),

          ty_self(ref did) => to_bytes::iter_bytes_2(&13u8, did, lsb0, f),

          ty_infer(ref v) =>
          to_bytes::iter_bytes_2(&14u8, v, lsb0, f),

          ty_param(ref p) =>
          to_bytes::iter_bytes_2(&15u8, p, lsb0, f),

          ty_type => 16u8.iter_bytes(lsb0, f),
          ty_bot => 17u8.iter_bytes(lsb0, f),

          ty_ptr(ref mt) =>
          to_bytes::iter_bytes_2(&18u8, mt, lsb0, f),

          ty_uniq(ref mt) =>
          to_bytes::iter_bytes_2(&19u8, mt, lsb0, f),

          ty_trait(ref did, ref substs, ref v, ref mutbl) =>
          to_bytes::iter_bytes_5(&20u8, did, substs, v, mutbl, lsb0, f),

          ty_opaque_closure_ptr(ref ck) =>
          to_bytes::iter_bytes_2(&21u8, ck, lsb0, f),

          ty_opaque_box => 22u8.iter_bytes(lsb0, f),

          ty_struct(ref did, ref substs) =>
          to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f),

          ty_rptr(ref r, ref mt) =>
          to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),

          ty_err => 25u8.iter_bytes(lsb0, f),

          ty_closure(ref ct) =>
          to_bytes::iter_bytes_2(&26u8, ct, lsb0, f),
        }
    }
}
2966

2967 2968 2969 2970 2971 2972 2973 2974 2975 2976
pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef {
    match cx.trait_refs.find(&id) {
       Some(&t) => t,
       None => cx.sess.bug(
           fmt!("node_id_to_trait_ref: no trait ref for node `%s`",
                ast_map::node_id_to_str(cx.items, id,
                                        cx.sess.parse_sess.interner)))
    }
}

2977
pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
2978
    //io::println(fmt!("%?/%?", id, cx.node_types.len()));
D
Daniel Micay 已提交
2979 2980
    match cx.node_types.find(&(id as uint)) {
       Some(&t) => t,
B
Brian Anderson 已提交
2981
       None => cx.sess.bug(
2982
           fmt!("node_id_to_type: no type for node `%s`",
P
Paul Stansifer 已提交
2983
                ast_map::node_id_to_str(cx.items, id,
P
Paul Stansifer 已提交
2984
                                        cx.sess.parse_sess.interner)))
T
Tim Chevalier 已提交
2985
    }
2986 2987
}

2988
pub fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2989
    match cx.node_type_substs.find(&id) {
B
Brian Anderson 已提交
2990
      None => return ~[],
2991
      Some(ts) => return /*bad*/ copy *ts
2992 2993 2994
    }
}

2995
fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
2996
    cx.node_type_substs.contains_key(&id)
2997 2998
}

2999 3000 3001 3002 3003 3004 3005 3006 3007 3008
pub fn ty_fn_sig(fty: t) -> FnSig {
    match get(fty).sty {
        ty_bare_fn(ref f) => copy f.sig,
        ty_closure(ref f) => copy f.sig,
        ref s => {
            fail!(fmt!("ty_fn_sig() called on non-fn type: %?", s))
        }
    }
}

3009
// Type accessors for substructures of types
3010
pub fn ty_fn_args(fty: t) -> ~[arg] {
3011
    match get(fty).sty {
3012 3013 3014
        ty_bare_fn(ref f) => copy f.sig.inputs,
        ty_closure(ref f) => copy f.sig.inputs,
        ref s => {
3015
            fail!(fmt!("ty_fn_args() called on non-fn type: %?", s))
3016
        }
3017 3018 3019
    }
}

3020
pub fn ty_closure_sigil(fty: t) -> Sigil {
3021
    match get(fty).sty {
3022 3023
        ty_closure(ref f) => f.sigil,
        ref s => {
3024 3025
            fail!(fmt!("ty_closure_sigil() called on non-closure type: %?",
                       s))
3026
        }
M
Marijn Haverbeke 已提交
3027
    }
G
Graydon Hoare 已提交
3028 3029
}

3030
pub fn ty_fn_purity(fty: t) -> ast::purity {
3031
    match get(fty).sty {
3032 3033 3034
        ty_bare_fn(ref f) => f.purity,
        ty_closure(ref f) => f.purity,
        ref s => {
3035
            fail!(fmt!("ty_fn_purity() called on non-fn type: %?", s))
3036
        }
3037 3038 3039
    }
}

3040
pub fn ty_fn_ret(fty: t) -> t {
3041
    match get(fty).sty {
3042 3043 3044
        ty_bare_fn(ref f) => f.sig.output,
        ty_closure(ref f) => f.sig.output,
        ref s => {
3045
            fail!(fmt!("ty_fn_ret() called on non-fn type: %?", s))
3046
        }
3047
    }
G
Graydon Hoare 已提交
3048 3049
}

3050
pub fn is_fn_ty(fty: t) -> bool {
3051
    match get(fty).sty {
3052 3053 3054
        ty_bare_fn(_) => true,
        ty_closure(_) => true,
        _ => false
3055 3056 3057
    }
}

3058
pub fn ty_vstore(ty: t) -> vstore {
3059 3060 3061
    match get(ty).sty {
        ty_evec(_, vstore) => vstore,
        ty_estr(vstore) => vstore,
3062
        ref s => fail!(fmt!("ty_vstore() called on invalid sty: %?", s))
3063 3064 3065
    }
}

3066 3067 3068
pub fn ty_region(tcx: ctxt,
                 span: span,
                 ty: t) -> Region {
3069
    match get(ty).sty {
3070 3071 3072 3073 3074 3075 3076 3077
        ty_rptr(r, _) => r,
        ty_evec(_, vstore_slice(r)) => r,
        ty_estr(vstore_slice(r)) => r,
        ref s => {
            tcx.sess.span_bug(
                span,
                fmt!("ty_region() invoked on in appropriate ty: %?", s));
        }
3078
    }
G
Graydon Hoare 已提交
3079 3080
}

N
Niko Matsakis 已提交
3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091
pub fn replace_fn_sig(cx: ctxt, fsty: &sty, new_sig: FnSig) -> t {
    match *fsty {
        ty_bare_fn(ref f) => mk_bare_fn(cx, BareFnTy {sig: new_sig, ..*f}),
        ty_closure(ref f) => mk_closure(cx, ClosureTy {sig: new_sig, ..*f}),
        ref s => {
            cx.sess.bug(
                fmt!("ty_fn_sig() called on non-fn type: %?", s));
        }
    }
}

3092
pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
3093 3094 3095 3096 3097 3098
    /*!
     *
     * Returns a new function type based on `fn_type` but returning a value of
     * type `ret_type` instead. */

    match ty::get(fn_type).sty {
3099 3100 3101 3102
        ty::ty_closure(ref fty) => {
            ty::mk_closure(tcx, ClosureTy {
                sig: FnSig {output: ret_type, ..copy fty.sig},
                ..copy *fty
3103 3104 3105 3106 3107 3108 3109 3110 3111 3112
            })
        }
        _ => {
            tcx.sess.bug(fmt!(
                "replace_fn_ret() invoked with non-fn-type: %s",
                ty_to_str(tcx, fn_type)));
        }
    }
}

3113
// Returns a vec of all the input and output types of fty.
3114
pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
3115
    vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
3116 3117
}

3118
// Type accessors for AST nodes
3119
pub fn block_ty(cx: ctxt, b: &ast::blk) -> t {
B
Brian Anderson 已提交
3120
    return node_id_to_type(cx, b.node.id);
3121
}
3122 3123


3124 3125
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
3126
pub fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
B
Brian Anderson 已提交
3127
    return node_id_to_type(cx, pat.id);
3128 3129
}

3130

3131 3132
// Returns the type of an expression as a monotype.
//
3133 3134 3135 3136 3137 3138
// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
// some cases, we insert `AutoAdjustment` annotations such as auto-deref or
// auto-ref.  The type returned by this function does not consider such
// adjustments.  See `expr_ty_adjusted()` instead.
//
// NB (2): This type doesn't provide type parameter substitutions; e.g. if you
3139
// ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
3140
// instead of "fn(t) -> T with T = int". If this isn't what you want, see
3141
// expr_ty_params_and_ty() below.
3142
pub fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
B
Brian Anderson 已提交
3143
    return node_id_to_type(cx, expr.id);
3144 3145
}

3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160
pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t {
    /*!
     *
     * Returns the type of `expr`, considering any `AutoAdjustment`
     * entry recorded for that expression.
     *
     * It would almost certainly be better to store the adjusted ty in with
     * the `AutoAdjustment`, but I opted not to do this because it would
     * require serializing and deserializing the type and, although that's not
     * hard to do, I just hate that code so much I didn't want to touch it
     * unless it was to fix it properly, which seemed a distraction from the
     * task at hand! -nmatsakis
     */

    let unadjusted_ty = expr_ty(cx, expr);
3161
    adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find_copy(&expr.id))
3162 3163 3164 3165 3166
}

pub fn adjust_ty(cx: ctxt,
                 span: span,
                 unadjusted_ty: ty::t,
3167
                 adjustment: Option<@AutoAdjustment>) -> ty::t
3168 3169
{
    /*! See `expr_ty_adjusted` */
3170

3171
    return match adjustment {
3172 3173
        None => unadjusted_ty,

3174
        Some(@AutoAddEnv(r, s)) => {
3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191
            match ty::get(unadjusted_ty).sty {
                ty::ty_bare_fn(ref b) => {
                    ty::mk_closure(
                        cx,
                        ty::ClosureTy {purity: b.purity,
                                       sigil: s,
                                       onceness: ast::Many,
                                       region: r,
                                       sig: copy b.sig})
                }
                ref b => {
                    cx.sess.bug(
                        fmt!("add_env adjustment on non-bare-fn: %?", b));
                }
            }
        }

3192
        Some(@AutoDerefRef(ref adj)) => {
3193 3194 3195 3196 3197 3198 3199
            let mut adjusted_ty = unadjusted_ty;

            for uint::range(0, adj.autoderefs) |i| {
                match ty::deref(cx, adjusted_ty, true) {
                    Some(mt) => { adjusted_ty = mt.ty; }
                    None => {
                        cx.sess.span_bug(
3200
                            span,
3201 3202 3203 3204 3205 3206 3207 3208 3209 3210
                            fmt!("The %uth autoderef failed: %s",
                                 i, ty_to_str(cx,
                                              adjusted_ty)));
                    }
                }
            }

            match adj.autoref {
                None => adjusted_ty,
                Some(ref autoref) => {
N
Niko Matsakis 已提交
3211 3212 3213
                    match *autoref {
                        AutoPtr(r, m) => {
                            mk_rptr(cx, r, mt {ty: adjusted_ty, mutbl: m})
3214 3215
                        }

N
Niko Matsakis 已提交
3216 3217
                        AutoBorrowVec(r, m) => {
                            borrow_vec(cx, span, r, m, adjusted_ty)
3218 3219
                        }

N
Niko Matsakis 已提交
3220 3221 3222
                        AutoBorrowVecRef(r, m) => {
                            adjusted_ty = borrow_vec(cx, span, r, m, adjusted_ty);
                            mk_rptr(cx, r, mt {ty: adjusted_ty, mutbl: ast::m_imm})
3223 3224
                        }

N
Niko Matsakis 已提交
3225 3226 3227 3228 3229 3230
                        AutoBorrowFn(r) => {
                            borrow_fn(cx, span, r, adjusted_ty)
                        }

                        AutoUnsafe(m) => {
                            mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
3231 3232 3233 3234 3235 3236 3237
                        }
                    }
                }
            }
        }
    };

3238
    fn borrow_vec(cx: ctxt, span: span,
N
Niko Matsakis 已提交
3239 3240
                  r: Region, m: ast::mutability,
                  ty: ty::t) -> ty::t {
3241 3242
        match get(ty).sty {
            ty_evec(mt, _) => {
N
Niko Matsakis 已提交
3243
                ty::mk_evec(cx, mt {ty: mt.ty, mutbl: m}, vstore_slice(r))
3244 3245 3246
            }

            ty_estr(_) => {
N
Niko Matsakis 已提交
3247
                ty::mk_estr(cx, vstore_slice(r))
3248 3249 3250 3251
            }

            ref s => {
                cx.sess.span_bug(
3252
                    span,
3253 3254 3255 3256 3257 3258
                    fmt!("borrow-vec associated with bad sty: %?",
                         s));
            }
        }
    }

N
Niko Matsakis 已提交
3259
    fn borrow_fn(cx: ctxt, span: span, r: Region, ty: ty::t) -> ty::t {
3260
        match get(ty).sty {
3261 3262 3263
            ty_closure(ref fty) => {
                ty::mk_closure(cx, ClosureTy {
                    sigil: BorrowedSigil,
N
Niko Matsakis 已提交
3264
                    region: r,
3265 3266
                    ..copy *fty
                })
3267 3268 3269 3270
            }

            ref s => {
                cx.sess.span_bug(
3271
                    span,
3272 3273 3274 3275 3276 3277 3278
                    fmt!("borrow-fn associated with bad sty: %?",
                         s));
            }
        }
    }
}

N
Niko Matsakis 已提交
3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290
pub impl AutoRef {
    fn map_region(&self, f: &fn(Region) -> Region) -> AutoRef {
        match *self {
            ty::AutoPtr(r, m) => ty::AutoPtr(f(r), m),
            ty::AutoBorrowVec(r, m) => ty::AutoBorrowVec(f(r), m),
            ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(f(r), m),
            ty::AutoBorrowFn(r) => ty::AutoBorrowFn(f(r)),
            ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
        }
    }
}

3291 3292 3293 3294 3295
pub struct ParamsTy {
    params: ~[t],
    ty: t
}

3296 3297
pub fn expr_ty_params_and_ty(cx: ctxt,
                             expr: @ast::expr)
3298 3299 3300 3301 3302
                          -> ParamsTy {
    ParamsTy {
        params: node_id_to_type_params(cx, expr.id),
        ty: node_id_to_type(cx, expr.id)
    }
3303 3304
}

3305
pub fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
B
Brian Anderson 已提交
3306
    return node_id_has_type_params(cx, expr.id);
3307 3308
}

3309 3310 3311 3312 3313
pub fn method_call_type_param_defs(
    tcx: ctxt,
    method_map: typeck::method_map,
    id: ast::node_id) -> Option<@~[TypeParameterDef]>
{
3314
    do method_map.find(&id).map |method| {
3315 3316
        match method.origin {
          typeck::method_static(did) => {
3317 3318
            // n.b.: When we encode impl methods, the bounds
            // that we encode include both the impl bounds
3319
            // and then the method bounds themselves...
3320
            ty::lookup_item_type(tcx, did).generics.type_param_defs
3321
          }
3322 3323 3324
          typeck::method_param(typeck::method_param {
              trait_id: trt_id,
              method_num: n_mth, _}) |
3325
          typeck::method_trait(trt_id, n_mth, _) |
3326 3327
          typeck::method_self(trt_id, n_mth) |
          typeck::method_super(trt_id, n_mth) => {
3328 3329 3330
            // ...trait methods bounds, in contrast, include only the
            // method bounds, so we must preprend the tps from the
            // trait itself.  This ought to be harmonized.
3331 3332 3333 3334 3335
            let trait_type_param_defs =
                ty::lookup_trait_def(tcx, trt_id).generics.type_param_defs;
            @vec::append(
                copy *trait_type_param_defs,
                *ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs)
3336 3337 3338 3339 3340
          }
        }
    }
}

3341
pub fn resolve_expr(tcx: ctxt, expr: @ast::expr) -> ast::def {
3342
    match tcx.def_map.find(&expr.id) {
3343
        Some(&def) => def,
3344 3345 3346 3347 3348 3349 3350
        None => {
            tcx.sess.span_bug(expr.span, fmt!(
                "No def-map entry for expr %?", expr.id));
        }
    }
}

3351 3352 3353
pub fn expr_is_lval(tcx: ctxt,
                    method_map: typeck::method_map,
                    e: @ast::expr) -> bool {
3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364
    match expr_kind(tcx, method_map, e) {
        LvalueExpr => true,
        RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
    }
}

/// We categorize expressions into three kinds.  The distinction between
/// lvalue/rvalue is fundamental to the language.  The distinction between the
/// two kinds of rvalues is an artifact of trans which reflects how we will
/// generate code for that kind of expression.  See trans/expr.rs for more
/// information.
3365
pub enum ExprKind {
3366 3367 3368 3369 3370 3371
    LvalueExpr,
    RvalueDpsExpr,
    RvalueDatumExpr,
    RvalueStmtExpr
}

3372 3373 3374
pub fn expr_kind(tcx: ctxt,
                 method_map: typeck::method_map,
                 expr: @ast::expr) -> ExprKind {
3375
    if method_map.contains_key(&expr.id) {
3376 3377 3378 3379 3380 3381 3382 3383 3384 3385
        // Overloaded operations are generally calls, and hence they are
        // generated via DPS.  However, assign_op (e.g., `x += y`) is an
        // exception, as its result is always unit.
        return match expr.node {
            ast::expr_assign_op(*) => RvalueStmtExpr,
            _ => RvalueDpsExpr
        };
    }

    match expr.node {
3386
        ast::expr_path(*) | ast::expr_self => {
3387
            match resolve_expr(tcx, expr) {
3388
                ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3389

3390 3391 3392
                // Fn pointers are just scalar values.
                ast::def_fn(*) | ast::def_static_method(*) => RvalueDatumExpr,

3393 3394 3395 3396 3397 3398 3399 3400 3401 3402
                // Note: there is actually a good case to be made that
                // def_args, particularly those of immediate type, ought to
                // considered rvalues.
                ast::def_const(*) |
                ast::def_binding(*) |
                ast::def_upvar(*) |
                ast::def_arg(*) |
                ast::def_local(*) |
                ast::def_self(*) => LvalueExpr,

L
Luqman Aden 已提交
3403
                def => {
3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417
                    tcx.sess.span_bug(expr.span, fmt!(
                        "Uncategorized def for expr %?: %?",
                        expr.id, def));
                }
            }
        }

        ast::expr_unary(ast::deref, _) |
        ast::expr_field(*) |
        ast::expr_index(*) => {
            LvalueExpr
        }

        ast::expr_call(*) |
3418
        ast::expr_method_call(*) |
3419 3420 3421 3422 3423 3424 3425 3426 3427 3428
        ast::expr_struct(*) |
        ast::expr_tup(*) |
        ast::expr_if(*) |
        ast::expr_match(*) |
        ast::expr_fn_block(*) |
        ast::expr_loop_body(*) |
        ast::expr_do_body(*) |
        ast::expr_block(*) |
        ast::expr_copy(*) |
        ast::expr_repeat(*) |
J
John Clements 已提交
3429
        ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
3430
        ast::expr_vstore(_, ast::expr_vstore_slice) |
3431
        ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3432 3433 3434 3435 3436
        ast::expr_vec(*) => {
            RvalueDpsExpr
        }

        ast::expr_cast(*) => {
D
Daniel Micay 已提交
3437 3438
            match tcx.node_types.find(&(expr.id as uint)) {
                Some(&t) => {
3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468
                    if ty::type_is_immediate(t) {
                        RvalueDatumExpr
                    } else {
                        RvalueDpsExpr
                    }
                }
                None => {
                    // Technically, it should not happen that the expr is not
                    // present within the table.  However, it DOES happen
                    // during type check, because the final types from the
                    // expressions are not yet recorded in the tcx.  At that
                    // time, though, we are only interested in knowing lvalue
                    // vs rvalue.  It would be better to base this decision on
                    // the AST type in cast node---but (at the time of this
                    // writing) it's not easy to distinguish casts to traits
                    // from other casts based on the AST.  This should be
                    // easier in the future, when casts to traits would like
                    // like @Foo, ~Foo, or &Foo.
                    RvalueDatumExpr
                }
            }
        }

        ast::expr_break(*) |
        ast::expr_again(*) |
        ast::expr_ret(*) |
        ast::expr_log(*) |
        ast::expr_while(*) |
        ast::expr_loop(*) |
        ast::expr_assign(*) |
3469
        ast::expr_inline_asm(*) |
3470 3471 3472 3473 3474 3475 3476 3477
        ast::expr_assign_op(*) => {
            RvalueStmtExpr
        }

        ast::expr_lit(_) | // Note: lit_str is carved out above
        ast::expr_unary(*) |
        ast::expr_addr_of(*) |
        ast::expr_binary(*) |
3478
        ast::expr_vstore(_, ast::expr_vstore_box) |
3479
        ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3480
        ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3481 3482 3483
            RvalueDatumExpr
        }

3484 3485
        ast::expr_paren(e) => expr_kind(tcx, method_map, e),

3486 3487 3488
        ast::expr_mac(*) => {
            tcx.sess.span_bug(
                expr.span,
S
Seo Sanghyeon 已提交
3489
                "macro expression remains after expansion");
3490
        }
M
Marijn Haverbeke 已提交
3491 3492 3493
    }
}

3494
pub fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3495
    match s.node {
B
Brian Anderson 已提交
3496
      ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
B
Brian Anderson 已提交
3497
        return id;
3498
      }
3499
      ast::stmt_mac(*) => fail!(~"unexpanded macro in trans")
3500 3501 3502
    }
}

3503
pub fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3504
    let mut i = 0u;
B
Brian Anderson 已提交
3505 3506
    for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
    return None;
3507 3508
}

3509 3510
pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
                     -> uint {
3511 3512 3513 3514
    let mut i = 0u;
    for fields.each |f| { if f.ident == id { return i; } i += 1u; }
    tcx.sess.bug(fmt!(
        "No field named `%s` found in the list of fields `%?`",
3515
        *tcx.sess.str_of(id),
3516 3517 3518
        fields.map(|f| tcx.sess.str_of(f.ident))));
}

3519 3520
pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option<uint> {
    vec::position(meths, |m| m.ident == id)
3521 3522
}

3523 3524 3525
/// Returns a vector containing the indices of all type parameters that appear
/// in `ty`.  The vector may contain duplicates.  Probably should be converted
/// to a bitset or some other representation.
3526
pub fn param_tys_in_type(ty: t) -> ~[param_ty] {
3527 3528
    let mut rslt = ~[];
    do walk_ty(ty) |ty| {
3529
        match get(ty).sty {
B
Brian Anderson 已提交
3530
          ty_param(p) => {
3531
            rslt.push(p);
3532
          }
B
Brian Anderson 已提交
3533
          _ => ()
3534 3535 3536 3537 3538
        }
    }
    rslt
}

3539
pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3540 3541
    // Returns a vec of all the type variables occurring in `ty`. It may
    // contain duplicates.  (Integral type vars aren't counted.)
3542
    fn vars_in_type(ty: t) -> ~[TyVid] {
3543
        let mut rslt = ~[];
B
Brian Anderson 已提交
3544
        do walk_ty(ty) |ty| {
3545
            match get(ty).sty {
3546
              ty_infer(TyVar(v)) => rslt.push(v),
B
Brian Anderson 已提交
3547 3548
              _ => ()
            }
3549 3550 3551 3552
        }
        rslt
    }

3553
    // Fast path
B
Brian Anderson 已提交
3554
    if !type_needs_infer(rt) { return; }
B
Brian Anderson 已提交
3555

T
Tim Chevalier 已提交
3556
    // Occurs check!
N
Niko Matsakis 已提交
3557
    if vec::contains(vars_in_type(rt), &vid) {
T
Tim Chevalier 已提交
3558 3559 3560
            // Maybe this should be span_err -- however, there's an
            // assertion later on that the type doesn't contain
            // variables, so in this case we have to be sure to die.
3561
            tcx.sess.span_fatal
3562
                (sp, ~"type inference failed because I \
3563
                     could not find a type\n that's both of the form "
3564 3565
                 + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
                 ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
3566
                 ~" - such a type would have to be infinitely large.");
3567
    }
T
Tim Chevalier 已提交
3568
}
3569

3570
pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3571
    match get(t).sty {
N
Niko Matsakis 已提交
3572
      ty_nil | ty_bot | ty_bool | ty_int(_) |
M
Michael Sullivan 已提交
3573
      ty_uint(_) | ty_float(_) | ty_estr(_) |
B
Brian Anderson 已提交
3574
      ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
3575
        ::util::ppaux::ty_to_str(cx, t)
N
Niko Matsakis 已提交
3576 3577
      }

P
Paul Stansifer 已提交
3578
      ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3579 3580 3581 3582 3583 3584
      ty_box(_) => ~"@-ptr",
      ty_uniq(_) => ~"~-ptr",
      ty_evec(_, _) => ~"vector",
      ty_unboxed_vec(_) => ~"unboxed vector",
      ty_ptr(_) => ~"*-ptr",
      ty_rptr(_, _) => ~"&-ptr",
3585 3586
      ty_bare_fn(_) => ~"extern fn",
      ty_closure(_) => ~"fn",
3587
      ty_trait(id, _, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3588
      ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3589
      ty_tup(_) => ~"tuple",
3590 3591
      ty_infer(TyVar(_)) => ~"inferred type",
      ty_infer(IntVar(_)) => ~"integral variable",
3592
      ty_infer(FloatVar(_)) => ~"floating-point variable",
B
Brian Anderson 已提交
3593
      ty_param(_) => ~"type parameter",
3594
      ty_self(_) => ~"self",
3595
      ty_err => ~"type error"
N
Niko Matsakis 已提交
3596 3597 3598
    }
}

3599
pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3600 3601 3602 3603 3604 3605 3606 3607 3608
    /*!
     *
     * Explains the source of a type err in a short,
     * human readable way.  This is meant to be placed in
     * parentheses after some larger message.  You should
     * also invoke `note_and_explain_type_err()` afterwards
     * to present additional details, particularly when
     * it comes to lifetime-related errors. */

3609
    fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3610 3611 3612
        match k {
            terr_vec => ~"[]",
            terr_str => ~"str",
3613 3614
            terr_fn => ~"fn",
            terr_trait => ~"trait"
3615
        }
3616 3617
    }

N
Niko Matsakis 已提交
3618
    match *err {
3619 3620 3621
        terr_mismatch => ~"types differ",
        terr_purity_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3622
                 values.expected.to_str(), values.found.to_str())
3623
        }
3624 3625 3626 3627
        terr_abi_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
                 values.expected.to_str(), values.found.to_str())
        }
3628 3629
        terr_onceness_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3630
                 values.expected.to_str(), values.found.to_str())
3631
        }
3632
        terr_sigil_mismatch(values) => {
3633
            fmt!("expected %s closure, found %s closure",
3634 3635
                 values.expected.to_str(),
                 values.found.to_str())
3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
        }
        terr_mutability => ~"values differ in mutability",
        terr_box_mutability => ~"boxed values differ in mutability",
        terr_vec_mutability => ~"vectors differ in mutability",
        terr_ptr_mutability => ~"pointers differ in mutability",
        terr_ref_mutability => ~"references differ in mutability",
        terr_ty_param_size(values) => {
            fmt!("expected a type with %? type params \
                  but found one with %? type params",
                 values.expected, values.found)
        }
        terr_tuple_size(values) => {
            fmt!("expected a tuple with %? elements \
                  but found one with %? elements",
                 values.expected, values.found)
        }
        terr_record_size(values) => {
            fmt!("expected a record with %? fields \
                  but found one with %? fields",
                 values.expected, values.found)
        }
        terr_record_mutability => {
            ~"record elements differ in mutability"
        }
        terr_record_fields(values) => {
            fmt!("expected a record with field `%s` but found one with field \
                  `%s`",
3663 3664
                 *cx.sess.str_of(values.expected),
                 *cx.sess.str_of(values.found))
3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685
        }
        terr_arg_count => ~"incorrect number of function parameters",
        terr_regions_does_not_outlive(*) => {
            fmt!("lifetime mismatch")
        }
        terr_regions_not_same(*) => {
            fmt!("lifetimes are not the same")
        }
        terr_regions_no_overlap(*) => {
            fmt!("lifetimes do not intersect")
        }
        terr_regions_insufficiently_polymorphic(br, _) => {
            fmt!("expected bound lifetime parameter %s, \
                  but found concrete lifetime",
                 bound_region_to_str(cx, br))
        }
        terr_regions_overly_polymorphic(br, _) => {
            fmt!("expected concrete lifetime, \
                  but found bound lifetime parameter %s",
                 bound_region_to_str(cx, br))
        }
3686
        terr_vstores_differ(k, ref values) => {
3687 3688
            fmt!("%s storage differs: expected %s but found %s",
                 terr_vstore_kind_to_str(k),
3689 3690
                 vstore_to_str(cx, (*values).expected),
                 vstore_to_str(cx, (*values).found))
3691
        }
3692 3693 3694 3695 3696
        terr_trait_stores_differ(_, ref values) => {
            fmt!("trait storage differs: expected %s but found %s",
                 trait_store_to_str(cx, (*values).expected),
                 trait_store_to_str(cx, (*values).found))
        }
3697
        terr_in_field(err, fname) => {
3698
            fmt!("in field `%s`, %s", *cx.sess.str_of(fname),
3699 3700 3701 3702 3703 3704 3705
                 type_err_to_str(cx, err))
        }
        terr_sorts(values) => {
            fmt!("expected %s but found %s",
                 ty_sort_str(cx, values.expected),
                 ty_sort_str(cx, values.found))
        }
3706 3707 3708 3709 3710
        terr_traits(values) => {
            fmt!("expected trait %s but found trait %s",
                 item_path_str(cx, values.expected),
                 item_path_str(cx, values.found))
        }
3711 3712 3713
        terr_self_substs => {
            ~"inconsistent self substitution" // XXX this is more of a bug
        }
3714
        terr_integer_as_char => {
3715
            fmt!("expected an integral type but found char")
3716
        }
3717 3718 3719 3720 3721 3722 3723 3724 3725
        terr_int_mismatch(ref values) => {
            fmt!("expected %s but found %s",
                 values.expected.to_str(),
                 values.found.to_str())
        }
        terr_float_mismatch(ref values) => {
            fmt!("expected %s but found %s",
                 values.expected.to_str(),
                 values.found.to_str())
3726
        }
3727 3728 3729
    }
}

3730
pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746
    match *err {
        terr_regions_does_not_outlive(subregion, superregion) => {
            note_and_explain_region(cx, ~"", subregion, ~"...");
            note_and_explain_region(cx, ~"...does not necessarily outlive ",
                                    superregion, ~"");
        }
        terr_regions_not_same(region1, region2) => {
            note_and_explain_region(cx, ~"", region1, ~"...");
            note_and_explain_region(cx, ~"...is not the same lifetime as ",
                                    region2, ~"");
        }
        terr_regions_no_overlap(region1, region2) => {
            note_and_explain_region(cx, ~"", region1, ~"...");
            note_and_explain_region(cx, ~"...does not overlap ",
                                    region2, ~"");
        }
3747 3748 3749 3750 3751 3752 3753 3754 3755 3756
        terr_regions_insufficiently_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
                                    ~"concrete lifetime that was found is ",
                                    conc_region, ~"");
        }
        terr_regions_overly_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
                                    ~"expected concrete lifetime is ",
                                    conc_region, ~"");
        }
3757 3758 3759 3760
        _ => {}
    }
}

3761
pub fn def_has_ty_params(def: ast::def) -> bool {
3762
    match def {
3763
      ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
B
Brian Anderson 已提交
3764 3765
        => true,
      _ => false
3766 3767 3768
    }
}

3769
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3770
    if is_local(id) {
3771
        match cx.items.find(&id.node) {
A
Alex Crichton 已提交
3772
            Some(&ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
3773 3774 3775
                        node: item_trait(_, _, ref ms),
                        _
                    }, _)) =>
3776
                match ast_util::split_trait_methods(*ms) {
3777
                   (_, p) => p.map(|method| method.ident)
3778
                },
3779
            _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3780 3781
                                  id))
        }
3782
    } else {
3783
        csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3784 3785 3786
    }
}

3787
pub fn trait_supertraits(cx: ctxt,
3788 3789
                         id: ast::def_id) -> @~[@TraitRef]
{
3790
    // Check the cache.
3791
    match cx.supertraits.find(&id) {
3792
        Some(&trait_refs) => { return trait_refs; }
3793 3794 3795 3796 3797
        None => {}  // Continue.
    }

    // Not in the cache. It had better be in the metadata, which means it
    // shouldn't be local.
P
Patrick Walton 已提交
3798
    assert!(!is_local(id));
3799 3800

    // Get the supertraits out of the metadata and create the
3801 3802 3803 3804
    // TraitRef for each.
    let result = @csearch::get_supertraits(cx, id);
    cx.supertraits.insert(id, result);
    return result;
3805
}
3806

3807 3808 3809
pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] {
    let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
    supertrait_refs.map(
3810
        |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs))
3811 3812
}

3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857
fn lookup_locally_or_in_crate_store<V:Copy>(
    descr: &str,
    def_id: ast::def_id,
    map: &mut HashMap<ast::def_id, V>,
    load_external: &fn() -> V) -> V
{
    /*!
     *
     * Helper for looking things up in the various maps
     * that are populated during typeck::collect (e.g.,
     * `cx.methods`, `cx.tcache`, etc).  All of these share
     * the pattern that if the id is local, it should have
     * been loaded into the map by the `typeck::collect` phase.
     * If the def-id is external, then we have to go consult
     * the crate loading code (and cache the result for the future).
     */

    match map.find(&def_id) {
        Some(&v) => { return v; }
        None => { }
    }

    if def_id.crate == ast::local_crate {
        fail!(fmt!("No def'n found for %? in tcx.%s",
                   def_id, descr));
    }
    let v = load_external();
    map.insert(def_id, v);
    return v;
}

pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method {
    let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
    ty::method(cx, method_def_id)
}

pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
    match cx.trait_methods_cache.find(&trait_did) {
        Some(&methods) => methods,
        None => {
            let def_ids = ty::trait_method_def_ids(cx, trait_did);
            let methods = @def_ids.map(|d| ty::method(cx, *d));
            cx.trait_methods_cache.insert(trait_did, methods);
            methods
        }
3858 3859
    }
}
3860

3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872
pub fn method(cx: ctxt, id: ast::def_id) -> @method {
    lookup_locally_or_in_crate_store(
        "methods", id, cx.methods,
        || @csearch::get_method(cx, id))
}

pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
    lookup_locally_or_in_crate_store(
        "methods", id, cx.trait_method_def_ids,
        || @csearch::get_trait_method_def_ids(cx.cstore, id))
}

3873
pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] {
3874
    if id.crate == ast::local_crate {
P
Paul Stansifer 已提交
3875
        debug!("(impl_traits) searching for trait impl %?", id);
3876
        match cx.items.find(&id.node) {
A
Alex Crichton 已提交
3877
           Some(&ast_map::node_item(@ast::item {
3878
                        node: ast::item_impl(_, opt_trait, _, _),
3879
                        _},
B
Brian Anderson 已提交
3880
                    _)) => {
3881 3882 3883
               match opt_trait {
                   Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)],
                   None => ~[]
3884
               }
3885
           }
B
Brian Anderson 已提交
3886
           _ => ~[]
3887
        }
3888
    } else {
3889
        csearch::get_impl_traits(cx, id)
3890 3891 3892
    }
}

3893
pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3894
    match get(ty).sty {
3895
      ty_trait(id, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
B
Brian Anderson 已提交
3896
      _ => None
3897 3898 3899
    }
}

3900 3901 3902 3903 3904 3905 3906 3907 3908
/// Returns the def ID of the constructor for the given tuple-like struct, or
/// None if the struct is not tuple-like. Fails if the given def ID does not
/// refer to a struct at all.
fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option<ast::def_id> {
    if struct_did.crate != ast::local_crate {
        // XXX: Cross-crate functionality.
        cx.sess.unimpl(~"constructor ID of cross-crate tuple structs");
    }

3909
    match cx.items.find(&struct_did.node) {
A
Alex Crichton 已提交
3910
        Some(&ast_map::node_item(item, _)) => {
3911
            match item.node {
3912
                ast::item_struct(struct_def, _) => {
3913 3914 3915 3916 3917 3918 3919 3920 3921 3922
                    struct_def.ctor_id.map(|ctor_id|
                        ast_util::local_def(*ctor_id))
                }
                _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
            }
        }
        _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
    }
}

3923
// Enum information
3924
pub struct VariantInfo_ {
3925 3926 3927 3928 3929 3930 3931 3932
    args: ~[t],
    ctor_ty: t,
    name: ast::ident,
    id: ast::def_id,
    disr_val: int,
    vis: visibility
}

3933
pub type VariantInfo = @VariantInfo_;
M
Marijn Haverbeke 已提交
3934

3935 3936 3937 3938
pub fn substd_enum_variants(cx: ctxt,
                            id: ast::def_id,
                            substs: &substs)
                         -> ~[VariantInfo] {
B
Brian Anderson 已提交
3939 3940
    do vec::map(*enum_variants(cx, id)) |variant_info| {
        let substd_args = vec::map(variant_info.args,
3941
                                   |aty| subst(cx, substs, *aty));
3942

3943
        let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3944

3945
        @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
3946
                      ../*bad*/copy **variant_info}
3947 3948 3949
    }
}

3950
pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
P
Paul Stansifer 已提交
3951
    ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3952 3953
}

3954
pub enum DtorKind {
3955 3956 3957 3958
    NoDtor,
    TraitDtor(def_id)
}

3959
pub impl DtorKind {
3960
    fn is_not_present(&const self) -> bool {
3961 3962 3963 3964 3965
        match *self {
            NoDtor => true,
            _ => false
        }
    }
3966
    fn is_present(&const self) -> bool {
3967 3968 3969 3970
        !self.is_not_present()
    }
}

3971
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
3972
   Otherwise return none. */
3973
pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
3974
    match cx.destructor_for_type.find(&struct_id) {
E
Erick Tryzelaar 已提交
3975
        Some(&method_def_id) => TraitDtor(method_def_id),
3976
        None => NoDtor,
3977 3978 3979
    }
}

3980
pub fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
3981
    ty_dtor(cx, struct_id).is_present()
3982 3983
}

3984
pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
3985 3986 3987
    if id.crate != ast::local_crate {
        csearch::get_item_path(cx, id)
    } else {
A
Alex Crichton 已提交
3988 3989 3990 3991 3992 3993
        // FIXME (#5521): uncomment this code and don't have a catch-all at the
        //                end of the match statement. Favor explicitly listing
        //                each variant.
        // let node = cx.items.get(&id.node);
        // match *node {
        match *cx.items.get(&id.node) {
B
Brian Anderson 已提交
3994
          ast_map::node_item(item, path) => {
3995
            let item_elt = match item.node {
B
Brian Anderson 已提交
3996
              item_mod(_) | item_foreign_mod(_) => {
3997 3998
                ast_map::path_mod(item.ident)
              }
B
Brian Anderson 已提交
3999
              _ => {
4000 4001 4002
                ast_map::path_name(item.ident)
              }
            };
4003
            vec::append_one(/*bad*/copy *path, item_elt)
4004 4005
          }

4006
          ast_map::node_foreign_item(nitem, _, _, path) => {
4007 4008
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(nitem.ident))
4009 4010
          }

B
Brian Anderson 已提交
4011
          ast_map::node_method(method, _, path) => {
4012 4013
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
4014
          }
B
Brian Anderson 已提交
4015
          ast_map::node_trait_method(trait_method, _, path) => {
4016
            let method = ast_util::trait_method_to_ty_method(&*trait_method);
4017 4018
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
4019
          }
4020

4021
          ast_map::node_variant(ref variant, _, path) => {
4022
            vec::append_one(vec::to_owned(vec::init(*path)),
4023
                            ast_map::path_name((*variant).node.name))
4024 4025
          }

4026
          ast_map::node_struct_ctor(_, item, path) => {
4027
            vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
4028 4029
          }

A
Alex Crichton 已提交
4030
          ref node => {
P
Paul Stansifer 已提交
4031
            cx.sess.bug(fmt!("cannot find item_path for node %?", node));
4032 4033 4034 4035 4036
          }
        }
    }
}

4037
pub fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
4038
    enum_variants(cx, id).len() == 1
4039 4040
}

4041
pub fn type_is_empty(cx: ctxt, t: t) -> bool {
4042
    match ty::get(t).sty {
B
Brian Anderson 已提交
4043 4044
       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
       _ => false
4045 4046 4047
     }
}

4048
pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
4049
    match cx.enum_var_cache.find(&id) {
4050
      Some(&variants) => return variants,
B
Brian Anderson 已提交
4051
      _ => { /* fallthrough */ }
4052
    }
4053

4054
    let result = if ast::local_crate != id.crate {
4055
        @csearch::get_enum_variants(cx, id)
4056
    } else {
4057 4058 4059 4060 4061
        /*
          Although both this code and check_enum_variants in typeck/check
          call eval_const_expr, it should never get called twice for the same
          expr, since check_enum_variants also updates the enum_var_cache
         */
4062
        match cx.items.get_copy(&id.node) {
4063
          ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
4064 4065 4066
                    node: ast::item_enum(ref enum_definition, _),
                    _
                }, _) => {
4067
            let mut disr_val = -1;
4068
            @vec::map(enum_definition.variants, |variant| {
4069
                match variant.node.kind {
4070
                    ast::tuple_variant_kind(ref args) => {
4071 4072
                        let ctor_ty = node_id_to_type(cx, variant.node.id);
                        let arg_tys = {
4073
                            if args.len() > 0u {
4074 4075 4076 4077 4078 4079
                                ty_fn_args(ctor_ty).map(|a| a.ty)
                            } else {
                                ~[]
                            }
                        };
                        match variant.node.disr_expr {
B
Brian Anderson 已提交
4080
                          Some (ex) => {
4081 4082 4083 4084 4085 4086 4087 4088
                            disr_val = match const_eval::eval_const_expr(cx,
                                                                         ex) {
                              const_eval::const_int(val) => val as int,
                              _ => cx.sess.bug(~"tag_variants: bad disr expr")
                            }
                          }
                          _ => disr_val += 1
                        }
4089
                        @VariantInfo_{args: arg_tys,
4090 4091 4092
                          ctor_ty: ctor_ty,
                          name: variant.node.name,
                          id: ast_util::local_def(variant.node.id),
4093 4094
                          disr_val: disr_val,
                          vis: variant.node.vis
4095
                         }
4096
                    }
4097
                    ast::struct_variant_kind(_) => {
4098
                        fail!(~"struct variant kinds unimpl in enum_variants")
4099
                    }
4100
                }
4101
            })
M
Marijn Haverbeke 已提交
4102
          }
B
Brian Anderson 已提交
4103
          _ => cx.sess.bug(~"tag_variants: id not bound to an enum")
4104
        }
4105
    };
4106
    cx.enum_var_cache.insert(id, result);
4107
    result
4108 4109
}

4110

P
Patrick Walton 已提交
4111
// Returns information about the enum variant with the given ID:
4112 4113 4114 4115
pub fn enum_variant_with_id(cx: ctxt,
                            enum_id: ast::def_id,
                            variant_id: ast::def_id)
                         -> VariantInfo {
4116
    let variants = enum_variants(cx, enum_id);
4117 4118
    let mut i = 0;
    while i < variants.len() {
B
Brian Anderson 已提交
4119
        let variant = variants[i];
4120
        if variant.id == variant_id { return variant; }
4121
        i += 1;
4122
    }
4123
    cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
4124 4125
}

4126

4127 4128
// If the given item is in an external crate, looks up its type and adds it to
// the type cache. Returns the type parameters and type.
4129 4130 4131
pub fn lookup_item_type(cx: ctxt,
                        did: ast::def_id)
                     -> ty_param_bounds_and_ty {
4132 4133 4134
    lookup_locally_or_in_crate_store(
        "tcache", did, cx.tcache,
        || csearch::get_type(cx, did))
T
Tim Chevalier 已提交
4135 4136
}

4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153
/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
    match cx.trait_defs.find(&did) {
        Some(&trait_def) => {
            // The item is in this crate. The caller should have added it to the
            // type cache already
            return trait_def;
        }
        None => {
            assert!(did.crate != ast::local_crate);
            let trait_def = @csearch::get_trait_def(cx, did);
            cx.trait_defs.insert(did, trait_def);
            return trait_def;
        }
    }
}

4154 4155
/// Determine whether an item is annotated with an attribute
pub fn has_attr(tcx: ctxt, did: def_id, attr: &str) -> bool {
4156 4157 4158 4159 4160 4161
    if is_local(did) {
        match tcx.items.find(&did.node) {
            Some(
                &ast_map::node_item(@ast::item {
                    attrs: ref attrs,
                    _
4162
                }, _)) => attr::attrs_contains_name(*attrs, attr),
S
Seo Sanghyeon 已提交
4163
            _ => tcx.sess.bug(fmt!("has_attr: %? is not an item",
4164 4165 4166 4167 4168
                                   did))
        }
    } else {
        let mut ret = false;
        do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
4169
            ret = attr::contains_name(meta_items, attr);
4170 4171 4172 4173 4174
        }
        ret
    }
}

S
Seo Sanghyeon 已提交
4175
/// Determine whether an item is annotated with `#[packed]`
4176 4177 4178 4179
pub fn lookup_packed(tcx: ctxt, did: def_id) -> bool {
    has_attr(tcx, did, "packed")
}

S
Seo Sanghyeon 已提交
4180
/// Determine whether an item is annotated with `#[simd]`
S
Seo Sanghyeon 已提交
4181 4182 4183 4184
pub fn lookup_simd(tcx: ctxt, did: def_id) -> bool {
    has_attr(tcx, did, "simd")
}

T
Tim Chevalier 已提交
4185
// Look up a field ID, whether or not it's local
4186
// Takes a list of type substs in case the struct is generic
4187 4188 4189 4190 4191
pub fn lookup_field_type(tcx: ctxt,
                         struct_id: def_id,
                         id: def_id,
                         substs: &substs)
                      -> ty::t {
4192
    let t = if id.crate == ast::local_crate {
T
Tim Chevalier 已提交
4193 4194 4195
        node_id_to_type(tcx, id.node)
    }
    else {
4196
        match tcx.tcache.find(&id) {
N
Niko Matsakis 已提交
4197
           Some(&ty_param_bounds_and_ty {ty, _}) => ty,
B
Brian Anderson 已提交
4198
           None => {
4199
               let tpt = csearch::get_field_type(tcx, struct_id, id);
T
Tim Chevalier 已提交
4200
               tcx.tcache.insert(id, tpt);
4201
               tpt.ty
T
Tim Chevalier 已提交
4202 4203
           }
        }
4204
    };
4205
    subst(tcx, substs, t)
T
Tim Chevalier 已提交
4206 4207
}

4208 4209
// Look up the list of field names and IDs for a given struct
// Fails if the id is not bound to a struct.
4210
pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
4211
  if did.crate == ast::local_crate {
4212
    match cx.items.find(&did.node) {
A
Alex Crichton 已提交
4213
       Some(&ast_map::node_item(i,_)) => {
4214
         match i.node {
4215
            ast::item_struct(struct_def, _) => {
4216
               struct_field_tys(struct_def.fields)
4217
            }
4218
            _ => cx.sess.bug(~"struct ID bound to non-struct")
T
Tim Chevalier 已提交
4219
         }
T
Tim Chevalier 已提交
4220
       }
A
Alex Crichton 已提交
4221
       Some(&ast_map::node_variant(ref variant, _, _)) => {
4222
          match (*variant).node.kind {
4223
            ast::struct_variant_kind(struct_def) => {
4224
              struct_field_tys(struct_def.fields)
4225 4226 4227 4228 4229 4230 4231
            }
            _ => {
              cx.sess.bug(~"struct ID bound to enum variant that isn't \
                            struct-like")
            }
          }
       }
B
Brian Anderson 已提交
4232
       _ => {
P
Paul Stansifer 已提交
4233
           cx.sess.bug(
4234
               fmt!("struct ID not bound to an item: %s",
P
Paul Stansifer 已提交
4235
                    ast_map::node_id_to_str(cx.items, did.node,
P
Paul Stansifer 已提交
4236
                                            cx.sess.parse_sess.interner)));
4237
       }
T
Tim Chevalier 已提交
4238
    }
T
Tim Chevalier 已提交
4239
        }
4240
  else {
4241
        return csearch::get_struct_fields(cx.sess.cstore, did);
T
Tim Chevalier 已提交
4242 4243 4244
    }
}

4245 4246 4247 4248
pub fn lookup_struct_field(cx: ctxt,
                           parent: ast::def_id,
                           field_id: ast::def_id)
                        -> field_ty {
4249
    match vec::find(lookup_struct_fields(cx, parent),
B
Brian Anderson 已提交
4250
                 |f| f.id.node == field_id.node) {
B
Brian Anderson 已提交
4251
        Some(t) => t,
4252
        None => cx.sess.bug(~"struct ID not found in parent's fields")
4253 4254 4255
    }
}

4256
fn struct_field_tys(fields: &[@struct_field]) -> ~[field_ty] {
4257
    do fields.map |field| {
4258
        match field.node.kind {
4259
            named_field(ident, visibility) => {
4260 4261 4262 4263 4264
                field_ty {
                    ident: ident,
                    id: ast_util::local_def(field.node.id),
                    vis: visibility,
                }
4265
            }
4266
            unnamed_field => {
4267 4268 4269 4270 4271 4272
                field_ty {
                    ident:
                        syntax::parse::token::special_idents::unnamed_field,
                    id: ast_util::local_def(field.node.id),
                    vis: ast::public,
                }
4273
            }
4274
        }
T
Tim Chevalier 已提交
4275
    }
T
Tim Chevalier 已提交
4276 4277
}

4278 4279 4280 4281
// Returns a list of fields corresponding to the struct's items. trans uses
// this. Takes a list of substs with which to instantiate field types.
pub fn struct_fields(cx: ctxt, did: ast::def_id, substs: &substs)
                     -> ~[field] {
4282
    do lookup_struct_fields(cx, did).map |f| {
4283
       field {
4284
            ident: f.ident,
4285 4286
            mt: mt {
                ty: lookup_field_type(cx, did, f.id, substs),
4287
                mutbl: m_imm
4288 4289
            }
        }
T
Tim Chevalier 已提交
4290 4291 4292
    }
}

4293
pub fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308
    static tycat_other: int = 0;
    static tycat_bool: int = 1;
    static tycat_int: int = 2;
    static tycat_float: int = 3;
    static tycat_struct: int = 4;
    static tycat_bot: int = 5;

    static opcat_add: int = 0;
    static opcat_sub: int = 1;
    static opcat_mult: int = 2;
    static opcat_shift: int = 3;
    static opcat_rel: int = 4;
    static opcat_eq: int = 5;
    static opcat_bit: int = 6;
    static opcat_logic: int = 7;
M
Marijn Haverbeke 已提交
4309 4310

    fn opcat(op: ast::binop) -> int {
4311
        match op {
B
Brian Anderson 已提交
4312 4313 4314
          ast::add => opcat_add,
          ast::subtract => opcat_sub,
          ast::mul => opcat_mult,
4315
          ast::div => opcat_mult,
B
Brian Anderson 已提交
4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329
          ast::rem => opcat_mult,
          ast::and => opcat_logic,
          ast::or => opcat_logic,
          ast::bitxor => opcat_bit,
          ast::bitand => opcat_bit,
          ast::bitor => opcat_bit,
          ast::shl => opcat_shift,
          ast::shr => opcat_shift,
          ast::eq => opcat_eq,
          ast::ne => opcat_eq,
          ast::lt => opcat_rel,
          ast::le => opcat_rel,
          ast::ge => opcat_rel,
          ast::gt => opcat_rel
M
Marijn Haverbeke 已提交
4330 4331 4332
        }
    }

4333
    fn tycat(ty: t) -> int {
4334
        match get(ty).sty {
B
Brian Anderson 已提交
4335
          ty_bool => tycat_bool,
4336
          ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4337
          ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
4338
          ty_tup(_) | ty_enum(_, _) => tycat_struct,
B
Brian Anderson 已提交
4339 4340
          ty_bot => tycat_bot,
          _ => tycat_other
M
Marijn Haverbeke 已提交
4341 4342 4343
        }
    }

4344 4345
    static t: bool = true;
    static f: bool = false;
4346

4347
    let tbl = ~[
4348 4349 4350
    /*.          add,     shift,   bit
      .             sub,     rel,     logic
      .                mult,    eq,         */
4351
    /*other*/   ~[f, f, f, f, f, f, f, f],
4352 4353 4354
    /*bool*/    ~[f, f, f, f, t, t, t, t],
    /*int*/     ~[t, t, t, t, t, t, t, f],
    /*float*/   ~[t, t, t, f, t, t, f, f],
4355 4356
    /*bot*/     ~[f, f, f, f, f, f, f, f],
    /*struct*/  ~[t, t, t, t, f, f, t, t]];
B
Brian Anderson 已提交
4357

B
Brian Anderson 已提交
4358
    return tbl[tycat(ty)][opcat(op)];
4359 4360
}

4361 4362 4363 4364 4365
pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> ~[t] {
    vec::from_fn(generics.ty_params.len(), |i| {
        let id = generics.ty_params.get(i).id;
        ty::mk_param(tcx, i, ast_util::local_def(id))
    })
4366
}
4367

4368
/// Returns an equivalent type with all the typedefs and self regions removed.
4369
pub fn normalize_ty(cx: ctxt, t: t) -> t {
4370
    fn normalize_mt(cx: ctxt, mt: mt) -> mt {
4371
        mt { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
4372 4373 4374 4375 4376 4377 4378 4379
    }
    fn normalize_vstore(vstore: vstore) -> vstore {
        match vstore {
            vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
            vstore_slice(_) => vstore_slice(re_static)
        }
    }

4380
    match cx.normalized_cache.find(&t) {
4381
      Some(&t) => return t,
B
Brian Anderson 已提交
4382
      None => ()
B
Brian Anderson 已提交
4383 4384
    }

4385
    let t = match get(t).sty {
4386 4387 4388 4389
        ty_evec(mt, vstore) =>
            // This type has a vstore. Get rid of it
            mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),

4390 4391 4392 4393
        ty_estr(vstore) =>
            // This type has a vstore. Get rid of it
            mk_estr(cx, normalize_vstore(vstore)),

E
Erick Tryzelaar 已提交
4394
        ty_rptr(_, mt) =>
4395
            // This type has a region. Get rid of it
4396 4397
            mk_rptr(cx, re_static, normalize_mt(cx, mt)),

4398 4399 4400 4401
        ty_closure(ref closure_ty) => {
            mk_closure(cx, ClosureTy {
                region: ty::re_static,
                ..copy *closure_ty
4402 4403
            })
        }
4404

4405 4406
        ty_enum(did, ref r) =>
            match (*r).self_r {
B
Brian Anderson 已提交
4407
                Some(_) =>
4408
                    // Use re_static since trans doesn't care about regions
E
Eric Holk 已提交
4409
                    mk_enum(cx, did,
4410 4411 4412 4413 4414
                     substs {
                        self_r: Some(ty::re_static),
                        self_ty: None,
                        tps: /*bad*/copy (*r).tps
                     }),
B
Brian Anderson 已提交
4415
                None =>
4416 4417 4418
                    t
            },

4419
        ty_struct(did, ref r) =>
4420
            match (*r).self_r {
B
Brian Anderson 已提交
4421
              Some(_) =>
4422
                // Ditto.
4423 4424 4425
                mk_struct(cx, did, substs {self_r: Some(ty::re_static),
                                           self_ty: None,
                                           tps: /*bad*/copy (*r).tps}),
B
Brian Anderson 已提交
4426
              None =>
4427 4428 4429 4430 4431
                t
            },

        _ =>
            t
4432 4433
    };

4434
    let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
B
Brian Anderson 已提交
4435 4436
    let t_norm = mk_t(cx, sty);
    cx.normalized_cache.insert(t, t_norm);
B
Brian Anderson 已提交
4437
    return t_norm;
4438 4439
}

4440
// Returns the repeat count for a repeating vector expression.
4441
pub fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr) -> uint {
4442 4443
    match const_eval::eval_const_expr_partial(tcx, count_expr) {
      Ok(ref const_val) => match *const_val {
4444 4445 4446
        const_eval::const_int(count) => return count as uint,
        const_eval::const_uint(count) => return count as uint,
        const_eval::const_float(count) => {
4447
            tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4448 4449
                              "expected signed or unsigned integer for \
                               repeat count but found float");
4450 4451 4452
            return count as uint;
        }
        const_eval::const_str(_) => {
4453
            tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4454 4455
                              "expected signed or unsigned integer for \
                               repeat count but found string");
4456 4457
            return 0;
        }
4458
        const_eval::const_bool(_) => {
4459
            tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4460 4461
                              "expected signed or unsigned integer for \
                               repeat count but found boolean");
4462 4463
            return 0;
        }
4464 4465
      },
      Err(*) => {
4466
        tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4467 4468
                          "expected constant integer for repeat count \
                           but found variable");
4469 4470
        return 0;
      }
4471 4472 4473
    }
}

4474
// Determine what purity to check a nested function under
4475 4476 4477 4478
pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id),
                                  child: (ast::purity, ast::node_id),
                                  child_sigil: ast::Sigil)
                                    -> (ast::purity, ast::node_id) {
4479 4480 4481
    // If the closure is a stack closure and hasn't had some non-standard
    // purity inferred for it, then check it under its parent's purity.
    // Otherwise, use its own
4482
    match child_sigil {
4483 4484
        ast::BorrowedSigil if child.first() == ast::impure_fn => parent,
        _ => child
4485
    }
4486 4487
}

4488 4489
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
4490 4491 4492
// Here, the supertraits are the transitive closure of the supertrait
// relation on the supertraits from each bounded trait's constraint
// list.
4493
#[cfg(stage0)]
4494
pub fn each_bound_trait_and_supertraits(tcx: ctxt,
4495 4496 4497
                                        bounds: &ParamBounds,
                                        f: &fn(@TraitRef) -> bool) {
    for bounds.trait_bounds.each |&bound_trait_ref| {
4498
        let mut supertrait_set = HashMap::new();
4499
        let mut trait_refs = ~[];
4500
        let mut i = 0;
4501

4502 4503 4504
        // Seed the worklist with the trait from the bound
        supertrait_set.insert(bound_trait_ref.def_id, ());
        trait_refs.push(bound_trait_ref);
4505 4506

        // Add the given trait ty to the hash map
4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525
        while i < trait_refs.len() {
            debug!("each_bound_trait_and_supertraits(i=%?, trait_ref=%s)",
                   i, trait_refs[i].repr(tcx));

            if !f(trait_refs[i]) {
                return;
            }

            // Add supertraits to supertrait_set
            let supertrait_refs = trait_ref_supertraits(tcx, trait_refs[i]);
            for supertrait_refs.each |&supertrait_ref| {
                debug!("each_bound_trait_and_supertraits(supertrait_ref=%s)",
                       supertrait_ref.repr(tcx));

                let d_id = supertrait_ref.def_id;
                if !supertrait_set.contains_key(&d_id) {
                    // FIXME(#5527) Could have same trait multiple times
                    supertrait_set.insert(d_id, ());
                    trait_refs.push(supertrait_ref);
4526
                }
4527
            }
4528 4529 4530

            i += 1;
        }
4531 4532
    }
}
4533 4534 4535 4536 4537 4538 4539
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
// Here, the supertraits are the transitive closure of the supertrait
// relation on the supertraits from each bounded trait's constraint
// list.
#[cfg(not(stage0))]
pub fn each_bound_trait_and_supertraits(tcx: ctxt,
A
Alex Crichton 已提交
4540 4541 4542
                                        bounds: &ParamBounds,
                                        f: &fn(@TraitRef) -> bool) -> bool {
    for bounds.trait_bounds.each |&bound_trait_ref| {
4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578
        let mut supertrait_set = HashMap::new();
        let mut trait_refs = ~[];
        let mut i = 0;

        // Seed the worklist with the trait from the bound
        supertrait_set.insert(bound_trait_ref.def_id, ());
        trait_refs.push(bound_trait_ref);

        // Add the given trait ty to the hash map
        while i < trait_refs.len() {
            debug!("each_bound_trait_and_supertraits(i=%?, trait_ref=%s)",
                   i, trait_refs[i].repr(tcx));

            if !f(trait_refs[i]) {
                return false;
            }

            // Add supertraits to supertrait_set
            let supertrait_refs = trait_ref_supertraits(tcx, trait_refs[i]);
            for supertrait_refs.each |&supertrait_ref| {
                debug!("each_bound_trait_and_supertraits(supertrait_ref=%s)",
                       supertrait_ref.repr(tcx));

                let d_id = supertrait_ref.def_id;
                if !supertrait_set.contains_key(&d_id) {
                    // FIXME(#5527) Could have same trait multiple times
                    supertrait_set.insert(d_id, ());
                    trait_refs.push(supertrait_ref);
                }
            }

            i += 1;
        }
    }
    return true;
}
4579

4580
pub fn count_traits_and_supertraits(tcx: ctxt,
4581
                                    type_param_defs: &[TypeParameterDef]) -> uint {
4582
    let mut total = 0;
4583 4584
    for type_param_defs.each |type_param_def| {
        for each_bound_trait_and_supertraits(tcx, type_param_def.bounds) |_| {
4585 4586 4587 4588 4589 4590
            total += 1;
        }
    }
    return total;
}

4591
// Given a trait and a type, returns the impl of that type
4592
pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
4593 4594
    match tcx.trait_impls.find(&trait_id) {
        Some(ty_to_impl) => match ty_to_impl.find(&self_ty) {
4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606
            Some(the_impl) => the_impl.did,
            None => // try autoderef!
                match deref(tcx, self_ty, false) {
                    Some(some_ty) => get_impl_id(tcx, trait_id, some_ty.ty),
                    None => tcx.sess.bug(~"get_impl_id: no impl of trait for \
                                           this type")
            }
        },
        None => tcx.sess.bug(~"get_impl_id: trait isn't in trait_impls")
    }
}

4607 4608 4609
pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
    let ty_visitor_name = special_idents::ty_visitor;
    assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
4610
    let trait_ref = tcx.intrinsic_traits.get_copy(&ty_visitor_name);
4611
    (trait_ref,
4612
     mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore, ast::m_imm))
4613
}