ty.rs 133.5 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
use core::prelude::*;
12

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

30
use core::ptr::to_unsafe_ptr;
31
use core::to_bytes;
32
use core::hashmap::{HashMap, HashSet};
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
impl to_bytes::IterBytes for creader_cache_key {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
139 140 141
        self.cnum.iter_bytes(lsb0, f) &&
        self.pos.iter_bytes(lsb0, f) &&
        self.len.iter_bytes(lsb0, f)
142 143
    }
}
144

145 146 147
struct intern_key {
    sty: *sty,
}
148

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

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

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

176
pub type opt_region_variance = Option<region_variance>;
177

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

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

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

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

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

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

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

    /// Convert from T to *T
    AutoUnsafe(ast::mutability)
209 210
}

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

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

226
pub struct ProvidedMethodSource {
227 228 229 230
    method_id: ast::def_id,
    impl_id: ast::def_id
}

231 232 233
pub type ctxt = @ctxt_;

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

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

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

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

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

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

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

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

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

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

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

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

325
pub type t_box = &'static t_box_;
326

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

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

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

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

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

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

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

394 395
impl to_bytes::IterBytes for BareFnTy {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
396 397 398
        self.purity.iter_bytes(lsb0, f) &&
        self.abis.iter_bytes(lsb0, f) &&
        self.sig.iter_bytes(lsb0, f)
399 400
    }
}
401

402 403
impl to_bytes::IterBytes for ClosureTy {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
404 405 406 407 408
        self.purity.iter_bytes(lsb0, f) &&
        self.sigil.iter_bytes(lsb0, f) &&
        self.onceness.iter_bytes(lsb0, f) &&
        self.region.iter_bytes(lsb0, f) &&
        self.sig.iter_bytes(lsb0, f)
409 410
    }
}
411

412
#[deriving(Eq, IterBytes)]
413
pub struct param_ty {
414 415
    idx: uint,
    def_id: def_id
416
}
417

418
/// Representation of regions:
419
#[deriving(Eq, IterBytes, Encodable, Decodable)]
420
pub enum Region {
421 422 423 424 425 426 427 428 429
    /// 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 已提交
430
    re_bound(bound_region),
431 432 433 434

    /// 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.
435
    re_free(FreeRegion),
436 437

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

N
Niko Matsakis 已提交
440
    /// Static data that has an "infinite" lifetime. Top in the region lattice.
441 442 443
    re_static,

    /// A region variable.  Should not exist after typeck.
N
Niko Matsakis 已提交
444 445 446 447 448 449 450 451 452 453
    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 已提交
454 455
}

456 457 458 459 460 461 462 463 464
pub impl Region {
    fn is_bound(&self) -> bool {
        match self {
            &re_bound(*) => true,
            _ => false
        }
    }
}

465
#[deriving(Eq, IterBytes, Encodable, Decodable)]
466 467 468 469 470
pub struct FreeRegion {
    scope_id: node_id,
    bound_region: bound_region
}

471
#[deriving(Eq, IterBytes, Encodable, Decodable)]
472
pub enum bound_region {
473
    /// The self region for structs, impls (&T in a type defn or &'self T)
474 475
    br_self,

476 477
    /// An anonymous region parameter for a given fn (&T)
    br_anon(uint),
478

479
    /// Named region parameters for functions (a in &'a T)
480 481
    br_named(ast::ident),

482 483 484
    /// Fresh bound identifiers created during GLB computations.
    br_fresh(uint),

485 486 487 488 489 490 491 492 493
    /**
     * 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. */
494
    br_cap_avoid(ast::node_id, @bound_region),
495 496
}

497
type opt_region = Option<Region>;
498

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

523
mod primitives {
524
    use super::t_box_;
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 564 565 566 567 568 569

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

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

593
    ty_param(param_ty), // type parameter
594 595
    ty_self(def_id), /* special, implicit `self` type parameter;
                      * def_id is the id of the trait */
P
Patrick Walton 已提交
596

597
    ty_infer(InferTy), // something used only during inference/typeck
598 599 600
    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)
601

M
Michael Sullivan 已提交
602
    // "Fake" types, used for trans purposes
P
Patrick Walton 已提交
603
    ty_type, // type_desc*
604
    ty_opaque_box, // used by monomorphizer to represent any @ box
605
    ty_opaque_closure_ptr(Sigil), // ptr to env for &fn, @fn, ~fn
