ty.rs 133.2 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 17 18 19
use metadata;
use middle::const_eval;
use middle::freevars;
use middle::resolve::{Impl, MethodInfo};
use middle::resolve;
use middle::ty;
20
use middle::subst::Subst;
21 22 23
use middle::typeck;
use middle;
use util::ppaux::{note_and_explain_region, bound_region_to_str};
24
use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
25
use util::ppaux::{Repr, UserString};
26
use util::common::{indenter};
27
use util::enum_set::{EnumSet, CLike};
28

29
use core::ptr::to_unsafe_ptr;
30
use core::to_bytes;
31
use core::hashmap::{HashMap, HashSet};
D
Daniel Micay 已提交
32
use std::smallintmap::SmallIntMap;
P
Patrick Walton 已提交
33
use syntax::ast::*;
T
Tim Chevalier 已提交
34
use syntax::ast_util::is_local;
35
use syntax::ast_util;
36
use syntax::attr;
37
use syntax::codemap::span;
J
John Clements 已提交
38
use syntax::codemap;
39
use syntax::parse::token::special_idents;
40
use syntax::{ast, ast_map};
41 42
use syntax::opt_vec::OptVec;
use syntax::opt_vec;
43
use syntax::abi::AbiSet;
44
use syntax;
45

46
// Data types
47

48
#[deriving(Eq)]
49
pub struct field {
50 51 52
    ident: ast::ident,
    mt: mt
}
53

54
pub struct Method {
55
    ident: ast::ident,
56
    generics: ty::Generics,
57
    transformed_self_ty: Option<ty::t>,
58
    fty: BareFnTy,
59
    explicit_self: ast::explicit_self_,
60 61
    vis: ast::visibility,
    def_id: ast::def_id
62
}
63

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
pub impl Method {
    fn new(ident: ast::ident,
           generics: ty::Generics,
           transformed_self_ty: Option<ty::t>,
           fty: BareFnTy,
           explicit_self: ast::explicit_self_,
           vis: ast::visibility,
           def_id: ast::def_id) -> Method {
        // Check the invariants.
        if explicit_self == ast::sty_static {
            assert!(transformed_self_ty.is_none());
        } else {
            assert!(transformed_self_ty.is_some());
        }

       Method {
            ident: ident,
            generics: generics,
            transformed_self_ty: transformed_self_ty,
            fty: fty,
            explicit_self: explicit_self,
            vis: vis,
            def_id: def_id
        }
    }
}

91
#[deriving(Eq)]
92
pub struct mt {
93 94 95
    ty: t,
    mutbl: ast::mutability,
}
96

97
#[deriving(Eq, Encodable, Decodable)]
98
pub enum vstore {
99 100 101
    vstore_fixed(uint),
    vstore_uniq,
    vstore_box,
102
    vstore_slice(Region)
103 104
}

105
#[deriving(Eq, IterBytes, Encodable, Decodable)]
106 107 108 109 110 111
pub enum TraitStore {
    BoxTraitStore,              // @Trait
    UniqTraitStore,             // ~Trait
    RegionTraitStore(Region),   // &Trait
}

112 113
// XXX: This should probably go away at some point. Maybe after destructors
// do?
114
#[deriving(Eq, Encodable, Decodable)]
115 116 117 118 119
pub enum SelfMode {
    ByCopy,
    ByRef,
}

120
pub struct field_ty {
121 122 123
    ident: ident,
    id: def_id,
    vis: ast::visibility,
124
}
T
Tim Chevalier 已提交
125

126 127
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
128
#[deriving(Eq)]
129
pub struct creader_cache_key {
130 131 132
    cnum: int,
    pos: uint,
    len: uint
133
}
134

135
type creader_cache = @mut HashMap<creader_cache_key, t>;
136

137 138 139 140 141
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)
    }
}
142

143 144 145
struct intern_key {
    sty: *sty,
}
146

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

161 162 163 164 165 166 167
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)
        }
    }
}
168

169
pub enum ast_ty_to_ty_cache_entry {
170
    atttce_unresolved,  /* not resolved yet */
171
    atttce_resolved(t)  /* resolved to a type, irrespective of region */
172 173
}

174
pub type opt_region_variance = Option<region_variance>;
175

176
#[deriving(Eq, Decodable, Encodable)]
177
pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant }
178

179
#[deriving(Decodable, Encodable)]
180 181 182 183 184
pub enum AutoAdjustment {
    AutoAddEnv(ty::Region, ast::Sigil),
    AutoDerefRef(AutoDerefRef)
}

185
#[deriving(Decodable, Encodable)]
186
pub struct AutoDerefRef {
187 188
    autoderefs: uint,
    autoref: Option<AutoRef>
189
}
190

191
#[deriving(Decodable, Encodable)]
N
Niko Matsakis 已提交
192
pub enum AutoRef {
193
    /// Convert from T to &T
N
Niko Matsakis 已提交
194
    AutoPtr(Region, ast::mutability),
195

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

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

202
    /// Convert from @fn()/~fn()/&fn() to &fn()
N
Niko Matsakis 已提交
203 204 205 206
    AutoBorrowFn(Region),

    /// Convert from T to *T
    AutoUnsafe(ast::mutability)
207 208
}

209 210 211 212 213 214
// 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.
215
pub type ProvidedMethodsMap = @mut HashMap<def_id,@mut ~[@ProvidedMethodInfo]>;
216 217 218

// Stores the method info and definition ID of the associated trait method for
// each instantiation of each provided method.
219
pub struct ProvidedMethodInfo {
220 221 222 223
    method_info: @MethodInfo,
    trait_method_def_id: def_id
}

224
pub struct ProvidedMethodSource {
225 226 227 228
    method_id: ast::def_id,
    impl_id: ast::def_id
}

229 230 231
pub type ctxt = @ctxt_;

struct ctxt_ {
232
    diag: @syntax::diagnostic::span_handler,
233
    interner: @mut HashMap<intern_key, ~t_box_>,
234
    next_id: @mut uint,
235
    legacy_modes: bool,
236
    cstore: @mut metadata::cstore::CStore,
237 238 239
    sess: session::Session,
    def_map: resolve::DefMap,

240
    region_maps: @mut middle::region::RegionMaps,
241 242 243 244 245 246 247 248 249 250 251
    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.
252
    node_type_substs: @mut HashMap<node_id, ~[t]>,
253

254
    // Maps from a method to the method "descriptor"
255
    methods: @mut HashMap<def_id, @Method>,
256 257 258 259 260

    // 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
261
    trait_methods_cache: @mut HashMap<def_id, @~[@Method]>,
262

263 264 265
    trait_refs: @mut HashMap<node_id, @TraitRef>,
    trait_defs: @mut HashMap<def_id, @TraitDef>,

266
    items: ast_map::map,
267
    intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
268
    intrinsic_traits: @mut HashMap<ast::ident, @TraitRef>,
269 270 271 272
    freevars: freevars::freevar_map,
    tcache: type_cache,
    rcache: creader_cache,
    ccache: constness_cache,
273 274 275 276 277
    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]>,
278
    ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
279 280
    adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
    normalized_cache: @mut HashMap<t, t>,
281 282 283 284 285
    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,
286
    provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>,
287
    supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
288 289 290 291 292

    // 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.
293
    destructor_for_type: @mut HashMap<ast::def_id, ast::def_id>,
294 295

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

    // Maps a trait onto a mapping from self-ty to impl
299 300 301 302 303
    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>,
304 305 306 307 308

    // 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>,
309
}
310

311
pub enum tbox_flag {
312 313 314 315
    has_params = 1,
    has_self = 2,
    needs_infer = 4,
    has_regions = 8,
316
    has_ty_err = 16,
T
Tim Chevalier 已提交
317
    has_ty_bot = 32,
318 319 320 321 322 323

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

324
pub type t_box = &'static t_box_;
325

326
pub struct t_box_ {
327 328 329 330
    sty: sty,
    id: uint,
    flags: uint,
}
331

332 333 334 335 336 337
// 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 {}
338
pub type t = *t_opaque;
339

340
pub fn get(t: t) -> t_box {
341
    unsafe {
342 343
        let t2: t_box = cast::transmute(t);
        t2
344
    }
345 346
}

347
pub fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
348 349
    (tb.flags & (flag as uint)) != 0u
}
350
pub fn type_has_params(t: t) -> bool {
P
Patrick Walton 已提交
351 352
    tbox_has_flag(get(t), has_params)
}
353 354
pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
pub fn type_needs_infer(t: t) -> bool {
355 356
    tbox_has_flag(get(t), needs_infer)
}
357
pub fn type_has_regions(t: t) -> bool {
358 359
    tbox_has_flag(get(t), has_regions)
}
360
pub fn type_id(t: t) -> uint { get(t).id }
361

362
#[deriving(Eq)]
363 364
pub struct BareFnTy {
    purity: ast::purity,
365
    abis: AbiSet,
366 367 368
    sig: FnSig
}

369
#[deriving(Eq)]
370
pub struct ClosureTy {
371
    purity: ast::purity,
372
    sigil: ast::Sigil,
373
    onceness: ast::Onceness,
374
    region: Region,
375 376
    bounds: BuiltinBounds,
    sig: FnSig,
377 378 379 380 381 382
}

/**
 * Signature of a function type, which I have arbitrarily
 * decided to use to refer to the input/output types.
 *
383
 * - `lifetimes` is the list of region names bound in this fn.
384 385
 * - `inputs` is the list of arguments and their modes.
 * - `output` is the return type. */
386
#[deriving(Eq)]
387
pub struct FnSig {
388
    bound_lifetime_names: OptVec<ast::ident>,
E
Erick Tryzelaar 已提交
389
    inputs: ~[t],
390
    output: t
391 392
}

393 394 395 396 397
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)
    }
}
398

399 400 401 402 403 404
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)
    }
}
405

406
#[deriving(Eq, IterBytes)]
407
pub struct param_ty {
408 409
    idx: uint,
    def_id: def_id
410
}
411

412
/// Representation of regions:
413
#[deriving(Eq, IterBytes, Encodable, Decodable)]
414
pub enum Region {
415 416 417 418 419 420 421 422 423
    /// 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 已提交
424
    re_bound(bound_region),
425 426 427 428

    /// 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.
429
    re_free(FreeRegion),
430 431

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

N
Niko Matsakis 已提交
434
    /// Static data that has an "infinite" lifetime. Top in the region lattice.
435 436 437
    re_static,

    /// A region variable.  Should not exist after typeck.
N
Niko Matsakis 已提交
438 439 440 441 442 443 444 445 446 447
    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 已提交
448 449
}

450 451 452 453 454 455 456 457 458
pub impl Region {
    fn is_bound(&self) -> bool {
        match self {
            &re_bound(*) => true,
            _ => false
        }
    }
}

459
#[deriving(Eq, IterBytes, Encodable, Decodable)]
460 461 462 463 464
pub struct FreeRegion {
    scope_id: node_id,
    bound_region: bound_region
}

465
#[deriving(Eq, IterBytes, Encodable, Decodable)]
466
pub enum bound_region {
467
    /// The self region for structs, impls (&T in a type defn or &'self T)
468 469
    br_self,

470 471
    /// An anonymous region parameter for a given fn (&T)
    br_anon(uint),
472

473
    /// Named region parameters for functions (a in &'a T)
474 475
    br_named(ast::ident),

476 477 478
    /// Fresh bound identifiers created during GLB computations.
    br_fresh(uint),

479 480 481 482 483 484 485 486 487
    /**
     * 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. */
488
    br_cap_avoid(ast::node_id, @bound_region),
489 490
}

491
type opt_region = Option<Region>;
492

493 494 495 496 497 498 499 500 501
/**
 * 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
502
 *   types (enums, structs) declared as having a region parameter.  `self_r`
503 504 505 506 507 508 509
 *   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. */
510
#[deriving(Eq)]
511
pub struct substs {
512
    self_r: opt_region,
B
Brian Anderson 已提交
513
    self_ty: Option<ty::t>,
514
    tps: ~[t]
515
}
516

517
mod primitives {
518
    use super::t_box_;
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563

    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;
}

564
// NB: If you change this, you'll probably want to change the corresponding
565
// AST structure in libsyntax/ast.rs as well.
566
#[deriving(Eq)]
567
pub enum sty {
P
Patrick Walton 已提交
568 569 570 571 572 573
    ty_nil,
    ty_bot,
    ty_bool,
    ty_int(ast::int_ty),
    ty_uint(ast::uint_ty),
    ty_float(ast::float_ty),
574
    ty_estr(vstore),
575
    ty_enum(def_id, substs),
P
Patrick Walton 已提交
576 577
    ty_box(mt),
    ty_uniq(mt),
578
    ty_evec(mt, vstore),
P
Patrick Walton 已提交
579
    ty_ptr(mt),
580
    ty_rptr(Region, mt),
581 582
    ty_bare_fn(BareFnTy),
    ty_closure(ClosureTy),
583
    ty_trait(def_id, substs, TraitStore, ast::mutability),
584
    ty_struct(def_id, substs),
585
    ty_tup(~[t]),
P
Patrick Walton 已提交
586

587
    ty_param(param_ty), // type parameter
588 589
    ty_self(def_id), /* special, implicit `self` type parameter;
                      * def_id is the id of the trait */
P
Patrick Walton 已提交
590

591
    ty_infer(InferTy), // something used only during inference/typeck
592 593 594
    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)
595

M
Michael Sullivan 已提交
596
    // "Fake" types, used for trans purposes
P
Patrick Walton 已提交
597
    ty_type, // type_desc*
598
    ty_opaque_box, // used by monomorphizer to represent any @ box
599
    ty_opaque_closure_ptr(Sigil), // ptr to env for &fn, @fn, ~fn
M
Michael Sullivan 已提交
600
    ty_unboxed_vec(mt),
601 602
}

603 604 605 606 607 608
#[deriving(Eq, IterBytes)]
pub struct TraitRef {
    def_id: def_id,
    substs: substs
}

609
#[deriving(Eq)]
610
pub enum IntVarValue {
611 612 613 614
    IntType(ast::int_ty),
    UintType(ast::uint_ty),
}

615
pub enum terr_vstore_kind {
616
    terr_vec, terr_str, terr_fn, terr_trait
617 618
}

619
pub struct expected_found<T> {
620 621
    expected: T,
    found: T
622 623
}

624
// Data structures used in type unification
625
pub enum type_err {
P
Patrick Walton 已提交
626
    terr_mismatch,
627
    terr_purity_mismatch(expected_found<purity>),
628
    terr_onceness_mismatch(expected_found<Onceness>),
629
    terr_abi_mismatch(expected_found<AbiSet>),
630
    terr_mutability,
631
    terr_sigil_mismatch(expected_found<ast::Sigil>),
P
Patrick Walton 已提交
632
    terr_box_mutability,
M
Marijn Haverbeke 已提交
633
    terr_ptr_mutability,
634
    terr_ref_mutability,
P
Patrick Walton 已提交
635
    terr_vec_mutability,
636 637 638
    terr_tuple_size(expected_found<uint>),
    terr_ty_param_size(expected_found<uint>),
    terr_record_size(expected_found<uint>),
P
Patrick Walton 已提交
639
    terr_record_mutability,
640
    terr_record_fields(expected_found<ident>),
P
Patrick Walton 已提交
641
    terr_arg_count,
642 643 644
    terr_regions_does_not_outlive(Region, Region),
    terr_regions_not_same(Region, Region),
    terr_regions_no_overlap(Region, Region),
645 646
    terr_regions_insufficiently_polymorphic(bound_region, Region),
    terr_regions_overly_polymorphic(bound_region, Region),
647
    terr_vstores_differ(terr_vstore_kind, expected_found<vstore>),
648
    terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
B
Brian Anderson 已提交
649
    terr_in_field(@type_err, ast::ident),
650
    terr_sorts(expected_found<t>),
651
    terr_integer_as_char,
652
    terr_int_mismatch(expected_found<IntVarValue>),
653 654
    terr_float_mismatch(expected_found<ast::float_ty>),
    terr_traits(expected_found<ast::def_id>),
655
    terr_builtin_bounds(expected_found<BuiltinBounds>),
656 657
}

658
#[deriving(Eq, IterBytes)]
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
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()
}

678 679 680 681 682 683 684 685 686
pub fn AllBuiltinBounds() -> BuiltinBounds {
    let mut set = EnumSet::empty();
    set.add(BoundCopy);
    set.add(BoundStatic);
    set.add(BoundOwned);
    set.add(BoundConst);
    set
}

687 688 689 690 691 692 693
impl CLike for BuiltinBound {
    pub fn to_uint(&self) -> uint {
        *self as uint
    }
    pub fn from_uint(v: uint) -> BuiltinBound {
        unsafe { cast::transmute(v) }
    }
694 695
}

696
#[deriving(Eq)]
697
pub struct TyVid(uint);
698

699
#[deriving(Eq)]
700
pub struct IntVid(uint);
701

702
#[deriving(Eq)]
703
pub struct FloatVid(uint);
704

705
#[deriving(Eq, Encodable, Decodable)]
706 707 708
pub struct RegionVid {
    id: uint
}
N
Niko Matsakis 已提交
709

710
#[deriving(Eq)]
711
pub enum InferTy {
712
    TyVar(TyVid),
713 714
    IntVar(IntVid),
    FloatVar(FloatVid)
715 716
}

717 718 719 720 721 722 723 724 725
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),
        }
    }
}
726

727
#[deriving(Encodable, Decodable)]
728
pub enum InferRegion {
729 730 731 732
    ReVar(RegionVid),
    ReSkolemized(uint, bound_region)
}

733 734 735 736 737 738 739 740
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)
        }
    }
}
741

742
impl cmp::Eq for InferRegion {
743
    fn eq(&self, other: &InferRegion) -> bool {
744 745 746 747 748 749 750 751 752 753
        match ((*self), *other) {
            (ReVar(rva), ReVar(rvb)) => {
                rva == rvb
            }
            (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
                rva == rvb
            }
            _ => false
        }
    }
754
    fn ne(&self, other: &InferRegion) -> bool {
755 756
        !((*self) == (*other))
    }
757 758
}

759
pub trait Vid {
760
    fn to_uint(&self) -> uint;
N
Niko Matsakis 已提交
761 762
}

763
impl Vid for TyVid {
764
    fn to_uint(&self) -> uint { **self }
765 766
}

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

771
impl Vid for IntVid {
772
    fn to_uint(&self) -> uint { **self }
773 774
}

775
impl ToStr for IntVid {
776
    fn to_str(&self) -> ~str { fmt!("<VI%u>", self.to_uint()) }
777 778
}

779
impl Vid for FloatVid {
780
    fn to_uint(&self) -> uint { **self }
781 782
}

783
impl ToStr for FloatVid {
784
    fn to_str(&self) -> ~str { fmt!("<VF%u>", self.to_uint()) }
785 786
}

787
impl Vid for RegionVid {
788
    fn to_uint(&self) -> uint { self.id }
N
Niko Matsakis 已提交
789 790
}

791
impl ToStr for RegionVid {
792
    fn to_str(&self) -> ~str { fmt!("%?", self.id) }
793
}
794

795
impl ToStr for FnSig {
796
    fn to_str(&self) -> ~str {
797 798
        // grr, without tcx not much we can do.
        return ~"(...)";
799 800 801
    }
}

802
impl ToStr for InferTy {
803
    fn to_str(&self) -> ~str {
804
        match *self {
805 806 807 808
            TyVar(ref v) => v.to_str(),
            IntVar(ref v) => v.to_str(),
            FloatVar(ref v) => v.to_str()
        }
N
Niko Matsakis 已提交
809 810 811
    }
}

812
impl ToStr for IntVarValue {
813
    fn to_str(&self) -> ~str {
814
        match *self {
815 816 817
            IntType(ref v) => v.to_str(),
            UintType(ref v) => v.to_str(),
        }
818 819
    }
}
820

821 822 823 824 825
impl to_bytes::IterBytes for TyVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
826

827 828 829 830 831
impl to_bytes::IterBytes for IntVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
832

833 834 835 836 837
impl to_bytes::IterBytes for FloatVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
838

839 840 841 842 843
impl to_bytes::IterBytes for RegionVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
844

845 846
pub struct TypeParameterDef {
    def_id: ast::def_id,
847
    bounds: @ParamBounds
848 849
}

850 851 852
/// Information about the type/lifetime parametesr associated with an item.
/// Analogous to ast::Generics.
pub struct Generics {
853
    type_param_defs: @~[TypeParameterDef],
854 855 856
    region_param: Option<region_variance>,
}

857 858 859 860 861 862
pub impl Generics {
    fn has_type_params(&self) -> bool {
        !self.type_param_defs.is_empty()
    }
}

863 864 865 866 867 868 869 870 871 872
/// 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
873
pub struct ty_param_bounds_and_ty {
874
    generics: Generics,
875 876
    ty: t
}
877

878 879 880 881 882 883
/// As `ty_param_bounds_and_ty` but for a trait ref.
pub struct TraitDef {
    generics: Generics,
    trait_ref: @ty::TraitRef,
}

884 885 886 887
pub struct ty_param_substs_and_ty {
    substs: ty::substs,
    ty: ty::t
}
888

889
type type_cache = @mut HashMap<ast::def_id, ty_param_bounds_and_ty>;
890

891
type constness_cache = @mut HashMap<ast::def_id, const_eval::constness>;
892

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

895
fn mk_rcache() -> creader_cache {
896
    return @mut HashMap::new();
897
}
898

899 900
pub fn new_ty_hash<V:Copy>() -> @mut HashMap<t, V> {
    @mut HashMap::new()
901
}
902

903 904 905 906
pub fn mk_ctxt(s: session::Session,
               dm: resolve::DefMap,
               amap: ast_map::map,
               freevars: freevars::freevar_map,
907
               region_maps: @mut middle::region::RegionMaps,
908
               region_paramd_items: middle::region::region_paramd_items,
909
               lang_items: middle::lang_items::LanguageItems,
910 911
               crate: @ast::crate)
            -> ctxt {
912 913 914
    let mut legacy_modes = false;
    for crate.node.attrs.each |attribute| {
        match attribute.node.value.node {
915
            ast::meta_word(w) if *w == ~"legacy_modes" => {
916 917 918 919 920 921
                legacy_modes = true;
            }
            _ => {}
        }
    }

922 923
    @ctxt_ {
        diag: s.diagnostic(),
924
        interner: @mut HashMap::new(),
925
        next_id: @mut primitives::LAST_PRIMITIVE_ID,
926 927 928 929
        legacy_modes: legacy_modes,
        cstore: s.cstore,
        sess: s,
        def_map: dm,
930
        region_maps: region_maps,
931
        region_paramd_items: region_paramd_items,
D
Daniel Micay 已提交
932
        node_types: @mut SmallIntMap::new(),
933
        node_type_substs: @mut HashMap::new(),
934 935 936
        trait_refs: @mut HashMap::new(),
        trait_defs: @mut HashMap::new(),
        intrinsic_traits: @mut HashMap::new(),
937
        items: amap,
938
        intrinsic_defs: @mut HashMap::new(),
939
        freevars: freevars,
940
        tcache: @mut HashMap::new(),
941
        rcache: mk_rcache(),
942
        ccache: @mut HashMap::new(),
943 944
        short_names_cache: new_ty_hash(),
        needs_unwind_cleanup_cache: new_ty_hash(),
945 946 947
        tc_cache: @mut HashMap::new(),
        ast_ty_to_ty_cache: @mut HashMap::new(),
        enum_var_cache: @mut HashMap::new(),
948 949 950
        methods: @mut HashMap::new(),
        trait_method_def_ids: @mut HashMap::new(),
        trait_methods_cache: @mut HashMap::new(),
951
        ty_param_defs: @mut HashMap::new(),
952
        adjustments: @mut HashMap::new(),
953
        normalized_cache: new_ty_hash(),
L
Luqman Aden 已提交
954
        lang_items: lang_items,
955 956 957 958 959
        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(),
960 961
        trait_impls: @mut HashMap::new(),
        used_unsafe: @mut HashSet::new(),
962
        used_mut_nodes: @mut HashSet::new(),
963
     }
964
}
965

966
// Type constructors
967 968 969

// 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).
970
fn mk_t(cx: ctxt, st: sty) -> t {
971 972
    // Check for primitive types.
    match st {
T
Tim Chevalier 已提交
973 974 975 976 977 978
        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),
979 980 981
        _ => {}
    };

982
    let key = intern_key { sty: to_unsafe_ptr(&st) };
983
    match cx.interner.find(&key) {
984
      Some(t) => unsafe { return cast::transmute(&t.sty); },
B
Brian Anderson 已提交
985
      _ => ()
986
    }
987

988
    let mut flags = 0u;
989
    fn rflags(r: Region) -> uint {
990
        (has_regions as uint) | {
991
            match r {
992
              ty::re_infer(_) => needs_infer as uint,
B
Brian Anderson 已提交
993
              _ => 0u
994
            }
N
Niko Matsakis 已提交
995 996
        }
    }
N
Niko Matsakis 已提交
997
    fn sflags(substs: &substs) -> uint {
998
        let mut f = 0u;
999
        for substs.tps.each |tt| { f |= get(*tt).flags; }
1000
        for substs.self_r.each |r| { f |= rflags(*r) }
B
Brian Anderson 已提交
1001
        return f;
N
Niko Matsakis 已提交
1002
    }
1003 1004
    match &st {
      &ty_estr(vstore_slice(r)) => {
1005
        flags |= rflags(r);
1006
      }
1007
      &ty_evec(ref mt, vstore_slice(r)) => {
1008 1009
        flags |= rflags(r);
        flags |= get(mt.ty).flags;
1010
      }
T
Tim Chevalier 已提交
1011
      &ty_nil | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
1012
      &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
1013
      &ty_opaque_box => (),
T
Tim Chevalier 已提交
1014 1015 1016 1017 1018 1019 1020 1021
      // 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,
1022
      &ty_err => flags |= has_ty_err as uint,
1023 1024
      &ty_param(_) => flags |= has_params as uint,
      &ty_infer(_) => flags |= needs_infer as uint,
1025
      &ty_self(_) => flags |= has_self as uint,
1026
      &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
1027
      &ty_trait(_, ref substs, _, _) => {
1028
        flags |= sflags(substs);
1029
      }
1030 1031
      &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
      &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
1032
        flags |= get(m.ty).flags;
1033
      }
1034
      &ty_rptr(r, ref m) => {
1035 1036
        flags |= rflags(r);
        flags |= get(m.ty).flags;
M
Marijn Haverbeke 已提交
1037
      }
1038
      &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
1039
      &ty_bare_fn(ref f) => {
E
Erick Tryzelaar 已提交
1040
        for f.sig.inputs.each |a| { flags |= get(*a).flags; }
T
Tim Chevalier 已提交
1041 1042 1043
         flags |= get(f.sig.output).flags;
         // T -> _|_ is *not* _|_ !
         flags &= !(has_ty_bot as uint);
1044 1045 1046
      }
      &ty_closure(ref f) => {
        flags |= rflags(f.region);
E
Erick Tryzelaar 已提交
1047
        for f.sig.inputs.each |a| { flags |= get(*a).flags; }
1048
        flags |= get(f.sig.output).flags;
T
Tim Chevalier 已提交
1049 1050
        // T -> _|_ is *not* _|_ !
        flags &= !(has_ty_bot as uint);
M
Marijn Haverbeke 已提交
1051
      }
1052
    }
1053

1054
    let t = ~t_box_ {
1055
        sty: st,
1056
        id: *cx.next_id,
1057 1058
        flags: flags,
    };
1059 1060 1061

    let sty_ptr = to_unsafe_ptr(&t.sty);

1062
    let key = intern_key {
1063
        sty: sty_ptr,
1064
    };
1065

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

1068
    *cx.next_id += 1;
1069 1070 1071 1072

    unsafe {
        cast::transmute::<*sty, t>(sty_ptr)
    }
1073 1074
}

1075
#[inline(always)]
T
Tim Chevalier 已提交
1076
pub fn mk_prim_t(primitive: &'static t_box_) -> t {
1077 1078 1079 1080
    unsafe {
        cast::transmute::<&'static t_box_, t>(primitive)
    }
}
P
Patrick Walton 已提交
1081

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

T
Tim Chevalier 已提交
1133
pub fn mk_mach_int(tm: ast::int_ty) -> t {
1134
    match tm {
T
Tim Chevalier 已提交
1135 1136 1137 1138 1139 1140
        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(),
1141 1142
    }
}
1143

T
Tim Chevalier 已提交
1144
pub fn mk_mach_uint(tm: ast::uint_ty) -> t {
1145
    match tm {
T
Tim Chevalier 已提交
1146 1147 1148 1149 1150
        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(),
1151 1152
    }
}
1153