M
Michael Sullivan 已提交
606
    ty_unboxed_vec(mt),
607 608
}

609 610 611 612 613 614
#[deriving(Eq, IterBytes)]
pub struct TraitRef {
    def_id: def_id,
    substs: substs
}

615
#[deriving(Eq)]
616
pub enum IntVarValue {
617 618 619 620
    IntType(ast::int_ty),
    UintType(ast::uint_ty),
}

621
pub enum terr_vstore_kind {
622
    terr_vec, terr_str, terr_fn, terr_trait
623 624
}

625
pub struct expected_found<T> {
626 627
    expected: T,
    found: T
628 629
}

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

664
#[deriving(Eq, IterBytes)]
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
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()
}

684 685 686 687 688 689 690 691 692
pub fn AllBuiltinBounds() -> BuiltinBounds {
    let mut set = EnumSet::empty();
    set.add(BoundCopy);
    set.add(BoundStatic);
    set.add(BoundOwned);
    set.add(BoundConst);
    set
}

693 694 695 696 697 698 699
impl CLike for BuiltinBound {
    pub fn to_uint(&self) -> uint {
        *self as uint
    }
    pub fn from_uint(v: uint) -> BuiltinBound {
        unsafe { cast::transmute(v) }
    }
700 701
}

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

705
#[deriving(Eq)]
706
pub struct IntVid(uint);
707

708
#[deriving(Eq)]
709
pub struct FloatVid(uint);
710

711
#[deriving(Eq, Encodable, Decodable)]
712 713 714
pub struct RegionVid {
    id: uint
}
N
Niko Matsakis 已提交
715

716
#[deriving(Eq)]
717
pub enum InferTy {
718
    TyVar(TyVid),
719 720
    IntVar(IntVid),
    FloatVar(FloatVid)
721 722
}

723 724 725
impl to_bytes::IterBytes for InferTy {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
726 727 728 729 730 731 732 733 734
            TyVar(ref tv) => {
                0u8.iter_bytes(lsb0, f) && tv.iter_bytes(lsb0, f)
            }
            IntVar(ref iv) => {
                1u8.iter_bytes(lsb0, f) && iv.iter_bytes(lsb0, f)
            }
            FloatVar(ref fv) => {
                2u8.iter_bytes(lsb0, f) && fv.iter_bytes(lsb0, f)
            }
735 736 737
        }
    }
}
738

739
#[deriving(Encodable, Decodable)]
740
pub enum InferRegion {
741 742 743 744
    ReVar(RegionVid),
    ReSkolemized(uint, bound_region)
}

745 746 747
impl to_bytes::IterBytes for InferRegion {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
748 749 750 751 752 753
            ReVar(ref rv) => {
                0u8.iter_bytes(lsb0, f) && rv.iter_bytes(lsb0, f)
            }
            ReSkolemized(ref v, _) => {
                1u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f)
            }
754 755 756
        }
    }
}
757

758
impl cmp::Eq for InferRegion {
759
    fn eq(&self, other: &InferRegion) -> bool {
760 761 762 763 764 765 766 767 768 769
        match ((*self), *other) {
            (ReVar(rva), ReVar(rvb)) => {
                rva == rvb
            }
            (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
                rva == rvb
            }
            _ => false
        }
    }
770
    fn ne(&self, other: &InferRegion) -> bool {
771 772
        !((*self) == (*other))
    }
773 774
}

775
pub trait Vid {
776
    fn to_uint(&self) -> uint;
N
Niko Matsakis 已提交
777 778
}

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

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

787
impl Vid for IntVid {
788
    fn to_uint(&self) -> uint { **self }
789 790
}

791
impl ToStr for IntVid {
792
    fn to_str(&self) -> ~str { fmt!("<VI%u>", self.to_uint()) }
793 794
}

795
impl Vid for FloatVid {
796
    fn to_uint(&self) -> uint { **self }
797 798
}

799
impl ToStr for FloatVid {
800
    fn to_str(&self) -> ~str { fmt!("<VF%u>", self.to_uint()) }
801 802
}

803
impl Vid for RegionVid {
804
    fn to_uint(&self) -> uint { self.id }
N
Niko Matsakis 已提交
805 806
}

807
impl ToStr for RegionVid {
808
    fn to_str(&self) -> ~str { fmt!("%?", self.id) }
809
}
810

811
impl ToStr for FnSig {
812
    fn to_str(&self) -> ~str {
813 814
        // grr, without tcx not much we can do.
        return ~"(...)";
815 816 817
    }
}

818
impl ToStr for InferTy {
819
    fn to_str(&self) -> ~str {
820
        match *self {
821 822 823 824
            TyVar(ref v) => v.to_str(),
            IntVar(ref v) => v.to_str(),
            FloatVar(ref v) => v.to_str()
        }
N
Niko Matsakis 已提交
825 826 827
    }
}

828
impl ToStr for IntVarValue {
829
    fn to_str(&self) -> ~str {
830
        match *self {
831 832 833
            IntType(ref v) => v.to_str(),
            UintType(ref v) => v.to_str(),
        }
834 835
    }
}
836

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

843 844 845 846 847
impl to_bytes::IterBytes for IntVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
848

849 850 851 852 853
impl to_bytes::IterBytes for FloatVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
854

855 856 857 858 859
impl to_bytes::IterBytes for RegionVid {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        self.to_uint().iter_bytes(lsb0, f)
    }
}
860

861 862
pub struct TypeParameterDef {
    def_id: ast::def_id,
863
    bounds: @ParamBounds
864 865
}

866 867 868
/// Information about the type/lifetime parametesr associated with an item.
/// Analogous to ast::Generics.
pub struct Generics {
869
    type_param_defs: @~[TypeParameterDef],
870 871 872
    region_param: Option<region_variance>,
}

873 874 875 876 877 878
pub impl Generics {
    fn has_type_params(&self) -> bool {
        !self.type_param_defs.is_empty()
    }
}

879 880 881 882 883 884 885 886 887 888
/// 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
889
pub struct ty_param_bounds_and_ty {
890
    generics: Generics,
891 892
    ty: t
}
893

894 895 896 897 898 899
/// As `ty_param_bounds_and_ty` but for a trait ref.
pub struct TraitDef {
    generics: Generics,
    trait_ref: @ty::TraitRef,
}

900 901 902 903
pub struct ty_param_substs_and_ty {
    substs: ty::substs,
    ty: ty::t
}
904

905
type type_cache = @mut HashMap<ast::def_id, ty_param_bounds_and_ty>;
906

907
type constness_cache = @mut HashMap<ast::def_id, const_eval::constness>;
908

909
pub type node_type_table = @mut HashMap<uint,t>;
910

911
fn mk_rcache() -> creader_cache {
912
    return @mut HashMap::new();
913
}
914

915 916
pub fn new_ty_hash<V:Copy>() -> @mut HashMap<t, V> {
    @mut HashMap::new()
917
}
918

919 920 921 922
pub fn mk_ctxt(s: session::Session,
               dm: resolve::DefMap,
               amap: ast_map::map,
               freevars: freevars::freevar_map,
923
               region_maps: @mut middle::region::RegionMaps,
924
               region_paramd_items: middle::region::region_paramd_items,
S
Seo Sanghyeon 已提交
925
               lang_items: middle::lang_items::LanguageItems)
926
            -> ctxt {
927 928
    @ctxt_ {
        diag: s.diagnostic(),
929
        interner: @mut HashMap::new(),
930
        next_id: @mut primitives::LAST_PRIMITIVE_ID,
931 932 933
        cstore: s.cstore,
        sess: s,
        def_map: dm,
934
        region_maps: region_maps,
935
        region_paramd_items: region_paramd_items,
936
        node_types: @mut HashMap::new(),
937
        node_type_substs: @mut HashMap::new(),
938 939 940
        trait_refs: @mut HashMap::new(),
        trait_defs: @mut HashMap::new(),
        intrinsic_traits: @mut HashMap::new(),
941
        items: amap,
942
        intrinsic_defs: @mut HashMap::new(),
943
        freevars: freevars,
944
        tcache: @mut HashMap::new(),
945
        rcache: mk_rcache(),
946
        ccache: @mut HashMap::new(),
947 948
        short_names_cache: new_ty_hash(),
        needs_unwind_cleanup_cache: new_ty_hash(),
949 950 951
        tc_cache: @mut HashMap::new(),
        ast_ty_to_ty_cache: @mut HashMap::new(),
        enum_var_cache: @mut HashMap::new(),
952 953 954
        methods: @mut HashMap::new(),
        trait_method_def_ids: @mut HashMap::new(),
        trait_methods_cache: @mut HashMap::new(),
955
        ty_param_defs: @mut HashMap::new(),
956
        adjustments: @mut HashMap::new(),
957
        normalized_cache: new_ty_hash(),
L
Luqman Aden 已提交
958
        lang_items: lang_items,
959 960 961 962 963
        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(),
964 965
        trait_impls: @mut HashMap::new(),
        used_unsafe: @mut HashSet::new(),
966
        used_mut_nodes: @mut HashSet::new(),
967
     }
968
}
969