T
Tim Chevalier 已提交
1154
pub fn mk_mach_float(tm: ast::float_ty) -> t {
1155
    match tm {
T
Tim Chevalier 已提交
1156 1157 1158
        ast::ty_f    => mk_float(),
        ast::ty_f32  => mk_f32(),
        ast::ty_f64  => mk_f64(),
1159
    }
1160
}
1161

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

1165
pub fn mk_estr(cx: ctxt, t: vstore) -> t {
1166 1167 1168
    mk_t(cx, ty_estr(t))
}

1169
pub fn mk_enum(cx: ctxt, did: ast::def_id, substs: substs) -> t {
N
Niko Matsakis 已提交
1170
    // take a copy of substs so that we own the vectors inside
1171
    mk_t(cx, ty_enum(did, substs))
1172
}
1173

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

1176
pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
1177 1178
    mk_box(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1179

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

1182
pub fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
1183 1184
    mk_uniq(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1185

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

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

1190
pub fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1191
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_mutbl})
1192
}
1193
pub fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1194
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_imm})
1195 1196
}

1197
pub fn mk_mut_ptr(cx: ctxt, ty: t) -> t {
1198 1199
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_mutbl})
}
1200

1201
pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
1202
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_imm})
1203 1204
}

1205
pub fn mk_nil_ptr(cx: ctxt) -> t {
T
Tim Chevalier 已提交
1206
    mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::m_imm})
1207 1208
}

1209
pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
1210 1211 1212
    mk_t(cx, ty_evec(tm, t))
}

1213
pub fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
M
Michael Sullivan 已提交
1214 1215
    mk_t(cx, ty_unboxed_vec(tm))
}
1216
pub fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
1217
    mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::m_imm}))
1218
}
M
Michael Sullivan 已提交
1219

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

1222
pub fn mk_closure(cx: ctxt, fty: ClosureTy) -> t {
1223 1224 1225
    mk_t(cx, ty_closure(fty))
}

1226
pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
1227 1228 1229 1230
    mk_t(cx, ty_bare_fn(fty))
}

pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
E
Erick Tryzelaar 已提交
1231
    let input_args = input_tys.map(|t| *t);
1232 1233 1234
    mk_bare_fn(cx,
               BareFnTy {
                   purity: ast::pure_fn,
1235
                   abis: AbiSet::Rust(),
1236 1237 1238 1239 1240 1241
                   sig: FnSig {
                    bound_lifetime_names: opt_vec::Empty,
                    inputs: input_args,
                    output: output
                   }
                })
1242 1243
}

1244

1245 1246
pub fn mk_trait(cx: ctxt,
                did: ast::def_id,
1247
                substs: substs,
1248 1249
                store: TraitStore,
                mutability: ast::mutability)
1250
             -> t {
N
Niko Matsakis 已提交
1251
    // take a copy of substs so that we own the vectors inside
1252
    mk_t(cx, ty_trait(did, substs, store, mutability))
1253 1254
}

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

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

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

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

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

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

1270
pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
1271
    mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
1272
}
1273

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

1276 1277
pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
    mk_t(cx, ty_opaque_closure_ptr(sigil))
1278 1279
}

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

1282
pub fn walk_ty(ty: t, f: &fn(t)) {
B
Brian Anderson 已提交
1283
    maybe_walk_ty(ty, |t| { f(t); true });
1284 1285
}

1286
pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
1287 1288 1289
    if !f(ty) {
        return;
    }
1290
    match get(ty).sty {
1291
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1292
      ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
1293
      ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1294
      }
1295 1296
      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) => {
1297
        maybe_walk_ty(tm.ty, f);
1298
      }
1299
      ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1300
      ty_trait(_, ref substs, _, _) => {
1301
        for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); }
1302
      }
1303
      ty_tup(ref ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
1304
      ty_bare_fn(ref ft) => {
E
Erick Tryzelaar 已提交
1305
        for ft.sig.inputs.each |a| { maybe_walk_ty(*a, f); }
1306 1307 1308
        maybe_walk_ty(ft.sig.output, f);
      }
      ty_closure(ref ft) => {
E
Erick Tryzelaar 已提交
1309
        for ft.sig.inputs.each |a| { maybe_walk_ty(*a, f); }
1310
        maybe_walk_ty(ft.sig.output, f);
M
Marijn Haverbeke 已提交
1311
      }
1312 1313 1314
    }
}

1315
pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
N
Niko Matsakis 已提交
1316
    mk_t(tcx, fold_sty(sty, foldop))
1317
}
1318

1319
pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
1320
    let args = sig.inputs.map(|arg| fldop(*arg));
1321 1322

    FnSig {
1323
        bound_lifetime_names: copy sig.bound_lifetime_names,
L
Luqman Aden 已提交
1324
        inputs: args,
1325 1326 1327 1328
        output: fldop(sig.output)
    }
}

1329 1330 1331 1332 1333 1334
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}
}

1335 1336
fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
    fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
1337 1338 1339
        substs {self_r: substs.self_r,
                self_ty: substs.self_ty.map(|t| fldop(*t)),
                tps: substs.tps.map(|t| fldop(*t))}
1340 1341
    }

1342 1343
    match *sty {
        ty_box(ref tm) => {
1344
            ty_box(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1345
        }
1346
        ty_uniq(ref tm) => {
1347
            ty_uniq(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1348
        }
1349
        ty_ptr(ref tm) => {
1350
            ty_ptr(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1351
        }
1352
        ty_unboxed_vec(ref tm) => {
1353
            ty_unboxed_vec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1354
        }
1355
        ty_evec(ref tm, vst) => {
1356
            ty_evec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
1357 1358 1359 1360
        }
        ty_enum(tid, ref substs) => {
            ty_enum(tid, fold_substs(substs, fldop))
        }
1361 1362
        ty_trait(did, ref substs, st, mutbl) => {
            ty_trait(did, fold_substs(substs, fldop), st, mutbl)
1363
        }
1364 1365
        ty_tup(ref ts) => {
            let new_ts = ts.map(|tt| fldop(*tt));
1366 1367
            ty_tup(new_ts)
        }
1368
        ty_bare_fn(ref f) => {
1369
            ty_bare_fn(fold_bare_fn_ty(f, fldop))
1370 1371
        }
        ty_closure(ref f) => {
1372
            let sig = fold_sig(&f.sig, fldop);
1373
            ty_closure(ClosureTy {sig: sig, ..copy *f})
1374
        }
1375
        ty_rptr(r, ref tm) => {
1376
            ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1377
        }
1378 1379
        ty_struct(did, ref substs) => {
            ty_struct(did, fold_substs(substs, fldop))
1380 1381
        }
        ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1382
        ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1383
        ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
1384
            /*bad*/copy *sty
1385
        }
N
Niko Matsakis 已提交
1386 1387
    }
}
1388

N
Niko Matsakis 已提交
1389
// Folds types from the bottom up.
1390
pub fn fold_ty(cx: ctxt, t0: t, fldop: &fn(t) -> t) -> t {
1391
    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
N
Niko Matsakis 已提交
1392 1393
    fldop(mk_t(cx, sty))
}
1394

1395
pub fn walk_regions_and_ty(
1396 1397
    cx: ctxt,
    ty: t,
1398 1399
    walkr: &fn(r: Region),
    walkt: &fn(t: t) -> bool) {
1400 1401 1402 1403

    if (walkt(ty)) {
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1404
            |r| { walkr(r); r },
1405 1406
            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t },
            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t });
1407 1408 1409
    }
}

1410
pub fn fold_regions_and_ty(
1411 1412
    cx: ctxt,
    ty: t,
1413 1414 1415
    fldr: &fn(r: Region) -> Region,
    fldfnt: &fn(t: t) -> t,
    fldt: &fn(t: t) -> t) -> t {
1416 1417

    fn fold_substs(
N
Niko Matsakis 已提交
1418
        substs: &substs,
1419 1420
        fldr: &fn(r: Region) -> Region,
        fldt: &fn(t: t) -> t)
1421 1422 1423 1424 1425 1426
     -> 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))
        }
1427 1428 1429
    }

    let tb = ty::get(ty);
1430
    match tb.sty {
B
Brian Anderson 已提交
1431
      ty::ty_rptr(r, mt) => {
1432 1433
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1434
        ty::mk_rptr(cx, m_r, mt {ty: m_t, mutbl: mt.mutbl})
1435
      }
B
Brian Anderson 已提交
1436
      ty_estr(vstore_slice(r)) => {
1437 1438 1439
        let m_r = fldr(r);
        ty::mk_estr(cx, vstore_slice(m_r))
      }
B
Brian Anderson 已提交
1440
      ty_evec(mt, vstore_slice(r)) => {
1441 1442
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1443
        ty::mk_evec(cx, mt {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
1444
      }
N
Niko Matsakis 已提交
1445
      ty_enum(def_id, ref substs) => {
1446 1447
        ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
      }
1448 1449
      ty_struct(def_id, ref substs) => {
        ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1450
      }
1451 1452
      ty_trait(def_id, ref substs, st, mutbl) => {
        ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl)
1453
      }
1454 1455 1456 1457 1458 1459 1460 1461
      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})
1462
      }
N
Niko Matsakis 已提交
1463
      ref sty => {
B
Brian Anderson 已提交
1464
        fold_sty_to_ty(cx, sty, |t| fldt(t))
1465 1466 1467 1468
      }
    }
}

1469 1470
// n.b. this function is intended to eventually replace fold_region() below,
// that is why its name is so similar.
1471
pub fn fold_regions(
1472 1473
    cx: ctxt,
    ty: t,
1474
    fldr: &fn(r: Region, in_fn: bool) -> Region) -> t {
1475
    fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1476
               fldr: &fn(Region, bool) -> Region) -> t {
1477
        debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
B
Brian Anderson 已提交
1478
        if !type_has_regions(ty) { return ty; }
1479 1480
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1481 1482 1483
            |r| fldr(r, in_fn),
            |t| do_fold(cx, t, true, fldr),
            |t| do_fold(cx, t, in_fn, fldr))
1484 1485 1486 1487
    }
    do_fold(cx, ty, false, fldr)
}

1488
// Substitute *only* type parameters.  Used in trans where regions are erased.
1489
pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
1490
    if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1491
    let tb = ty::get(typ);
1492
    if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1493
    match tb.sty {
1494
        ty_param(p) => tps[p.idx],
1495
        ty_self(_) => {
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505
            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))
        }
1506 1507 1508
    }
}

1509
pub fn substs_is_noop(substs: &substs) -> bool {
1510 1511 1512
    substs.tps.len() == 0u &&
        substs.self_r.is_none() &&
        substs.self_ty.is_none()
1513 1514
}

1515
pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
1516
    substs.repr(cx)
1517 1518
}

1519 1520 1521 1522
pub fn subst(cx: ctxt,
             substs: &substs,
             typ: t)
          -> t {
1523
    typ.subst(cx, substs)
1524 1525
}

1526
// Type utilities
1527

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

T
Tim Chevalier 已提交
1530 1531 1532 1533 1534 1535 1536
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
}
1537

1538 1539 1540 1541
pub fn type_needs_subst(ty: t) -> bool {
    tbox_has_flag(get(ty), needs_subst)
}

1542 1543 1544 1545 1546
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))
}

1547
pub fn type_is_ty_var(ty: t) -> bool {
1548
    match get(ty).sty {
1549
      ty_infer(TyVar(_)) => true,
B
Brian Anderson 已提交
1550
      _ => false
1551 1552 1553
    }
}

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

1556 1557 1558 1559 1560 1561 1562
pub fn type_is_self(ty: t) -> bool {
    match get(ty).sty {
        ty_self(*) => true,
        _ => false
    }
}

1563
pub fn type_is_structural(ty: t) -> bool {
1564
    match get(ty).sty {
1565
      ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_closure(_) | ty_trait(*) |
1566 1567
      ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
B
Brian Anderson 已提交
1568 1569
      => true,
      _ => false
1570 1571 1572
    }
}

1573
pub fn type_is_sequence(ty: t) -> bool {
1574
    match get(ty).sty {
B
Brian Anderson 已提交
1575 1576
      ty_estr(_) | ty_evec(_, _) => true,
      _ => false
1577 1578 1579
    }
}

S
Seo Sanghyeon 已提交
1580 1581 1582 1583 1584 1585 1586
pub fn type_is_simd(cx: ctxt, ty: t) -> bool {
    match get(ty).sty {
        ty_struct(did, _) => lookup_simd(cx, did),
        _ => false
    }
}

1587
pub fn type_is_str(ty: t) -> bool {
1588
    match get(ty).sty {
B
Brian Anderson 已提交
1589 1590
      ty_estr(_) => true,
      _ => false
1591 1592
    }
}
1593

1594
pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
1595
    match get(ty).sty {
T
Tim Chevalier 已提交
1596
      ty_estr(_) => return mk_mach_uint(ast::ty_u8),
B
Brian Anderson 已提交
1597 1598 1599
      ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
      _ => cx.sess.bug(
          ~"sequence_element_type called on non-sequence value"),
1600 1601 1602
    }
}

S
Seo Sanghyeon 已提交
1603 1604 1605 1606 1607 1608
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)
        }
1609
        _ => fail!("simd_type called on invalid type")
S
Seo Sanghyeon 已提交
1610 1611 1612 1613 1614 1615 1616 1617 1618
    }
}

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()
        }
1619
        _ => fail!("simd_size called on invalid type")
S
Seo Sanghyeon 已提交
1620 1621 1622
    }
}

1623
pub fn get_element_type(ty: t, i: uint) -> t {
1624 1625
    match get(ty).sty {
      ty_tup(ref ts) => return ts[i],
1626
      _ => fail!("get_element_type called on invalid type")
1627 1628 1629
    }
}

1630
pub fn type_is_box(ty: t) -> bool {
1631
    match get(ty).sty {
B
Brian Anderson 已提交
1632 1633
      ty_box(_) => return true,
      _ => return false
1634
    }
M
Marijn Haverbeke 已提交
1635 1636
}

1637
pub fn type_is_boxed(ty: t) -> bool {
1638
    match get(ty).sty {
1639
      ty_box(_) | ty_opaque_box |
B
Brian Anderson 已提交
1640 1641
      ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
      _ => false
1642 1643 1644
    }
}

1645
pub fn type_is_region_ptr(ty: t) -> bool {
1646
    match get(ty).sty {
B
Brian Anderson 已提交
1647 1648
      ty_rptr(_, _) => true,
      _ => false
1649 1650 1651
    }
}

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

1659
pub fn type_is_unique_box(ty: t) -> bool {
1660
    match get(ty).sty {
B
Brian Anderson 已提交
1661 1662
      ty_uniq(_) => return true,
      _ => return false
1663
    }
M
Marijn Haverbeke 已提交
1664
}
1665