970
// Type constructors
971 972 973

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

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

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

1058
    let t = ~t_box_ {
1059
        sty: st,
1060
        id: *cx.next_id,
1061 1062
        flags: flags,
    };
1063 1064 1065

    let sty_ptr = to_unsafe_ptr(&t.sty);

1066
    let key = intern_key {
1067
        sty: sty_ptr,
1068
    };
1069

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

1072
    *cx.next_id += 1;
1073 1074 1075 1076

    unsafe {
        cast::transmute::<*sty, t>(sty_ptr)
    }
1077 1078
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1169
pub fn mk_estr(cx: ctxt, t: vstore) -> t {
1170 1171 1172
    mk_t(cx, ty_estr(t))
}

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

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

1180
pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
1181 1182
    mk_box(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1183

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

1186
pub fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
1187 1188
    mk_uniq(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1189

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

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

1194
pub fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1195
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_mutbl})
1196
}
1197
pub fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1198
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_imm})
1199 1200
}

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

1205
pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
1206
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_imm})
1207 1208
}

1209
pub fn mk_nil_ptr(cx: ctxt) -> t {
T
Tim Chevalier 已提交
1210
    mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::m_imm})
1211 1212
}

1213
pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
1214 1215 1216
    mk_t(cx, ty_evec(tm, t))
}

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

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

1226
pub fn mk_closure(cx: ctxt, fty: ClosureTy) -> t {
1227 1228 1229
    mk_t(cx, ty_closure(fty))
}

1230
pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
1231 1232 1233 1234
    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 已提交
1235
    let input_args = input_tys.map(|t| *t);
1236 1237 1238
    mk_bare_fn(cx,
               BareFnTy {
                   purity: ast::pure_fn,
1239
                   abis: AbiSet::Rust(),
1240 1241 1242 1243 1244 1245
                   sig: FnSig {
                    bound_lifetime_names: opt_vec::Empty,
                    inputs: input_args,
                    output: output
                   }
                })
1246 1247
}

1248

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

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

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

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

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

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

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

1274
pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
1275
    mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
1276
}
1277

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

1280 1281
pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
    mk_t(cx, ty_opaque_closure_ptr(sigil))
1282 1283
}

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

1286
pub fn walk_ty(ty: t, f: &fn(t)) {
B
Brian Anderson 已提交
1287
    maybe_walk_ty(ty, |t| { f(t); true });
1288 1289
}

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

1319
pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
N
Niko Matsakis 已提交
1320
    mk_t(tcx, fold_sty(sty, foldop))
1321
}
1322

1323
pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
1324
    let args = sig.inputs.map(|arg| fldop(*arg));
1325 1326

    FnSig {
1327
        bound_lifetime_names: copy sig.bound_lifetime_names,
L
Luqman Aden 已提交
1328
        inputs: args,
1329 1330 1331 1332
        output: fldop(sig.output)
    }
}

1333 1334 1335 1336 1337 1338
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}
}

1339 1340
fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
    fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
1341 1342 1343
        substs {self_r: substs.self_r,
                self_ty: substs.self_ty.map(|t| fldop(*t)),
                tps: substs.tps.map(|t| fldop(*t))}
1344 1345
    }

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

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

1399
pub fn walk_regions_and_ty(
1400 1401
    cx: ctxt,
    ty: t,
1402 1403
    walkr: &fn(r: Region),
    walkt: &fn(t: t) -> bool) {
1404 1405 1406 1407

    if (walkt(ty)) {
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1408
            |r| { walkr(r); r },
1409 1410
            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t },
            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t });
1411 1412 1413
    }
}

1414
pub fn fold_regions_and_ty(
1415 1416
    cx: ctxt,
    ty: t,
1417 1418 1419
    fldr: &fn(r: Region) -> Region,
    fldfnt: &fn(t: t) -> t,
    fldt: &fn(t: t) -> t) -> t {
1420 1421

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

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

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

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

1513
pub fn substs_is_noop(substs: &substs) -> bool {
1514 1515 1516
    substs.tps.len() == 0u &&
        substs.self_r.is_none() &&
        substs.self_ty.is_none()
1517 1518
}

1519
pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
1520
    substs.repr(cx)
1521 1522
}

1523 1524 1525 1526
pub fn subst(cx: ctxt,
             substs: &substs,
             typ: t)
          -> t {
1527
    typ.subst(cx, substs)
1528 1529
}

1530
// Type utilities
1531

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

T
Tim Chevalier 已提交
1534 1535 1536 1537 1538 1539 1540
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
}
1541

1542 1543 1544 1545
pub fn type_needs_subst(ty: t) -> bool {
    tbox_has_flag(get(ty), needs_subst)
}

1546 1547 1548 1549 1550
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))
}

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

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

1560 1561 1562 1563 1564 1565 1566
pub fn type_is_self(ty: t) -> bool {
    match get(ty).sty {
        ty_self(*) => true,
        _ => false
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1713
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1714
    type_contents(cx, ty).needs_drop(cx)
1715 1716
}

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

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

fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1735
                              tycache: &mut HashSet<t>,
1736 1737
                              encountered_box: bool) -> bool {

1738
    // Prevent infinite recursion
1739 1740
    if !tycache.insert(ty) {
        return false;
1741
    }
1742

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

        encountered_box = old_encountered_box;
        result
1790 1791
    }

B
Brian Anderson 已提交
1792
    return needs_unwind_cleanup;
1793 1794
}

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

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

1825 1826 1827
    fn intersects(&self, tc: TypeContents) -> bool {
        (self.bits & tc.bits) != 0
    }
1828

1829 1830 1831
    fn is_copy(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::noncopyable(cx))
    }
1832

1833
    fn noncopyable(_cx: ctxt) -> TypeContents {
1834 1835 1836
        TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE +
            TC_EMPTY_ENUM
    }
1837

1838 1839
    fn is_static(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonstatic(cx))
1840
    }
1841

1842
    fn nonstatic(_cx: ctxt) -> TypeContents {
1843 1844
        TC_BORROWED_POINTER
    }
1845

1846 1847 1848
    fn is_owned(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonowned(cx))
    }
1849

1850
    fn nonowned(_cx: ctxt) -> TypeContents {
1851
        TC_MANAGED + TC_BORROWED_POINTER + TC_NON_OWNED
1852
    }
1853

1854 1855 1856 1857
    fn contains_managed(&self) -> bool {
        self.intersects(TC_MANAGED)
    }

1858 1859 1860
    fn is_const(&self, cx: ctxt) -> bool {
        !self.intersects(TypeContents::nonconst(cx))
    }
1861

1862
    fn nonconst(_cx: ctxt) -> TypeContents {
1863 1864
        TC_MUTABLE
    }
1865

1866 1867 1868
    fn moves_by_default(&self, cx: ctxt) -> bool {
        self.intersects(TypeContents::nonimplicitly_copyable(cx))
    }
1869

1870
    fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
1871
        TypeContents::noncopyable(cx) + TC_OWNED_POINTER + TC_OWNED_VEC
1872
    }
1873

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

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

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

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

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

1903
/// Constant for a type containing nothing of interest.
1904
static TC_NONE: TypeContents =             TypeContents{bits: 0b0000_0000_0000};
1905

1906
/// Contains a borrowed value with a lifetime other than static
1907
static TC_BORROWED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0001};
1908

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

1912
/// Contains an owned vector ~[] or owned string ~str
1913
static TC_OWNED_VEC: TypeContents =        TypeContents{bits: 0b0000_0000_0100};
1914

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

1918
/// Type with a destructor
1919
static TC_DTOR: TypeContents =             TypeContents{bits: 0b0000_0001_0000};
1920

1921
/// Contains a managed value
1922
static TC_MANAGED: TypeContents =          TypeContents{bits: 0b0000_0010_0000};
1923

1924
/// &mut with any region
1925
static TC_BORROWED_MUT: TypeContents =     TypeContents{bits: 0b0000_0100_0000};
1926

1927
/// Mutable content, whether owned or by ref
1928
static TC_MUTABLE: TypeContents =          TypeContents{bits: 0b0000_1000_0000};
1929

1930 1931
/// One-shot closure
static TC_ONCE_CLOSURE: TypeContents =     TypeContents{bits: 0b0001_0000_0000};
1932