1666
pub fn type_is_unsafe_ptr(ty: t) -> bool {
1667
    match get(ty).sty {
B
Brian Anderson 已提交
1668 1669
      ty_ptr(_) => return true,
      _ => return false
1670 1671 1672
    }
}

1673
pub fn type_is_vec(ty: t) -> bool {
1674
    return match get(ty).sty {
B
Brian Anderson 已提交
1675 1676 1677
          ty_evec(_, _) | ty_unboxed_vec(_) => true,
          ty_estr(_) => true,
          _ => false
B
Brian Anderson 已提交
1678
        };
M
Marijn Haverbeke 已提交
1679 1680
}

1681
pub fn type_is_unique(ty: t) -> bool {
1682
    match get(ty).sty {
1683 1684 1685 1686 1687
        ty_uniq(_) |
        ty_evec(_, vstore_uniq) |
        ty_estr(vstore_uniq) |
        ty_opaque_closure_ptr(ast::OwnedSigil) => true,
        _ => return false
B
Brian Anderson 已提交
1688
    }
1689 1690
}

1691 1692 1693 1694 1695
/*
 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.)
*/
1696
pub fn type_is_scalar(ty: t) -> bool {
1697
    match get(ty).sty {
1698
      ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1699
      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
1700
      ty_bare_fn(*) | ty_ptr(_) => true,
B
Brian Anderson 已提交
1701
      _ => false
M
Marijn Haverbeke 已提交
1702
    }
1703 1704
}

1705
pub fn type_is_immediate(ty: t) -> bool {
B
Brian Anderson 已提交
1706
    return type_is_scalar(ty) || type_is_boxed(ty) ||
1707
        type_is_unique(ty) || type_is_region_ptr(ty);
1708 1709
}

1710
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1711
    type_contents(cx, ty).needs_drop(cx)
1712 1713
}

1714 1715 1716 1717
// 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.
1718
pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1719
    match cx.needs_unwind_cleanup_cache.find(&ty) {
1720
      Some(&result) => return result,
B
Brian Anderson 已提交
1721
      None => ()
1722 1723
    }

1724
    let mut tycache = HashSet::new();
1725
    let needs_unwind_cleanup =
1726
        type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
1727
    cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
B
Brian Anderson 已提交
1728
    return needs_unwind_cleanup;
1729 1730 1731
}

fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1732
                              tycache: &mut HashSet<t>,
1733 1734
                              encountered_box: bool) -> bool {

1735
    // Prevent infinite recursion
1736 1737
    if !tycache.insert(ty) {
        return false;
1738
    }
1739

1740
    let mut encountered_box = encountered_box;
1741
    let mut needs_unwind_cleanup = false;
B
Brian Anderson 已提交
1742
    do maybe_walk_ty(ty) |ty| {
1743
        let old_encountered_box = encountered_box;
1744
        let result = match get(ty).sty {
B
Brian Anderson 已提交
1745
          ty_box(_) | ty_opaque_box => {
1746 1747 1748
            encountered_box = true;
            true
          }
1749 1750
          ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
          ty_tup(_) | ty_ptr(_) => {
1751 1752
            true
          }
N
Niko Matsakis 已提交
1753
          ty_enum(did, ref substs) => {
1754
            for (*enum_variants(cx, did)).each |v| {
B
Brian Anderson 已提交
1755
                for v.args.each |aty| {
1756
                    let t = subst(cx, substs, *aty);
1757 1758 1759
                    needs_unwind_cleanup |=
                        type_needs_unwind_cleanup_(cx, t, tycache,
                                                   encountered_box);
1760 1761 1762 1763
                }
            }
            !needs_unwind_cleanup
          }
M
Michael Sullivan 已提交
1764
          ty_uniq(_) |
1765 1766 1767 1768
          ty_estr(vstore_uniq) |
          ty_estr(vstore_box) |
          ty_evec(_, vstore_uniq) |
          ty_evec(_, vstore_box)
B
Brian Anderson 已提交
1769
          => {
1770 1771 1772 1773 1774 1775 1776 1777 1778
            // 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 已提交
1779
          _ => {
1780 1781 1782
            needs_unwind_cleanup = true;
            false
          }
1783 1784 1785 1786
        };

        encountered_box = old_encountered_box;
        result
1787 1788
    }

B
Brian Anderson 已提交
1789
    return needs_unwind_cleanup;
1790 1791
}

1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806
/**
 * 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
}
1807

1808
pub impl TypeContents {
1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
    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)
        }
    }

1822 1823 1824
    fn intersects(&self, tc: TypeContents) -> bool {
        (self.bits & tc.bits) != 0
    }
1825

1826 1827 1828
    fn is_copy(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::noncopyable(cx))
    }
1829

1830
    fn noncopyable(_cx: ctxt) -> TypeContents {
1831 1832 1833
        TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE +
            TC_EMPTY_ENUM
    }
1834

1835 1836
    fn is_static(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonstatic(cx))
1837
    }
1838

1839
    fn nonstatic(_cx: ctxt) -> TypeContents {
1840 1841
        TC_BORROWED_POINTER
    }
1842

1843 1844 1845
    fn is_owned(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonowned(cx))
    }
1846

1847
    fn nonowned(_cx: ctxt) -> TypeContents {
1848
        TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED
1849
    }
1850

1851 1852 1853 1854
    fn contains_managed(&self) -> bool {
        self.intersects(TC_MANAGED)
    }

1855 1856 1857
    fn is_const(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonconst(cx))
    }
1858

1859
    fn nonconst(_cx: ctxt) -> TypeContents {
1860 1861
        TC_MUTABLE
    }
1862

1863 1864 1865
    fn moves_by_default(&self, cx: ctxt) -> bool {
        self.intersects(TypeContents::nonimplicitly_copyable(cx))
    }
1866

1867
    fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
1868
        TypeContents::noncopyable(cx) + TC_OWNED_POINTER + TC_OWNED_VEC
1869
    }
1870

1871 1872 1873 1874 1875
    fn needs_drop(&self, cx: ctxt) -> bool {
        let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx);
        self.intersects(tc)
    }

1876
    fn owned(_cx: ctxt) -> TypeContents {
1877 1878
        //! Any kind of owned contents.
        TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC
1879
    }
1880
}
1881

1882
impl ops::Add<TypeContents,TypeContents> for TypeContents {
1883
    fn add(&self, other: &TypeContents) -> TypeContents {
1884 1885
        TypeContents {bits: self.bits | other.bits}
    }
1886 1887
}

1888
impl ops::Sub<TypeContents,TypeContents> for TypeContents {
1889
    fn sub(&self, other: &TypeContents) -> TypeContents {
1890 1891
        TypeContents {bits: self.bits & !other.bits}
    }
1892 1893
}

1894
impl ToStr for TypeContents {
1895
    fn to_str(&self) -> ~str {
1896 1897
        fmt!("TypeContents(%s)", u32::to_str_radix(self.bits, 2))
    }
1898 1899
}

1900
/// Constant for a type containing nothing of interest.
1901
static TC_NONE: TypeContents =             TypeContents{bits: 0b0000_0000_0000};
1902

1903
/// Contains a borrowed value with a lifetime other than static
1904
static TC_BORROWED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0001};
1905

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

1909
/// Contains an owned vector ~[] or owned string ~str
1910
static TC_OWNED_VEC: TypeContents =        TypeContents{bits: 0b0000_0000_0100};
1911

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

1915
/// Type with a destructor
1916
static TC_DTOR: TypeContents =             TypeContents{bits: 0b0000_0001_0000};
1917

1918
/// Contains a managed value
1919
static TC_MANAGED: TypeContents =          TypeContents{bits: 0b0000_0010_0000};
1920

1921
/// &mut with any region
1922
static TC_BORROWED_MUT: TypeContents =     TypeContents{bits: 0b0000_0100_0000};
1923

1924
/// Mutable content, whether owned or by ref
1925
static TC_MUTABLE: TypeContents =          TypeContents{bits: 0b0000_1000_0000};
1926

1927 1928
/// One-shot closure
static TC_ONCE_CLOSURE: TypeContents =     TypeContents{bits: 0b0001_0000_0000};
1929

1930
/// An enum with no variants.
1931 1932 1933 1934
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};
1935

1936
/// All possible contents.
1937
static TC_ALL: TypeContents =              TypeContents{bits: 0b0111_1111_1111};
1938

1939 1940
pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_copy(cx)
1941 1942
}

1943 1944
pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_static(cx)
1945 1946
}

1947 1948 1949
pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_owned(cx)
}
1950

1951 1952 1953
pub fn type_is_const(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_const(cx)
}
1954

1955 1956 1957 1958 1959
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 => {}
1960 1961
    }

1962
    let mut cache = HashMap::new();
1963 1964 1965
    let result = tc_ty(cx, ty, &mut cache);
    cx.tc_cache.insert(ty_id, result);
    return result;
M
Marijn Haverbeke 已提交
1966

1967 1968
    fn tc_ty(cx: ctxt,
             ty: t,
1969
             cache: &mut HashMap<uint, TypeContents>) -> TypeContents
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996
    {
        // 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 => {}
        }
1997 1998 1999 2000
        match cx.tc_cache.find(&ty_id) {    // Must check both caches!
            Some(tc) => { return *tc; }
            None => {}
        }
2001 2002 2003 2004
        cache.insert(ty_id, TC_NONE);

        let _i = indenter();

2005
        let result = match get(ty).sty {
2006 2007 2008 2009 2010
            // 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
            }
2011

2012
            ty_estr(vstore_uniq) => {
2013
                TC_OWNED_VEC
2014
            }
M
Marijn Haverbeke 已提交
2015

2016 2017 2018
            ty_closure(ref c) => {
                closure_contents(c)
            }
2019

2020 2021 2022
            ty_box(mt) => {
                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
            }
2023

2024
            ty_trait(_, _, UniqTraitStore, _) => {
2025 2026
                TC_OWNED_CLOSURE
            }
2027

2028 2029 2030 2031 2032
            ty_trait(_, _, BoxTraitStore, mutbl) => {
                match mutbl {
                    ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
                    _ => TC_MANAGED
                }
2033
            }
2034

2035 2036
            ty_trait(_, _, RegionTraitStore(r), mutbl) => {
                borrowed_contents(r, mutbl)
2037
            }
2038

2039 2040 2041 2042
            ty_rptr(r, mt) => {
                borrowed_contents(r, mt.mutbl) +
                    nonowned(tc_mt(cx, mt, cache))
            }
2043

2044 2045 2046
            ty_uniq(mt) => {
                TC_OWNED_POINTER + tc_mt(cx, mt, cache)
            }
2047

2048
            ty_evec(mt, vstore_uniq) => {
2049
                TC_OWNED_VEC + tc_mt(cx, mt, cache)
2050
            }
2051

2052 2053 2054
            ty_evec(mt, vstore_box) => {
                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
            }
2055

2056 2057 2058 2059
            ty_evec(mt, vstore_slice(r)) => {
                borrowed_contents(r, mt.mutbl) +
                    nonowned(tc_mt(cx, mt, cache))
            }
2060

2061 2062 2063
            ty_evec(mt, vstore_fixed(_)) => {
                tc_mt(cx, mt, cache)
            }
2064

2065 2066 2067
            ty_estr(vstore_box) => {
                TC_MANAGED
            }
2068

2069 2070 2071
            ty_estr(vstore_slice(r)) => {
                borrowed_contents(r, m_imm)
            }
2072

2073 2074 2075
            ty_estr(vstore_fixed(_)) => {
                TC_NONE
            }
2076

2077 2078
            ty_struct(did, ref substs) => {
                let flds = struct_fields(cx, did, substs);
2079
                let mut res = flds.foldl(
2080 2081 2082
                    TC_NONE,
                    |tc, f| tc + tc_mt(cx, f.mt, cache));
                if ty::has_dtor(cx, did) {
2083
                    res += TC_DTOR;
2084
                }
D
Daniel Micay 已提交
2085
                apply_tc_attr(cx, did, res)
2086
            }
2087

2088 2089 2090
            ty_tup(ref tys) => {
                tys.foldl(TC_NONE, |tc, ty| *tc + tc_ty(cx, *ty, cache))
            }
2091

2092 2093
            ty_enum(did, ref substs) => {
                let variants = substd_enum_variants(cx, did, substs);
D
Daniel Micay 已提交
2094
                let res = if variants.is_empty() {
2095 2096 2097 2098 2099 2100 2101 2102 2103
                    // 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))
                    })
2104
                };
D
Daniel Micay 已提交
2105
                apply_tc_attr(cx, did, res)
2106
            }
2107

2108 2109 2110 2111 2112 2113 2114
            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.
2115
                assert_eq!(p.def_id.crate, ast::local_crate);
2116

2117 2118
                type_param_def_to_contents(
                    cx, cx.ty_param_defs.get(&p.def_id.node))
2119
            }
2120

2121
            ty_self(_) => {
2122 2123 2124 2125 2126 2127 2128
                // 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
            }
2129

2130 2131 2132 2133 2134 2135
            ty_infer(_) => {
                // This occurs during coherence, but shouldn't occur at other
                // times.
                TC_ALL
            }

2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147
            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,

2148 2149
            ty_err => {
                cx.sess.bug(~"Asked to compute contents of fictitious type");
2150
            }
2151 2152 2153 2154 2155
        };

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

2157 2158
    fn tc_mt(cx: ctxt,
             mt: mt,
2159
             cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2160 2161 2162 2163
    {
        let mc = if mt.mutbl == m_mutbl {TC_MUTABLE} else {TC_NONE};
        mc + tc_ty(cx, mt.ty, cache)
    }
2164

D
Daniel Micay 已提交
2165 2166 2167 2168 2169 2170 2171 2172 2173 2174
    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
    }

2175 2176 2177 2178 2179
    fn borrowed_contents(region: ty::Region,
                         mutbl: ast::mutability) -> TypeContents
    {
        let mc = if mutbl == m_mutbl {
            TC_MUTABLE + TC_BORROWED_MUT
2180
        } else {
2181 2182 2183 2184 2185 2186 2187 2188 2189
            TC_NONE
        };
        let rc = if region != ty::re_static {
            TC_BORROWED_POINTER
        } else {
            TC_NONE
        };
        mc + rc
    }
2190

2191 2192 2193 2194 2195 2196 2197 2198
    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.
         */
2199

2200 2201
        let mask = TC_MUTABLE.bits | TC_BORROWED_POINTER.bits;
        TypeContents {bits: pointee.bits & mask}
2202 2203
    }