1933
/// An enum with no variants.
1934 1935 1936 1937
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};
1938

1939
/// All possible contents.
1940
static TC_ALL: TypeContents =              TypeContents{bits: 0b0111_1111_1111};
1941

1942 1943
pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_copy(cx)
1944 1945
}

1946 1947
pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_static(cx)
1948 1949
}

1950 1951 1952
pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_owned(cx)
}
1953

1954 1955 1956
pub fn type_is_const(cx: ctxt, t: ty::t) -> bool {
    type_contents(cx, t).is_const(cx)
}
1957

1958 1959 1960 1961 1962
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 => {}
1963 1964
    }

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

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

        let _i = indenter();

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

2015
            ty_estr(vstore_uniq) => {
2016
                TC_OWNED_VEC
2017
            }
M
Marijn Haverbeke 已提交
2018

2019 2020 2021
            ty_closure(ref c) => {
                closure_contents(c)
            }
2022

2023 2024 2025
            ty_box(mt) => {
                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
            }
2026

2027
            ty_trait(_, _, UniqTraitStore, _) => {
2028 2029
                TC_OWNED_CLOSURE
            }
2030

2031 2032 2033 2034 2035
            ty_trait(_, _, BoxTraitStore, mutbl) => {
                match mutbl {
                    ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
                    _ => TC_MANAGED
                }
2036
            }
2037

2038 2039
            ty_trait(_, _, RegionTraitStore(r), mutbl) => {
                borrowed_contents(r, mutbl)
2040
            }
2041

2042 2043 2044 2045
            ty_rptr(r, mt) => {
                borrowed_contents(r, mt.mutbl) +
                    nonowned(tc_mt(cx, mt, cache))
            }
2046

2047 2048 2049
            ty_uniq(mt) => {
                TC_OWNED_POINTER + tc_mt(cx, mt, cache)
            }
2050

2051
            ty_evec(mt, vstore_uniq) => {
2052
                TC_OWNED_VEC + tc_mt(cx, mt, cache)
2053
            }
2054

2055 2056 2057
            ty_evec(mt, vstore_box) => {
                TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
            }
2058

2059 2060 2061 2062
            ty_evec(mt, vstore_slice(r)) => {
                borrowed_contents(r, mt.mutbl) +
                    nonowned(tc_mt(cx, mt, cache))
            }
2063

2064 2065 2066
            ty_evec(mt, vstore_fixed(_)) => {
                tc_mt(cx, mt, cache)
            }
2067

2068 2069 2070
            ty_estr(vstore_box) => {
                TC_MANAGED
            }
2071

2072 2073 2074
            ty_estr(vstore_slice(r)) => {
                borrowed_contents(r, m_imm)
            }
2075

2076 2077 2078
            ty_estr(vstore_fixed(_)) => {
                TC_NONE
            }
2079

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

2091 2092 2093
            ty_tup(ref tys) => {
                tys.foldl(TC_NONE, |tc, ty| *tc + tc_ty(cx, *ty, cache))
            }
2094

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

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

2120 2121
                type_param_def_to_contents(
                    cx, cx.ty_param_defs.get(&p.def_id.node))
2122
            }
2123

2124
            ty_self(_) => {
2125 2126 2127 2128 2129 2130 2131
                // 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
            }
2132

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

2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150
            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,

2151
            ty_err => {
2152
                cx.sess.bug("Asked to compute contents of fictitious type");
2153
            }
2154 2155 2156 2157 2158
        };

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

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

D
Daniel Micay 已提交
2168 2169 2170 2171 2172 2173 2174 2175 2176 2177
    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
    }

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

2194 2195 2196 2197 2198 2199 2200 2201
    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.
         */
2202

2203 2204
        let mask = TC_MUTABLE.bits | TC_BORROWED_POINTER.bits;
        TypeContents {bits: pointee.bits & mask}
2205 2206
    }

2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220
    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
    }

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

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

2238 2239
        debug!("result = %s", tc.to_str());
        return tc;
2240
    }
2241 2242
}

2243 2244 2245 2246
pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool {
    type_contents(cx, ty).moves_by_default(cx)
}

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

        let r = {
2256
            get(r_ty).sty == get(ty).sty ||
2257 2258 2259
                subtypes_require(cx, seen, r_ty, ty)
        };

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

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

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

2300
          ty_ptr(*) => {
2301 2302 2303
            false           // unsafe ptrs can always be NULL
          }