2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217
    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
    }

2218 2219
    fn type_param_def_to_contents(cx: ctxt,
                                  type_param_def: &TypeParameterDef) -> TypeContents
2220
    {
2221
        debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx));
2222 2223
        let _i = indenter();

2224 2225
        let mut tc = TC_ALL;
        for type_param_def.bounds.builtin_bounds.each |bound| {
2226
            debug!("tc = %s, bound = %?", tc.to_str(), bound);
2227 2228 2229 2230 2231 2232 2233
            tc = tc - match bound {
                BoundCopy => TypeContents::nonimplicitly_copyable(cx),
                BoundStatic => TypeContents::nonstatic(cx),
                BoundOwned => TypeContents::nonowned(cx),
                BoundConst => TypeContents::nonconst(cx),
            };
        }
2234

2235 2236
        debug!("result = %s", tc.to_str());
        return tc;
2237
    }
2238 2239
}

2240 2241 2242 2243
pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool {
    type_contents(cx, ty).moves_by_default(cx)
}

2244
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2245
pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
2246
    fn type_requires(cx: ctxt, seen: &mut ~[def_id],
2247
                     r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2248
        debug!("type_requires(%s, %s)?",
2249 2250
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2251 2252

        let r = {
2253
            get(r_ty).sty == get(ty).sty ||
2254 2255 2256
                subtypes_require(cx, seen, r_ty, ty)
        };

P
Paul Stansifer 已提交
2257
        debug!("type_requires(%s, %s)? %b",
2258 2259
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2260
               r);
B
Brian Anderson 已提交
2261
        return r;
2262 2263
    }

2264
    fn subtypes_require(cx: ctxt, seen: &mut ~[def_id],
2265
                        r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2266
        debug!("subtypes_require(%s, %s)?",
2267 2268
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2269

2270
        let r = match get(ty).sty {
2271 2272 2273 2274 2275 2276
          ty_nil |
          ty_bot |
          ty_bool |
          ty_int(_) |
          ty_uint(_) |
          ty_float(_) |
2277
          ty_estr(_) |
2278 2279
          ty_bare_fn(_) |
          ty_closure(_) |
2280
          ty_infer(_) |
2281
          ty_err |
2282
          ty_param(_) |
2283
          ty_self(_) |
2284 2285 2286
          ty_type |
          ty_opaque_box |
          ty_opaque_closure_ptr(_) |
2287
          ty_evec(_, _) |
B
Brian Anderson 已提交
2288
          ty_unboxed_vec(_) => {
2289 2290
            false
          }
2291 2292 2293
          ty_box(ref mt) |
          ty_uniq(ref mt) |
          ty_rptr(_, ref mt) => {
B
Brian Anderson 已提交
2294
            return type_requires(cx, seen, r_ty, mt.ty);
2295 2296
          }

2297
          ty_ptr(*) => {
2298 2299 2300
            false           // unsafe ptrs can always be NULL
          }

2301
          ty_trait(_, _, _, _) => {
2302 2303 2304
            false
          }

2305
          ty_struct(ref did, _) if vec::contains(*seen, did) => {
2306 2307 2308
            false
          }

2309
          ty_struct(did, ref substs) => {
2310
              seen.push(did);
2311
              let r = vec::any(struct_fields(cx, did, substs),
2312
                               |f| type_requires(cx, seen, r_ty, f.mt.ty));
N
Niko Matsakis 已提交
2313
              seen.pop();
2314 2315 2316
            r
          }

2317 2318
          ty_tup(ref ts) => {
            ts.any(|t| type_requires(cx, seen, r_ty, *t))
2319 2320
          }

N
Niko Matsakis 已提交
2321
          ty_enum(ref did, _) if vec::contains(*seen, did) => {
2322 2323 2324
            false
          }

2325 2326 2327 2328 2329
            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 已提交
2330
                        let sty = subst(cx, substs, *aty);
2331 2332 2333
                        type_requires(cx, seen, r_ty, sty)
                    })
                });
N
Niko Matsakis 已提交
2334
                seen.pop();
2335 2336
                r
            }
2337 2338
        };

P
Paul Stansifer 已提交
2339
        debug!("subtypes_require(%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);
2343

B
Brian Anderson 已提交
2344
        return r;
2345 2346
    }

2347
    let seen = @mut ~[];
2348 2349 2350
    !subtypes_require(cx, seen, r_ty, r_ty)
}

2351 2352
pub fn type_structurally_contains(cx: ctxt,
                                  ty: t,
2353
                                  test: &fn(x: &sty) -> bool)
2354
                               -> bool {
2355
    let sty = &get(ty).sty;
2356 2357
    debug!("type_structurally_contains: %s",
           ::util::ppaux::ty_to_str(cx, ty));
B
Brian Anderson 已提交
2358
    if test(sty) { return true; }
2359
    match *sty {
N
Niko Matsakis 已提交
2360
      ty_enum(did, ref substs) => {
2361
        for (*enum_variants(cx, did)).each |variant| {
B
Brian Anderson 已提交
2362
            for variant.args.each |aty| {
2363
                let sty = subst(cx, substs, *aty);
B
Brian Anderson 已提交
2364
                if type_structurally_contains(cx, sty, test) { return true; }
2365
            }
2366
        }
B
Brian Anderson 已提交
2367
        return false;
M
Marijn Haverbeke 已提交
2368
      }
2369 2370
      ty_struct(did, ref substs) => {
        for lookup_struct_fields(cx, did).each |field| {
2371
            let ft = lookup_field_type(cx, did, field.id, substs);
B
Brian Anderson 已提交
2372
            if type_structurally_contains(cx, ft, test) { return true; }
2373
        }
B
Brian Anderson 已提交
2374
        return false;
2375 2376
      }

2377
      ty_tup(ref ts) => {
B
Brian Anderson 已提交
2378
        for ts.each |tt| {
2379
            if type_structurally_contains(cx, *tt, test) { return true; }
2380
        }
B
Brian Anderson 已提交
2381
        return false;
2382
      }
2383
      ty_evec(ref mt, vstore_fixed(_)) => {
B
Brian Anderson 已提交
2384
        return type_structurally_contains(cx, mt.ty, test);
2385
      }
B
Brian Anderson 已提交
2386
      _ => return false
M
Marijn Haverbeke 已提交
2387 2388 2389
    }
}

2390
pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
2391
    return type_structurally_contains(cx, ty, |sty| {
N
Niko Matsakis 已提交
2392
        match *sty {
2393 2394
          ty_uniq(_) |
          ty_evec(_, vstore_uniq) |
B
Brian Anderson 已提交
2395 2396
          ty_estr(vstore_uniq) => true,
          _ => false,
2397
        }
2398
    });
2399 2400
}

2401
pub fn type_is_integral(ty: t) -> bool {
2402
    match get(ty).sty {
2403
      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
B
Brian Anderson 已提交
2404
      _ => false
M
Marijn Haverbeke 已提交
2405 2406 2407
    }
}

2408
pub fn type_is_char(ty: t) -> bool {
2409 2410 2411 2412 2413 2414
    match get(ty).sty {
        ty_int(ty_char) => true,
        _ => false
    }
}

2415
pub fn type_is_fp(ty: t) -> bool {
2416
    match get(ty).sty {
2417
      ty_infer(FloatVar(_)) | ty_float(_) => true,
B
Brian Anderson 已提交
2418
      _ => false
M
Marijn Haverbeke 已提交
2419 2420 2421
    }
}

2422
pub fn type_is_numeric(ty: t) -> bool {
B
Brian Anderson 已提交
2423
    return type_is_integral(ty) || type_is_fp(ty);
2424 2425
}

2426
pub fn type_is_signed(ty: t) -> bool {
2427
    match get(ty).sty {
B
Brian Anderson 已提交
2428 2429
      ty_int(_) => true,
      _ => false
M
Marijn Haverbeke 已提交
2430 2431 2432
    }
}

S
Seo Sanghyeon 已提交
2433 2434 2435 2436 2437 2438 2439 2440
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
    }
}

2441 2442
// Whether a type is Plain Old Data -- meaning it does not contain pointers
// that the cycle collector might care about.
2443
pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
2444
    let mut result = true;
2445
    match get(ty).sty {
B
Brian Anderson 已提交
2446
      // Scalar types
2447
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
2448
      ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
B
Brian Anderson 已提交
2449
      // Boxed types
2450
      ty_box(_) | ty_uniq(_) | ty_closure(_) |
2451 2452
      ty_estr(vstore_uniq) | ty_estr(vstore_box) |
      ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2453
      ty_trait(_, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
B
Brian Anderson 已提交
2454
      // Structural types
N
Niko Matsakis 已提交
2455
      ty_enum(did, ref substs) => {
2456
        let variants = enum_variants(cx, did);
2457
        for (*variants).each |variant| {
2458
            let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
B
Brian Anderson 已提交
2459 2460

            // Perform any type parameter substitutions.
2461
            let tup_ty = subst(cx, substs, tup_ty);
B
Brian Anderson 已提交
2462
            if !type_is_pod(cx, tup_ty) { result = false; }
2463
        }
B
Brian Anderson 已提交
2464
      }
2465
      ty_tup(ref elts) => {
2466
        for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
B
Brian Anderson 已提交
2467
      }
B
Brian Anderson 已提交
2468
      ty_estr(vstore_fixed(_)) => result = true,
2469
      ty_evec(ref mt, vstore_fixed(_)) | ty_unboxed_vec(ref mt) => {
2470 2471
        result = type_is_pod(cx, mt.ty);
      }
B
Brian Anderson 已提交
2472 2473
      ty_param(_) => result = false,
      ty_opaque_closure_ptr(_) => result = true,
2474 2475
      ty_struct(did, ref substs) => {
        result = vec::any(lookup_struct_fields(cx, did), |f| {
2476 2477 2478
            let fty = ty::lookup_item_type(cx, f.id);
            let sty = subst(cx, substs, fty.ty);
            type_is_pod(cx, sty)
2479
        });
2480
      }
2481

B
Brian Anderson 已提交
2482
      ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2483 2484 2485
        result = false;
      }

2486
      ty_infer(*) | ty_self(*) | ty_err => {
2487
        cx.sess.bug(~"non concrete type in type_is_pod");
2488
      }
P
Patrick Walton 已提交
2489 2490
    }

B
Brian Anderson 已提交
2491
    return result;
P
Patrick Walton 已提交
2492 2493
}

2494
pub fn type_is_enum(ty: t) -> bool {
2495
    match get(ty).sty {
B
Brian Anderson 已提交
2496 2497
      ty_enum(_, _) => return true,
      _ => return false
2498 2499 2500
    }
}

P
Patrick Walton 已提交
2501
// Whether a type is enum like, that is a enum type with only nullary
2502
// constructors
2503
pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2504
    match get(ty).sty {
2505 2506 2507 2508 2509 2510 2511 2512 2513
        ty_enum(did, _) => {
            let variants = enum_variants(cx, did);
            if variants.len() == 0 {
                false
            } else {
                variants.all(|v| v.args.len() == 0)
            }
        }
        _ => false
2514 2515 2516
    }
}

2517
pub fn type_param(ty: t) -> Option<uint> {
2518
    match get(ty).sty {
B
Brian Anderson 已提交
2519
      ty_param(p) => return Some(p.idx),
B
Brian Anderson 已提交
2520
      _ => {/* fall through */ }
2521
    }
B
Brian Anderson 已提交
2522
    return None;
2523 2524
}

2525 2526
// Returns the type and mutability of *t.
//
2527 2528
// The parameter `explicit` indicates if this is an *explicit* dereference.
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
2529
pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
2530
    deref_sty(cx, &get(t).sty, explicit)
2531
}
2532

2533
pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
N
Niko Matsakis 已提交
2534
    match *sty {
B
Brian Anderson 已提交
2535
      ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
B
Brian Anderson 已提交
2536
        Some(mt)
2537 2538
      }

2539
      ty_ptr(mt) if explicit => {
B
Brian Anderson 已提交
2540
        Some(mt)
2541 2542
      }

N
Niko Matsakis 已提交
2543
      ty_enum(did, ref substs) => {
2544
        let variants = enum_variants(cx, did);
Y
Youngmin Yoo 已提交
2545
        if (*variants).len() == 1u && variants[0].args.len() == 1u {
2546
            let v_t = subst(cx, substs, variants[0].args[0]);
2547
            Some(mt {ty: v_t, mutbl: ast::m_imm})
2548
        } else {
B
Brian Anderson 已提交
2549
            None
2550 2551 2552
        }
      }

2553 2554
      ty_struct(did, ref substs) => {
        let fields = struct_fields(cx, did, substs);
2555 2556
        if fields.len() == 1 && fields[0].ident ==
                syntax::parse::token::special_idents::unnamed_field {
2557
            Some(mt {ty: fields[0].mt.ty, mutbl: ast::m_imm})
2558 2559 2560 2561 2562
        } else {
            None
        }
      }

B
Brian Anderson 已提交
2563
      _ => None
2564 2565 2566
    }
}

2567
pub fn type_autoderef(cx: ctxt, t: t) -> t {
2568
    let mut t = t;
2569
    loop {
2570
        match deref(cx, t, false) {
B
Brian Anderson 已提交
2571 2572
          None => return t,
          Some(mt) => t = mt.ty
2573 2574
        }
    }
2575 2576 2577
}

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

T
Tim Chevalier 已提交
2582
pub fn index_sty(sty: &sty) -> Option<mt> {
N
Niko Matsakis 已提交
2583
    match *sty {
B
Brian Anderson 已提交
2584
      ty_evec(mt, _) => Some(mt),
T
Tim Chevalier 已提交
2585
      ty_estr(_) => Some(mt {ty: mk_u8(), mutbl: ast::m_imm}),
B
Brian Anderson 已提交
2586
      _ => None
2587
    }
2588 2589
}