2304
          ty_trait(_, _, _, _) => {
2305 2306 2307
            false
          }

2308
          ty_struct(ref did, _) if vec::contains(*seen, did) => {
2309 2310 2311
            false
          }

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

2320 2321
          ty_tup(ref ts) => {
            ts.any(|t| type_requires(cx, seen, r_ty, *t))
2322 2323
          }

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

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

P
Paul Stansifer 已提交
2342
        debug!("subtypes_require(%s, %s)? %b",
2343 2344
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2345
               r);
2346

B
Brian Anderson 已提交
2347
        return r;
2348 2349
    }

2350
    let seen = @mut ~[];
2351 2352 2353
    !subtypes_require(cx, seen, r_ty, r_ty)
}

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

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

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

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

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

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

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

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

S
Seo Sanghyeon 已提交
2436 2437 2438 2439 2440 2441 2442 2443
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
    }
}

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

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

B
Brian Anderson 已提交
2485
      ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2486 2487 2488
        result = false;
      }

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

B
Brian Anderson 已提交
2494
    return result;
P
Patrick Walton 已提交
2495 2496
}

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

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

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

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

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

2542
      ty_ptr(mt) if explicit => {
B
Brian Anderson 已提交
2543
        Some(mt)
2544 2545
      }

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

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

B
Brian Anderson 已提交
2566
      _ => None
2567 2568 2569
    }
}

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

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

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