2590 2591 2592 2593 2594 2595 2596 2597 2598 2599
/**
 * 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)
    }
}
2600

2601 2602 2603 2604 2605
impl cmp::TotalEq for FreeRegion {
    fn equals(&self, other: &FreeRegion) -> bool {
        *self == *other
    }
}
2606

2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628
/**
 * 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,
2629 2630 2631
        }
    }
}
2632

2633 2634 2635
impl cmp::TotalEq for bound_region {
    fn equals(&self, other: &bound_region) -> bool {
        *self == *other
2636 2637 2638
    }
}

2639 2640 2641 2642 2643
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),
2644

2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660
          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),
        }
    }
}

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)
    }
}
2661

2662 2663 2664 2665 2666 2667
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)
    }
}
2668

2669 2670 2671 2672 2673 2674
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)
    }
}
2675

2676 2677 2678 2679 2680 2681 2682
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)
    }
}
2683

2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757
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),
        }
    }
}
2758

2759 2760 2761 2762 2763 2764 2765 2766 2767 2768
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)))
    }
}

2769
pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
2770
    //io::println(fmt!("%?/%?", id, cx.node_types.len()));
D
Daniel Micay 已提交
2771 2772
    match cx.node_types.find(&(id as uint)) {
       Some(&t) => t,
B
Brian Anderson 已提交
2773
       None => cx.sess.bug(
2774
           fmt!("node_id_to_type: no type for node `%s`",
P
Paul Stansifer 已提交
2775
                ast_map::node_id_to_str(cx.items, id,
P
Paul Stansifer 已提交
2776
                                        cx.sess.parse_sess.interner)))
T
Tim Chevalier 已提交
2777
    }
2778 2779
}

2780
pub fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2781
    match cx.node_type_substs.find(&id) {
B
Brian Anderson 已提交
2782
      None => return ~[],
2783
      Some(ts) => return /*bad*/ copy *ts
2784 2785 2786
    }
}

2787
fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
2788
    cx.node_type_substs.contains_key(&id)
2789 2790
}

2791 2792 2793 2794 2795
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 => {
2796
            fail!("ty_fn_sig() called on non-fn type: %?", s)
2797 2798 2799 2800
        }
    }
}

2801
// Type accessors for substructures of types
E
Erick Tryzelaar 已提交
2802
pub fn ty_fn_args(fty: t) -> ~[t] {
2803
    match get(fty).sty {
2804 2805 2806
        ty_bare_fn(ref f) => copy f.sig.inputs,
        ty_closure(ref f) => copy f.sig.inputs,
        ref s => {
2807
            fail!("ty_fn_args() called on non-fn type: %?", s)
2808
        }
2809 2810 2811
    }
}

2812
pub fn ty_closure_sigil(fty: t) -> Sigil {
2813
    match get(fty).sty {
2814 2815
        ty_closure(ref f) => f.sigil,
        ref s => {
2816
            fail!("ty_closure_sigil() called on non-closure type: %?", s)
2817
        }
M
Marijn Haverbeke 已提交
2818
    }
G
Graydon Hoare 已提交
2819 2820
}

2821
pub fn ty_fn_purity(fty: t) -> ast::purity {
2822
    match get(fty).sty {
2823 2824 2825
        ty_bare_fn(ref f) => f.purity,
        ty_closure(ref f) => f.purity,
        ref s => {
2826
            fail!("ty_fn_purity() called on non-fn type: %?", s)
2827
        }
2828 2829 2830
    }
}

2831
pub fn ty_fn_ret(fty: t) -> t {
2832
    match get(fty).sty {
2833 2834 2835
        ty_bare_fn(ref f) => f.sig.output,
        ty_closure(ref f) => f.sig.output,
        ref s => {
2836
            fail!("ty_fn_ret() called on non-fn type: %?", s)
2837
        }
2838
    }
G
Graydon Hoare 已提交
2839 2840
}

2841
pub fn is_fn_ty(fty: t) -> bool {
2842
    match get(fty).sty {
2843 2844 2845
        ty_bare_fn(_) => true,
        ty_closure(_) => true,
        _ => false
2846 2847 2848
    }
}

2849
pub fn ty_vstore(ty: t) -> vstore {
2850 2851 2852
    match get(ty).sty {
        ty_evec(_, vstore) => vstore,
        ty_estr(vstore) => vstore,
2853
        ref s => fail!("ty_vstore() called on invalid sty: %?", s)
2854 2855 2856
    }
}

2857 2858 2859
pub fn ty_region(tcx: ctxt,
                 span: span,
                 ty: t) -> Region {
2860
    match get(ty).sty {
2861 2862 2863 2864 2865 2866 2867 2868
        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));
        }
2869
    }
G
Graydon Hoare 已提交
2870 2871
}

N
Niko Matsakis 已提交
2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882
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));
        }
    }
}

2883
pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
2884 2885 2886 2887 2888 2889
    /*!
     *
     * Returns a new function type based on `fn_type` but returning a value of
     * type `ret_type` instead. */

    match ty::get(fn_type).sty {
2890 2891 2892 2893
        ty::ty_closure(ref fty) => {
            ty::mk_closure(tcx, ClosureTy {
                sig: FnSig {output: ret_type, ..copy fty.sig},
                ..copy *fty
2894 2895 2896 2897 2898 2899 2900 2901 2902 2903
            })
        }
        _ => {
            tcx.sess.bug(fmt!(
                "replace_fn_ret() invoked with non-fn-type: %s",
                ty_to_str(tcx, fn_type)));
        }
    }
}

2904
// Returns a vec of all the input and output types of fty.
2905
pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
E
Erick Tryzelaar 已提交
2906
    vec::append_one(sig.inputs.map(|a| *a), sig.output)
2907 2908
}

2909
// Type accessors for AST nodes
2910
pub fn block_ty(cx: ctxt, b: &ast::blk) -> t {
B
Brian Anderson 已提交
2911
    return node_id_to_type(cx, b.node.id);
2912
}
2913 2914


2915 2916
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
2917
pub fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
B
Brian Anderson 已提交
2918
    return node_id_to_type(cx, pat.id);
2919 2920
}

2921

2922 2923
// Returns the type of an expression as a monotype.
//
2924 2925 2926 2927 2928 2929
// 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
2930
// ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
2931
// instead of "fn(t) -> T with T = int". If this isn't what you want, see
2932
// expr_ty_params_and_ty() below.
2933
pub fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
B
Brian Anderson 已提交
2934
    return node_id_to_type(cx, expr.id);
2935 2936
}

2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951
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);
2952
    adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find_copy(&expr.id))
2953 2954 2955 2956 2957
}

pub fn adjust_ty(cx: ctxt,
                 span: span,
                 unadjusted_ty: ty::t,
2958
                 adjustment: Option<@AutoAdjustment>) -> ty::t
2959 2960
{
    /*! See `expr_ty_adjusted` */
2961

2962
    return match adjustment {
2963 2964
        None => unadjusted_ty,

2965
        Some(@AutoAddEnv(r, s)) => {
2966 2967 2968 2969 2970 2971 2972 2973
            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,
2974
                                       bounds: ty::AllBuiltinBounds(),
2975 2976 2977 2978 2979 2980 2981 2982 2983
                                       sig: copy b.sig})
                }
                ref b => {
                    cx.sess.bug(
                        fmt!("add_env adjustment on non-bare-fn: %?", b));
                }
            }
        }

2984
        Some(@AutoDerefRef(ref adj)) => {
2985 2986 2987 2988 2989 2990 2991
            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(
2992
                            span,
2993 2994 2995 2996 2997 2998 2999 3000 3001 3002
                            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 已提交
3003 3004 3005
                    match *autoref {
                        AutoPtr(r, m) => {
                            mk_rptr(cx, r, mt {ty: adjusted_ty, mutbl: m})
3006 3007
                        }

N
Niko Matsakis 已提交
3008 3009
                        AutoBorrowVec(r, m) => {
                            borrow_vec(cx, span, r, m, adjusted_ty)
3010 3011
                        }

N
Niko Matsakis 已提交
3012 3013 3014
                        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})
3015 3016
                        }

N
Niko Matsakis 已提交
3017 3018 3019 3020 3021 3022
                        AutoBorrowFn(r) => {
                            borrow_fn(cx, span, r, adjusted_ty)
                        }

                        AutoUnsafe(m) => {
                            mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
3023 3024 3025 3026 3027 3028 3029
                        }
                    }
                }
            }
        }
    };

3030
    fn borrow_vec(cx: ctxt, span: span,
N
Niko Matsakis 已提交
3031 3032
                  r: Region, m: ast::mutability,
                  ty: ty::t) -> ty::t {
3033 3034
        match get(ty).sty {
            ty_evec(mt, _) => {
N
Niko Matsakis 已提交
3035
                ty::mk_evec(cx, mt {ty: mt.ty, mutbl: m}, vstore_slice(r))
3036 3037 3038
            }

            ty_estr(_) => {
N
Niko Matsakis 已提交
3039
                ty::mk_estr(cx, vstore_slice(r))
3040 3041 3042 3043
            }

            ref s => {
                cx.sess.span_bug(
3044
                    span,
3045 3046 3047 3048 3049 3050
                    fmt!("borrow-vec associated with bad sty: %?",
                         s));
            }
        }
    }

N
Niko Matsakis 已提交
3051
    fn borrow_fn(cx: ctxt, span: span, r: Region, ty: ty::t) -> ty::t {
3052
        match get(ty).sty {
3053 3054 3055
            ty_closure(ref fty) => {
                ty::mk_closure(cx, ClosureTy {
                    sigil: BorrowedSigil,
N
Niko Matsakis 已提交
3056
                    region: r,
3057 3058
                    ..copy *fty
                })
3059 3060 3061 3062
            }

            ref s => {
                cx.sess.span_bug(
3063
                    span,
3064 3065 3066 3067 3068 3069 3070
                    fmt!("borrow-fn associated with bad sty: %?",
                         s));
            }
        }
    }
}

N
Niko Matsakis 已提交
3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082
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),
        }
    }
}

3083 3084 3085 3086 3087
pub struct ParamsTy {
    params: ~[t],
    ty: t
}

3088 3089
pub fn expr_ty_params_and_ty(cx: ctxt,
                             expr: @ast::expr)
3090 3091 3092 3093 3094
                          -> ParamsTy {
    ParamsTy {
        params: node_id_to_type_params(cx, expr.id),
        ty: node_id_to_type(cx, expr.id)
    }
3095 3096
}

3097
pub fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
B
Brian Anderson 已提交
3098
    return node_id_has_type_params(cx, expr.id);
3099 3100
}

3101 3102 3103 3104 3105
pub fn method_call_type_param_defs(
    tcx: ctxt,
    method_map: typeck::method_map,
    id: ast::node_id) -> Option<@~[TypeParameterDef]>
{
3106
    do method_map.find(&id).map |method| {
3107 3108
        match method.origin {
          typeck::method_static(did) => {
3109 3110
            // n.b.: When we encode impl methods, the bounds
            // that we encode include both the impl bounds
3111
            // and then the method bounds themselves...
3112
            ty::lookup_item_type(tcx, did).generics.type_param_defs
3113
          }
3114 3115 3116
          typeck::method_param(typeck::method_param {
              trait_id: trt_id,
              method_num: n_mth, _}) |
3117
          typeck::method_trait(trt_id, n_mth, _) |
3118 3119
          typeck::method_self(trt_id, n_mth) |
          typeck::method_super(trt_id, n_mth) => {
3120 3121 3122
            // ...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.
3123 3124 3125 3126 3127
            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)
3128 3129 3130 3131 3132
          }
        }
    }
}

3133
pub fn resolve_expr(tcx: ctxt, expr: @ast::expr) -> ast::def {
3134
    match tcx.def_map.find(&expr.id) {
3135
        Some(&def) => def,
3136 3137 3138 3139 3140 3141 3142
        None => {
            tcx.sess.span_bug(expr.span, fmt!(
                "No def-map entry for expr %?", expr.id));
        }
    }
}

3143 3144 3145
pub fn expr_is_lval(tcx: ctxt,
                    method_map: typeck::method_map,
                    e: @ast::expr) -> bool {
3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156
    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.
3157
pub enum ExprKind {
3158 3159 3160 3161 3162 3163
    LvalueExpr,
    RvalueDpsExpr,
    RvalueDatumExpr,
    RvalueStmtExpr
}

3164 3165 3166
pub fn expr_kind(tcx: ctxt,
                 method_map: typeck::method_map,
                 expr: @ast::expr) -> ExprKind {
3167
    if method_map.contains_key(&expr.id) {
3168 3169 3170 3171 3172 3173 3174 3175 3176 3177
        // 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 {
3178
        ast::expr_path(*) | ast::expr_self => {
3179
            match resolve_expr(tcx, expr) {
3180
                ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3181

3182 3183 3184
                // Fn pointers are just scalar values.
                ast::def_fn(*) | ast::def_static_method(*) => RvalueDatumExpr,

3185 3186 3187 3188 3189 3190 3191 3192 3193 3194
                // 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 已提交
3195
                def => {
3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209
                    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(*) |
3210
        ast::expr_method_call(*) |
3211 3212 3213 3214 3215 3216 3217 3218 3219 3220
        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 已提交
3221
        ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
3222
        ast::expr_vstore(_, ast::expr_vstore_slice) |
3223
        ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3224 3225 3226 3227 3228
        ast::expr_vec(*) => {
            RvalueDpsExpr
        }

        ast::expr_cast(*) => {
D
Daniel Micay 已提交
3229 3230
            match tcx.node_types.find(&(expr.id as uint)) {
                Some(&t) => {
3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260
                    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(*) |
3261
        ast::expr_inline_asm(*) |
3262 3263 3264 3265 3266 3267 3268 3269
        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(*) |
3270
        ast::expr_vstore(_, ast::expr_vstore_box) |
3271
        ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3272
        ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3273 3274 3275
            RvalueDatumExpr
        }

3276 3277
        ast::expr_paren(e) => expr_kind(tcx, method_map, e),

3278 3279 3280
        ast::expr_mac(*) => {
            tcx.sess.span_bug(
                expr.span,
S
Seo Sanghyeon 已提交
3281
                "macro expression remains after expansion");
3282
        }
M
Marijn Haverbeke 已提交
3283 3284 3285
    }
}

3286
pub fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3287
    match s.node {
B
Brian Anderson 已提交
3288
      ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
B
Brian Anderson 已提交
3289
        return id;
3290
      }
3291
      ast::stmt_mac(*) => fail!("unexpanded macro in trans")
3292 3293 3294
    }
}

3295
pub fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3296
    let mut i = 0u;
B
Brian Anderson 已提交
3297 3298
    for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
    return None;
3299 3300
}

3301 3302
pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
                     -> uint {
3303 3304 3305 3306
    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 `%?`",
3307
        *tcx.sess.str_of(id),
3308 3309 3310
        fields.map(|f| tcx.sess.str_of(f.ident))));
}

3311
pub fn method_idx(id: ast::ident, meths: &[@Method]) -> Option<uint> {
3312
    vec::position(meths, |m| m.ident == id)
3313 3314
}

3315 3316 3317
/// 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.
3318
pub fn param_tys_in_type(ty: t) -> ~[param_ty] {
3319 3320
    let mut rslt = ~[];
    do walk_ty(ty) |ty| {
3321
        match get(ty).sty {
B
Brian Anderson 已提交
3322
          ty_param(p) => {
3323
            rslt.push(p);
3324
          }
B
Brian Anderson 已提交
3325
          _ => ()
3326 3327 3328 3329 3330
        }
    }
    rslt
}

3331
pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3332 3333
    // Returns a vec of all the type variables occurring in `ty`. It may
    // contain duplicates.  (Integral type vars aren't counted.)
3334
    fn vars_in_type(ty: t) -> ~[TyVid] {
3335
        let mut rslt = ~[];
B
Brian Anderson 已提交
3336
        do walk_ty(ty) |ty| {
3337
            match get(ty).sty {
3338
              ty_infer(TyVar(v)) => rslt.push(v),
B
Brian Anderson 已提交
3339 3340
              _ => ()
            }
3341 3342 3343 3344
        }
        rslt
    }

3345
    // Fast path
B
Brian Anderson 已提交
3346
    if !type_needs_infer(rt) { return; }
B
Brian Anderson 已提交
3347

T
Tim Chevalier 已提交
3348
    // Occurs check!
N
Niko Matsakis 已提交
3349
    if vec::contains(vars_in_type(rt), &vid) {
T
Tim Chevalier 已提交
3350 3351 3352
            // 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.
3353
            tcx.sess.span_fatal
3354
                (sp, ~"type inference failed because I \
3355
                     could not find a type\n that's both of the form "
3356 3357
                 + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
                 ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
3358
                 ~" - such a type would have to be infinitely large.");
3359
    }
T
Tim Chevalier 已提交
3360
}
3361

3362
pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3363
    match get(t).sty {
N
Niko Matsakis 已提交
3364
      ty_nil | ty_bot | ty_bool | ty_int(_) |
M
Michael Sullivan 已提交
3365
      ty_uint(_) | ty_float(_) | ty_estr(_) |
B
Brian Anderson 已提交
3366
      ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
3367
        ::util::ppaux::ty_to_str(cx, t)
N
Niko Matsakis 已提交
3368 3369
      }

P
Paul Stansifer 已提交
3370
      ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3371 3372 3373 3374 3375 3376
      ty_box(_) => ~"@-ptr",
      ty_uniq(_) => ~"~-ptr",
      ty_evec(_, _) => ~"vector",
      ty_unboxed_vec(_) => ~"unboxed vector",
      ty_ptr(_) => ~"*-ptr",
      ty_rptr(_, _) => ~"&-ptr",
3377 3378
      ty_bare_fn(_) => ~"extern fn",
      ty_closure(_) => ~"fn",
3379
      ty_trait(id, _, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3380
      ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3381
      ty_tup(_) => ~"tuple",
3382 3383
      ty_infer(TyVar(_)) => ~"inferred type",
      ty_infer(IntVar(_)) => ~"integral variable",
3384
      ty_infer(FloatVar(_)) => ~"floating-point variable",
B
Brian Anderson 已提交
3385
      ty_param(_) => ~"type parameter",
3386
      ty_self(_) => ~"self",
3387
      ty_err => ~"type error"
N
Niko Matsakis 已提交
3388 3389 3390
    }
}

3391
pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3392 3393 3394 3395 3396 3397 3398 3399 3400
    /*!
     *
     * 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. */

3401
    fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3402 3403 3404
        match k {
            terr_vec => ~"[]",
            terr_str => ~"str",
3405 3406
            terr_fn => ~"fn",
            terr_trait => ~"trait"
3407
        }
3408 3409
    }

N
Niko Matsakis 已提交
3410
    match *err {
3411 3412 3413
        terr_mismatch => ~"types differ",
        terr_purity_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3414
                 values.expected.to_str(), values.found.to_str())
3415
        }
3416 3417 3418 3419
        terr_abi_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
                 values.expected.to_str(), values.found.to_str())
        }
3420 3421
        terr_onceness_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3422
                 values.expected.to_str(), values.found.to_str())
3423
        }
3424
        terr_sigil_mismatch(values) => {
3425
            fmt!("expected %s closure, found %s closure",
3426 3427
                 values.expected.to_str(),
                 values.found.to_str())
3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454
        }
        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`",
3455 3456
                 *cx.sess.str_of(values.expected),
                 *cx.sess.str_of(values.found))
3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477
        }
        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))
        }
3478
        terr_vstores_differ(k, ref values) => {
3479 3480
            fmt!("%s storage differs: expected %s but found %s",
                 terr_vstore_kind_to_str(k),
3481 3482
                 vstore_to_str(cx, (*values).expected),
                 vstore_to_str(cx, (*values).found))
3483
        }
3484 3485 3486 3487 3488
        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))
        }
3489
        terr_in_field(err, fname) => {
3490
            fmt!("in field `%s`, %s", *cx.sess.str_of(fname),
3491 3492 3493 3494 3495 3496 3497
                 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))
        }
3498 3499 3500 3501 3502
        terr_traits(values) => {
            fmt!("expected trait %s but found trait %s",
                 item_path_str(cx, values.expected),
                 item_path_str(cx, values.found))
        }
3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515
        terr_builtin_bounds(values) => {
            if values.expected.is_empty() {
                fmt!("expected no bounds but found `%s`",
                     values.found.user_string(cx))
            } else if values.found.is_empty() {
                fmt!("expected bounds `%s` but found no bounds",
                     values.expected.user_string(cx))
            } else {
                fmt!("expected bounds `%s` but found bounds `%s`",
                     values.expected.user_string(cx),
                     values.found.user_string(cx))
            }
        }
3516
        terr_integer_as_char => {
3517
            fmt!("expected an integral type but found char")
3518
        }
3519 3520 3521 3522 3523 3524 3525 3526 3527
        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())
3528
        }
3529 3530 3531
    }
}

3532
pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548
    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, ~"");
        }
3549 3550 3551 3552 3553 3554 3555 3556 3557 3558
        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, ~"");
        }
3559 3560 3561 3562
        _ => {}
    }
}

3563
pub fn def_has_ty_params(def: ast::def) -> bool {
3564
    match def {
3565
      ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
B
Brian Anderson 已提交
3566 3567
        => true,
      _ => false
3568 3569 3570
    }
}

3571
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3572
    if is_local(id) {
3573
        match cx.items.find(&id.node) {
A
Alex Crichton 已提交
3574
            Some(&ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
3575 3576 3577
                        node: item_trait(_, _, ref ms),
                        _
                    }, _)) =>
3578
                match ast_util::split_trait_methods(*ms) {
3579
                   (_, p) => p.map(|method| method.ident)
3580
                },
3581
            _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3582 3583
                                  id))
        }
3584
    } else {
3585
        csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3586 3587 3588
    }
}

3589
pub fn trait_supertraits(cx: ctxt,
3590 3591
                         id: ast::def_id) -> @~[@TraitRef]
{
3592
    // Check the cache.
3593
    match cx.supertraits.find(&id) {
3594
        Some(&trait_refs) => { return trait_refs; }
3595 3596 3597 3598 3599
        None => {}  // Continue.
    }

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

    // Get the supertraits out of the metadata and create the
3603 3604 3605 3606
    // TraitRef for each.
    let result = @csearch::get_supertraits(cx, id);
    cx.supertraits.insert(id, result);
    return result;
3607
}
3608

3609 3610 3611
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(
3612
        |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs))
3613 3614
}

3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637
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 {
3638
        fail!("No def'n found for %? in tcx.%s", def_id, descr);
3639 3640 3641 3642 3643 3644
    }
    let v = load_external();
    map.insert(def_id, v);
    return v;
}

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

3650
pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] {
3651 3652 3653 3654 3655 3656 3657 3658
    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
        }
3659 3660
    }
}
3661

3662
pub fn method(cx: ctxt, id: ast::def_id) -> @Method {
3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673
    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))
}

3674
pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
3675
    if id.crate == ast::local_crate {
3676
        debug!("(impl_trait_ref) searching for trait impl %?", id);
3677
        match cx.items.find(&id.node) {
A
Alex Crichton 已提交
3678
           Some(&ast_map::node_item(@ast::item {
3679
                        node: ast::item_impl(_, opt_trait, _, _),
3680
                        _},
B
Brian Anderson 已提交
3681
                    _)) => {
3682
               match opt_trait {
3683 3684
                   Some(t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
                   None => None
3685
               }
3686
           }
3687
           _ => None
3688
        }
3689
    } else {
3690
        csearch::get_impl_trait(cx, id)
3691 3692 3693
    }
}

3694
pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3695
    match get(ty).sty {
3696
      ty_trait(id, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
B
Brian Anderson 已提交
3697
      _ => None
3698 3699 3700
    }
}

3701 3702 3703 3704 3705 3706 3707 3708 3709
/// 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");
    }

3710
    match cx.items.find(&struct_did.node) {
A
Alex Crichton 已提交
3711
        Some(&ast_map::node_item(item, _)) => {
3712
            match item.node {
3713
                ast::item_struct(struct_def, _) => {
3714 3715 3716 3717 3718 3719 3720 3721 3722 3723
                    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")
    }
}

3724
// Enum information
3725
pub struct VariantInfo_ {
3726 3727 3728 3729 3730 3731 3732 3733
    args: ~[t],
    ctor_ty: t,
    name: ast::ident,
    id: ast::def_id,
    disr_val: int,
    vis: visibility
}

3734
pub type VariantInfo = @VariantInfo_;
M
Marijn Haverbeke 已提交
3735

3736 3737 3738 3739
pub fn substd_enum_variants(cx: ctxt,
                            id: ast::def_id,
                            substs: &substs)
                         -> ~[VariantInfo] {
B
Brian Anderson 已提交
3740 3741
    do vec::map(*enum_variants(cx, id)) |variant_info| {
        let substd_args = vec::map(variant_info.args,
3742
                                   |aty| subst(cx, substs, *aty));
3743

3744
        let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3745

3746
        @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
3747
                      ../*bad*/copy **variant_info}
3748 3749 3750
    }
}

3751
pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
P
Paul Stansifer 已提交
3752
    ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3753 3754
}

3755
pub enum DtorKind {
3756 3757 3758 3759
    NoDtor,
    TraitDtor(def_id)
}

3760
pub impl DtorKind {
3761
    fn is_not_present(&const self) -> bool {
3762 3763 3764 3765 3766
        match *self {
            NoDtor => true,
            _ => false
        }
    }
3767
    fn is_present(&const self) -> bool {
3768 3769 3770 3771
        !self.is_not_present()
    }
}

3772
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
3773
   Otherwise return none. */
3774
pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
3775
    match cx.destructor_for_type.find(&struct_id) {
E
Erick Tryzelaar 已提交
3776
        Some(&method_def_id) => TraitDtor(method_def_id),
3777
        None => NoDtor,
3778 3779 3780
    }
}

3781
pub fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
3782
    ty_dtor(cx, struct_id).is_present()
3783 3784
}

3785
pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
3786 3787 3788
    if id.crate != ast::local_crate {
        csearch::get_item_path(cx, id)
    } else {
A
Alex Crichton 已提交
3789 3790 3791 3792 3793 3794
        // 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 已提交
3795
          ast_map::node_item(item, path) => {
3796
            let item_elt = match item.node {
B
Brian Anderson 已提交
3797
              item_mod(_) | item_foreign_mod(_) => {
3798 3799
                ast_map::path_mod(item.ident)
              }
B
Brian Anderson 已提交
3800
              _ => {
3801 3802 3803
                ast_map::path_name(item.ident)
              }
            };
3804
            vec::append_one(/*bad*/copy *path, item_elt)
3805 3806
          }

3807
          ast_map::node_foreign_item(nitem, _, _, path) => {
3808 3809
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(nitem.ident))
3810 3811
          }

B
Brian Anderson 已提交
3812
          ast_map::node_method(method, _, path) => {
3813 3814
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
3815
          }
B
Brian Anderson 已提交
3816
          ast_map::node_trait_method(trait_method, _, path) => {
3817
            let method = ast_util::trait_method_to_ty_method(&*trait_method);
3818 3819
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
3820
          }
3821

3822
          ast_map::node_variant(ref variant, _, path) => {
3823
            vec::append_one(vec::to_owned(vec::init(*path)),
3824
                            ast_map::path_name((*variant).node.name))
3825 3826
          }

3827
          ast_map::node_struct_ctor(_, item, path) => {
3828
            vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
3829 3830
          }

A
Alex Crichton 已提交
3831
          ref node => {
P
Paul Stansifer 已提交
3832
            cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3833 3834 3835 3836 3837
          }
        }
    }
}

3838
pub fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3839
    enum_variants(cx, id).len() == 1
3840 3841
}

3842
pub fn type_is_empty(cx: ctxt, t: t) -> bool {
3843
    match ty::get(t).sty {
B
Brian Anderson 已提交
3844 3845
       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
       _ => false
3846 3847 3848
     }
}

3849
pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3850
    match cx.enum_var_cache.find(&id) {
3851
      Some(&variants) => return variants,
B
Brian Anderson 已提交
3852
      _ => { /* fallthrough */ }
3853
    }
3854

3855
    let result = if ast::local_crate != id.crate {
3856
        @csearch::get_enum_variants(cx, id)
3857
    } else {
3858 3859 3860 3861 3862
        /*
          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
         */
3863
        match cx.items.get_copy(&id.node) {
3864
          ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
3865 3866 3867
                    node: ast::item_enum(ref enum_definition, _),
                    _
                }, _) => {
3868
            let mut disr_val = -1;
3869
            @vec::map(enum_definition.variants, |variant| {
3870
                match variant.node.kind {
3871
                    ast::tuple_variant_kind(ref args) => {
3872 3873
                        let ctor_ty = node_id_to_type(cx, variant.node.id);
                        let arg_tys = {
3874
                            if args.len() > 0u {
E
Erick Tryzelaar 已提交
3875
                                ty_fn_args(ctor_ty).map(|a| *a)
3876 3877 3878 3879 3880
                            } else {
                                ~[]
                            }
                        };
                        match variant.node.disr_expr {
B
Brian Anderson 已提交
3881
                          Some (ex) => {
3882 3883 3884 3885 3886 3887 3888 3889
                            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
                        }
3890
                        @VariantInfo_{args: arg_tys,
3891 3892 3893
                          ctor_ty: ctor_ty,
                          name: variant.node.name,
                          id: ast_util::local_def(variant.node.id),
3894 3895
                          disr_val: disr_val,
                          vis: variant.node.vis
3896
                         }
3897
                    }
3898
                    ast::struct_variant_kind(_) => {
3899
                        fail!("struct variant kinds unimpl in enum_variants")
3900
                    }
3901
                }
3902
            })
M
Marijn Haverbeke 已提交
3903
          }
B
Brian Anderson 已提交
3904
          _ => cx.sess.bug(~"tag_variants: id not bound to an enum")
3905
        }
3906
    };
3907
    cx.enum_var_cache.insert(id, result);
3908
    result
3909 3910
}

3911

P
Patrick Walton 已提交
3912
// Returns information about the enum variant with the given ID:
3913 3914 3915 3916
pub fn enum_variant_with_id(cx: ctxt,
                            enum_id: ast::def_id,
                            variant_id: ast::def_id)
                         -> VariantInfo {
3917
    let variants = enum_variants(cx, enum_id);
3918 3919
    let mut i = 0;
    while i < variants.len() {
B
Brian Anderson 已提交
3920
        let variant = variants[i];
3921
        if variant.id == variant_id { return variant; }
3922
        i += 1;
3923
    }
3924
    cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
3925 3926
}

3927

3928 3929
// 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.
3930 3931 3932
pub fn lookup_item_type(cx: ctxt,
                        did: ast::def_id)
                     -> ty_param_bounds_and_ty {
3933 3934 3935
    lookup_locally_or_in_crate_store(
        "tcache", did, cx.tcache,
        || csearch::get_type(cx, did))
T
Tim Chevalier 已提交
3936 3937
}

3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954
/// 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;
        }
    }
}

3955 3956
/// Determine whether an item is annotated with an attribute
pub fn has_attr(tcx: ctxt, did: def_id, attr: &str) -> bool {
3957 3958 3959 3960 3961 3962
    if is_local(did) {
        match tcx.items.find(&did.node) {
            Some(
                &ast_map::node_item(@ast::item {
                    attrs: ref attrs,
                    _
3963
                }, _)) => attr::attrs_contains_name(*attrs, attr),
S
Seo Sanghyeon 已提交
3964
            _ => tcx.sess.bug(fmt!("has_attr: %? is not an item",
3965 3966 3967 3968 3969
                                   did))
        }
    } else {
        let mut ret = false;
        do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
3970
            ret = attr::contains_name(meta_items, attr);
3971 3972 3973 3974 3975
        }
        ret
    }
}

S
Seo Sanghyeon 已提交
3976
/// Determine whether an item is annotated with `#[packed]`
3977 3978 3979 3980
pub fn lookup_packed(tcx: ctxt, did: def_id) -> bool {
    has_attr(tcx, did, "packed")
}