2593 2594 2595 2596 2597 2598 2599 2600 2601 2602
/**
 * 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)
    }
}
2603

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

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

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

2642 2643 2644
impl to_bytes::IterBytes for vstore {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
2645 2646 2647 2648 2649
            vstore_fixed(ref u) => {
                0u8.iter_bytes(lsb0, f) && u.iter_bytes(lsb0, f)
            }
            vstore_uniq => 1u8.iter_bytes(lsb0, f),
            vstore_box => 2u8.iter_bytes(lsb0, f),
2650

2651 2652 2653
            vstore_slice(ref r) => {
                3u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f)
            }
2654 2655 2656 2657 2658 2659
        }
    }
}

impl to_bytes::IterBytes for substs {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
2660 2661 2662
        self.self_r.iter_bytes(lsb0, f) &&
        self.self_ty.iter_bytes(lsb0, f) &&
        self.tps.iter_bytes(lsb0, f)
2663 2664
    }
}
2665

2666 2667
impl to_bytes::IterBytes for mt {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
2668
        self.ty.iter_bytes(lsb0, f) && self.mutbl.iter_bytes(lsb0, f)
2669 2670
    }
}
2671

2672 2673
impl to_bytes::IterBytes for field {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
2674
        self.ident.iter_bytes(lsb0, f) && self.mt.iter_bytes(lsb0, f)
2675 2676
    }
}
2677

2678 2679
impl to_bytes::IterBytes for FnSig {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
2680
        self.inputs.iter_bytes(lsb0, f) && self.output.iter_bytes(lsb0, f)
2681 2682
    }
}
2683

2684 2685 2686
impl to_bytes::IterBytes for sty {
    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
        match *self {
2687 2688
            ty_nil => 0u8.iter_bytes(lsb0, f),
            ty_bool => 1u8.iter_bytes(lsb0, f),
2689

2690
            ty_int(ref t) => 2u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
2691

2692
            ty_uint(ref t) => 3u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
2693

2694
            ty_float(ref t) => 4u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
2695

2696
            ty_estr(ref v) => 5u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f),
2697

2698 2699 2700 2701 2702
            ty_enum(ref did, ref substs) => {
                6u8.iter_bytes(lsb0, f) &&
                did.iter_bytes(lsb0, f) &&
                substs.iter_bytes(lsb0, f)
            }
2703

2704
            ty_box(ref mt) => 7u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
2705

2706 2707 2708 2709 2710
            ty_evec(ref mt, ref v) => {
                8u8.iter_bytes(lsb0, f) &&
                mt.iter_bytes(lsb0, f) &&
                v.iter_bytes(lsb0, f)
            }
2711

2712
            ty_unboxed_vec(ref mt) => 9u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
2713

2714
            ty_tup(ref ts) => 10u8.iter_bytes(lsb0, f) && ts.iter_bytes(lsb0, f),
2715

2716
            ty_bare_fn(ref ft) => 12u8.iter_bytes(lsb0, f) && ft.iter_bytes(lsb0, f),
2717

2718
            ty_self(ref did) => 13u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f),
2719

2720
            ty_infer(ref v) => 14u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f),
2721

2722
            ty_param(ref p) => 15u8.iter_bytes(lsb0, f) && p.iter_bytes(lsb0, f),
2723

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

2727
            ty_ptr(ref mt) => 18u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
2728

2729
            ty_uniq(ref mt) => 19u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
2730

2731 2732 2733 2734 2735 2736 2737
            ty_trait(ref did, ref substs, ref v, ref mutbl) => {
                20u8.iter_bytes(lsb0, f) &&
                did.iter_bytes(lsb0, f) &&
                substs.iter_bytes(lsb0, f) &&
                v.iter_bytes(lsb0, f) &&
                mutbl.iter_bytes(lsb0, f)
            }
2738

2739
            ty_opaque_closure_ptr(ref ck) => 21u8.iter_bytes(lsb0, f) && ck.iter_bytes(lsb0, f),
2740

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

2743 2744 2745
            ty_struct(ref did, ref substs) => {
                23u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f) && substs.iter_bytes(lsb0, f)
            }
2746

2747 2748 2749
            ty_rptr(ref r, ref mt) => {
                24u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f)
            }
2750

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

2753
            ty_closure(ref ct) => 26u8.iter_bytes(lsb0, f) && ct.iter_bytes(lsb0, f),
2754 2755 2756
        }
    }
}
2757

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

2920

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        ast::expr_cast(*) => {
D
Daniel Micay 已提交
3228 3229
            match tcx.node_types.find(&(expr.id as uint)) {
                Some(&t) => {
3230 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
                    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(*) |
3260
        ast::expr_inline_asm(*) |
3261 3262 3263 3264 3265 3266 3267 3268
        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(*) |
3269
        ast::expr_vstore(_, ast::expr_vstore_box) |
3270
        ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3271
        ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3272 3273 3274
            RvalueDatumExpr
        }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3531
pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
3532 3533
    match *err {
        terr_regions_does_not_outlive(subregion, superregion) => {
3534 3535 3536
            note_and_explain_region(cx, "", subregion, "...");
            note_and_explain_region(cx, "...does not necessarily outlive ",
                                    superregion, "");
3537 3538
        }
        terr_regions_not_same(region1, region2) => {
3539 3540 3541
            note_and_explain_region(cx, "", region1, "...");
            note_and_explain_region(cx, "...is not the same lifetime as ",
                                    region2, "");
3542 3543
        }
        terr_regions_no_overlap(region1, region2) => {
3544 3545 3546
            note_and_explain_region(cx, "", region1, "...");
            note_and_explain_region(cx, "...does not overlap ",
                                    region2, "");
3547
        }
3548 3549
        terr_regions_insufficiently_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
3550 3551
                                    "concrete lifetime that was found is ",
                                    conc_region, "");
3552 3553 3554
        }
        terr_regions_overly_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
3555 3556
                                    "expected concrete lifetime is ",
                                    conc_region, "");
3557
        }
3558 3559 3560 3561
        _ => {}
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

3700 3701 3702 3703 3704 3705
/// 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.
3706
        cx.sess.unimpl("constructor ID of cross-crate tuple structs");
3707 3708
    }

3709
    match cx.items.find(&struct_did.node) {
A
Alex Crichton 已提交
3710
        Some(&ast_map::node_item(item, _)) => {
3711
            match item.node {
3712
                ast::item_struct(struct_def, _) => {
3713 3714 3715
                    struct_def.ctor_id.map(|ctor_id|
                        ast_util::local_def(*ctor_id))
                }
3716
                _ => cx.sess.bug("called struct_ctor_id on non-struct")
3717 3718
            }
        }
3719
        _ => cx.sess.bug("called struct_ctor_id on non-struct")
3720 3721 3722
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3910

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

3926

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _ =>
            t
4232 4233
    };

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

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

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

4288 4289
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
4290 4291 4292
// Here, the supertraits are the transitive closure of the supertrait
// relation on the supertraits from each bounded trait's constraint
// list.
4293
pub fn each_bound_trait_and_supertraits(tcx: ctxt,
A
Alex Crichton 已提交
4294 4295 4296
                                        bounds: &ParamBounds,
                                        f: &fn(@TraitRef) -> bool) -> bool {
    for bounds.trait_bounds.each |&bound_trait_ref| {
4297 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
        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;
}
4333

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

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

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