S
Seo Sanghyeon 已提交
3981
/// Determine whether an item is annotated with `#[simd]`
S
Seo Sanghyeon 已提交
3982 3983 3984 3985
pub fn lookup_simd(tcx: ctxt, did: def_id) -> bool {
    has_attr(tcx, did, "simd")
}

T
Tim Chevalier 已提交
3986
// Look up a field ID, whether or not it's local
3987
// Takes a list of type substs in case the struct is generic
3988 3989 3990 3991 3992
pub fn lookup_field_type(tcx: ctxt,
                         struct_id: def_id,
                         id: def_id,
                         substs: &substs)
                      -> ty::t {
3993
    let t = if id.crate == ast::local_crate {
T
Tim Chevalier 已提交
3994 3995 3996
        node_id_to_type(tcx, id.node)
    }
    else {
3997
        match tcx.tcache.find(&id) {
N
Niko Matsakis 已提交
3998
           Some(&ty_param_bounds_and_ty {ty, _}) => ty,
B
Brian Anderson 已提交
3999
           None => {
4000
               let tpt = csearch::get_field_type(tcx, struct_id, id);
T
Tim Chevalier 已提交
4001
               tcx.tcache.insert(id, tpt);
4002
               tpt.ty
T
Tim Chevalier 已提交
4003 4004
           }
        }
4005
    };
4006
    subst(tcx, substs, t)
T
Tim Chevalier 已提交
4007 4008
}

4009 4010
// Look up the list of field names and IDs for a given struct
// Fails if the id is not bound to a struct.
4011
pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
4012
  if did.crate == ast::local_crate {
4013
    match cx.items.find(&did.node) {
A
Alex Crichton 已提交
4014
       Some(&ast_map::node_item(i,_)) => {
4015
         match i.node {
4016
            ast::item_struct(struct_def, _) => {
4017
               struct_field_tys(struct_def.fields)
4018
            }
4019
            _ => cx.sess.bug(~"struct ID bound to non-struct")
T
Tim Chevalier 已提交
4020
         }
T
Tim Chevalier 已提交
4021
       }
A
Alex Crichton 已提交
4022
       Some(&ast_map::node_variant(ref variant, _, _)) => {
4023
          match (*variant).node.kind {
4024
            ast::struct_variant_kind(struct_def) => {
4025
              struct_field_tys(struct_def.fields)
4026 4027 4028 4029 4030 4031 4032
            }
            _ => {
              cx.sess.bug(~"struct ID bound to enum variant that isn't \
                            struct-like")
            }
          }
       }
B
Brian Anderson 已提交
4033
       _ => {
P
Paul Stansifer 已提交
4034
           cx.sess.bug(
4035
               fmt!("struct ID not bound to an item: %s",
P
Paul Stansifer 已提交
4036
                    ast_map::node_id_to_str(cx.items, did.node,
P
Paul Stansifer 已提交
4037
                                            cx.sess.parse_sess.interner)));
4038
       }
T
Tim Chevalier 已提交
4039
    }
T
Tim Chevalier 已提交
4040
        }
4041
  else {
4042
        return csearch::get_struct_fields(cx.sess.cstore, did);
T
Tim Chevalier 已提交
4043 4044 4045
    }
}

4046 4047 4048 4049
pub fn lookup_struct_field(cx: ctxt,
                           parent: ast::def_id,
                           field_id: ast::def_id)
                        -> field_ty {
4050
    match vec::find(lookup_struct_fields(cx, parent),
B
Brian Anderson 已提交
4051
                 |f| f.id.node == field_id.node) {
B
Brian Anderson 已提交
4052
        Some(t) => t,
4053
        None => cx.sess.bug(~"struct ID not found in parent's fields")
4054 4055 4056
    }
}

4057
fn struct_field_tys(fields: &[@struct_field]) -> ~[field_ty] {
4058
    do fields.map |field| {
4059
        match field.node.kind {
4060
            named_field(ident, visibility) => {
4061 4062 4063 4064 4065
                field_ty {
                    ident: ident,
                    id: ast_util::local_def(field.node.id),
                    vis: visibility,
                }
4066
            }
4067
            unnamed_field => {
4068 4069 4070 4071 4072 4073
                field_ty {
                    ident:
                        syntax::parse::token::special_idents::unnamed_field,
                    id: ast_util::local_def(field.node.id),
                    vis: ast::public,
                }
4074
            }
4075
        }
T
Tim Chevalier 已提交
4076
    }
T
Tim Chevalier 已提交
4077 4078
}

4079 4080 4081 4082
// 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] {
4083
    do lookup_struct_fields(cx, did).map |f| {
4084
       field {
4085
            ident: f.ident,
4086 4087
            mt: mt {
                ty: lookup_field_type(cx, did, f.id, substs),
4088
                mutbl: m_imm
4089 4090
            }
        }
T
Tim Chevalier 已提交
4091 4092 4093
    }
}

4094
pub fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109
    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 已提交
4110 4111

    fn opcat(op: ast::binop) -> int {
4112
        match op {
B
Brian Anderson 已提交
4113 4114 4115
          ast::add => opcat_add,
          ast::subtract => opcat_sub,
          ast::mul => opcat_mult,
4116
          ast::div => opcat_mult,
B
Brian Anderson 已提交
4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130
          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 已提交
4131 4132 4133
        }
    }

4134
    fn tycat(ty: t) -> int {
4135
        match get(ty).sty {
B
Brian Anderson 已提交
4136
          ty_bool => tycat_bool,
4137
          ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4138
          ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
4139
          ty_tup(_) | ty_enum(_, _) => tycat_struct,
B
Brian Anderson 已提交
4140 4141
          ty_bot => tycat_bot,
          _ => tycat_other
M
Marijn Haverbeke 已提交
4142 4143 4144
        }
    }

4145 4146
    static t: bool = true;
    static f: bool = false;
4147

4148
    let tbl = ~[
4149 4150 4151
    /*.          add,     shift,   bit
      .             sub,     rel,     logic
      .                mult,    eq,         */
4152
    /*other*/   ~[f, f, f, f, f, f, f, f],
4153 4154 4155
    /*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],
4156 4157
    /*bot*/     ~[f, f, f, f, f, f, f, f],
    /*struct*/  ~[t, t, t, t, f, f, t, t]];
B
Brian Anderson 已提交
4158

B
Brian Anderson 已提交
4159
    return tbl[tycat(ty)][opcat(op)];
4160 4161
}

4162 4163 4164 4165 4166
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))
    })
4167
}
4168

4169
/// Returns an equivalent type with all the typedefs and self regions removed.
4170
pub fn normalize_ty(cx: ctxt, t: t) -> t {
4171
    fn normalize_mt(cx: ctxt, mt: mt) -> mt {
4172
        mt { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
4173 4174 4175 4176 4177 4178 4179 4180
    }
    fn normalize_vstore(vstore: vstore) -> vstore {
        match vstore {
            vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
            vstore_slice(_) => vstore_slice(re_static)
        }
    }

4181
    match cx.normalized_cache.find(&t) {
4182
      Some(&t) => return t,
B
Brian Anderson 已提交
4183
      None => ()
B
Brian Anderson 已提交
4184 4185
    }

4186
    let t = match get(t).sty {
4187 4188 4189 4190
        ty_evec(mt, vstore) =>
            // This type has a vstore. Get rid of it
            mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),

4191 4192 4193 4194
        ty_estr(vstore) =>
            // This type has a vstore. Get rid of it
            mk_estr(cx, normalize_vstore(vstore)),

E
Erick Tryzelaar 已提交
4195
        ty_rptr(_, mt) =>
4196
            // This type has a region. Get rid of it
4197 4198
            mk_rptr(cx, re_static, normalize_mt(cx, mt)),

4199 4200 4201 4202
        ty_closure(ref closure_ty) => {
            mk_closure(cx, ClosureTy {
                region: ty::re_static,
                ..copy *closure_ty
4203 4204
            })
        }
4205

4206 4207
        ty_enum(did, ref r) =>
            match (*r).self_r {
B
Brian Anderson 已提交
4208
                Some(_) =>
4209
                    // Use re_static since trans doesn't care about regions
E
Eric Holk 已提交
4210
                    mk_enum(cx, did,
4211 4212 4213 4214 4215
                     substs {
                        self_r: Some(ty::re_static),
                        self_ty: None,
                        tps: /*bad*/copy (*r).tps
                     }),
B
Brian Anderson 已提交
4216
                None =>
4217 4218 4219
                    t
            },

4220
        ty_struct(did, ref r) =>
4221
            match (*r).self_r {
B
Brian Anderson 已提交
4222
              Some(_) =>
4223
                // Ditto.
4224 4225 4226
                mk_struct(cx, did, substs {self_r: Some(ty::re_static),
                                           self_ty: None,
                                           tps: /*bad*/copy (*r).tps}),
B
Brian Anderson 已提交
4227
              None =>
4228 4229 4230 4231 4232
                t
            },

        _ =>
            t
4233 4234
    };

4235
    let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
B
Brian Anderson 已提交
4236 4237
    let t_norm = mk_t(cx, sty);
    cx.normalized_cache.insert(t, t_norm);
B
Brian Anderson 已提交
4238
    return t_norm;
4239 4240
}

4241
// Returns the repeat count for a repeating vector expression.
4242
pub fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr) -> uint {
4243 4244
    match const_eval::eval_const_expr_partial(tcx, count_expr) {
      Ok(ref const_val) => match *const_val {
4245 4246 4247
        const_eval::const_int(count) => return count as uint,
        const_eval::const_uint(count) => return count as uint,
        const_eval::const_float(count) => {
4248
            tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4249 4250
                              "expected signed or unsigned integer for \
                               repeat count but found float");
4251 4252 4253
            return count as uint;
        }
        const_eval::const_str(_) => {
4254
            tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4255 4256
                              "expected signed or unsigned integer for \
                               repeat count but found string");
4257 4258
            return 0;
        }
4259
        const_eval::const_bool(_) => {
4260
            tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4261 4262
                              "expected signed or unsigned integer for \
                               repeat count but found boolean");
4263 4264
            return 0;
        }
4265 4266
      },
      Err(*) => {
4267
        tcx.sess.span_err(count_expr.span,
S
Seo Sanghyeon 已提交
4268 4269
                          "expected constant integer for repeat count \
                           but found variable");
4270 4271
        return 0;
      }
4272 4273 4274
    }
}

4275
// Determine what purity to check a nested function under
4276 4277 4278 4279
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) {
4280 4281 4282
    // 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
4283
    match child_sigil {
4284 4285
        ast::BorrowedSigil if child.first() == ast::impure_fn => parent,
        _ => child
4286
    }
4287 4288
}

4289 4290
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
4291 4292 4293
// Here, the supertraits are the transitive closure of the supertrait
// relation on the supertraits from each bounded trait's constraint
// list.
4294
pub fn each_bound_trait_and_supertraits(tcx: ctxt,
A
Alex Crichton 已提交
4295 4296 4297
                                        bounds: &ParamBounds,
                                        f: &fn(@TraitRef) -> bool) -> bool {
    for bounds.trait_bounds.each |&bound_trait_ref| {
4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333
        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;
}
4334

4335
pub fn count_traits_and_supertraits(tcx: ctxt,
4336
                                    type_param_defs: &[TypeParameterDef]) -> uint {
4337
    let mut total = 0;
4338 4339
    for type_param_defs.each |type_param_def| {
        for each_bound_trait_and_supertraits(tcx, type_param_def.bounds) |_| {
4340 4341 4342 4343 4344 4345
            total += 1;
        }
    }
    return total;
}

4346
// Given a trait and a type, returns the impl of that type
4347
pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
4348 4349
    match tcx.trait_impls.find(&trait_id) {
        Some(ty_to_impl) => match ty_to_impl.find(&self_ty) {
4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361
            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")
    }
}

4362 4363 4364
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));
4365
    let trait_ref = tcx.intrinsic_traits.get_copy(&ty_visitor_name);
4366
    (trait_ref,
4367
     mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore, ast::m_imm))
4368
}