ty.rs 144.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// 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.

N
Niko Matsakis 已提交
11 12
#[warn(deprecated_pattern)];

13 14
use core::prelude::*;

P
Patrick Walton 已提交
15 16
use driver::session;
use metadata::csearch;
17 18 19
use metadata;
use middle::const_eval;
use middle::freevars;
P
Patrick Walton 已提交
20
use middle::lint::{get_lint_level, allow};
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
use middle::lint;
use middle::resolve::{Impl, MethodInfo};
use middle::resolve;
use middle::ty;
use middle::typeck;
use middle;
use session::Session;
use util::ppaux::{note_and_explain_region, bound_region_to_str};
use util::ppaux::{region_to_str, explain_region, vstore_to_str};
use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};

use core::cast;
use core::cmp;
use core::dvec::DVec;
use core::dvec;
use core::ops;
use core::option;
38
use core::ptr::to_unsafe_ptr;
39 40 41 42 43 44
use core::result::Result;
use core::result;
use core::to_bytes;
use core::uint;
use core::vec;
use std::map::HashMap;
45
use std::{map, oldsmallintmap};
P
Patrick Walton 已提交
46
use syntax::ast::*;
47 48 49
use syntax::ast_util::{is_local, local_def};
use syntax::ast_util;
use syntax::codemap::span;
50
use syntax::print::pprust;
51 52
use syntax::{ast, ast_map};
use syntax;
53

54
// Data types
55

56 57
// Note: after typeck, you should use resolved_mode() to convert this mode
// into an rmode, which will take into account the results of mode inference.
58
#[deriving_eq]
59
pub struct arg {
60 61 62
    mode: ast::mode,
    ty: t
}
63

64
#[deriving_eq]
65
pub struct field {
66 67 68
    ident: ast::ident,
    mt: mt
}
69

70
pub type param_bounds = @~[param_bound];
71

72 73 74 75 76 77 78 79 80 81
pub type method = {
    ident: ast::ident,
    tps: @~[param_bounds],
    fty: FnTy,
    self_ty: ast::self_ty_,
    vis: ast::visibility,
    def_id: ast::def_id
};

pub struct mt {
82 83 84
    ty: t,
    mutbl: ast::mutability,
}
85

86 87
#[auto_encode]
#[auto_decode]
88
pub enum vstore {
89 90 91
    vstore_fixed(uint),
    vstore_uniq,
    vstore_box,
92
    vstore_slice(Region)
93 94
}

95
pub struct field_ty {
T
Tim Chevalier 已提交
96
  ident: ident,
T
Tim Chevalier 已提交
97
  id: def_id,
98
  vis: ast::visibility,
99 100
  mutability: ast::struct_mutability,
}
T
Tim Chevalier 已提交
101

102 103
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
104
#[deriving_eq]
105
pub struct creader_cache_key {
106 107 108
    cnum: int,
    pos: uint,
    len: uint
109
}
110

111 112
type creader_cache = HashMap<creader_cache_key, t>;

113 114 115 116 117
impl creader_cache_key : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f);
    }
}
118

119 120 121 122
struct intern_key {
    sty: *sty,
    o_def_id: Option<ast::def_id>
}
123

124 125 126
// NB: Do not replace this with #[deriving_eq]. The automatically-derived
// implementation will not recurse through sty and you will get stack
// exhaustion.
127
impl intern_key : cmp::Eq {
128
    pure fn eq(&self, other: &intern_key) -> bool {
129 130 131
        unsafe {
            *self.sty == *other.sty && self.o_def_id == other.o_def_id
        }
132
    }
133 134 135
    pure fn ne(&self, other: &intern_key) -> bool {
        !self.eq(other)
    }
136
}
137

138 139
impl intern_key : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
140 141 142
        unsafe {
            to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f);
        }
143 144
    }
}
145

146
pub enum ast_ty_to_ty_cache_entry {
147
    atttce_unresolved,  /* not resolved yet */
148
    atttce_resolved(t)  /* resolved to a type, irrespective of region */
149 150
}

151
pub type opt_region_variance = Option<region_variance>;
152

153 154
#[auto_encode]
#[auto_decode]
155
pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant }
156

157
impl region_variance : cmp::Eq {
158 159 160 161 162 163 164 165 166 167 168
    pure fn eq(&self, other: &region_variance) -> bool {
        match ((*self), (*other)) {
            (rv_covariant, rv_covariant) => true,
            (rv_invariant, rv_invariant) => true,
            (rv_contravariant, rv_contravariant) => true,
            (rv_covariant, _) => false,
            (rv_invariant, _) => false,
            (rv_contravariant, _) => false
        }
    }
    pure fn ne(&self, other: &region_variance) -> bool { !(*self).eq(other) }
169
}
170

171 172
#[auto_encode]
#[auto_decode]
173
pub struct AutoAdjustment {
174 175
    autoderefs: uint,
    autoref: Option<AutoRef>
176
}
177

178 179
#[auto_encode]
#[auto_decode]
180
pub struct AutoRef {
181
    kind: AutoRefKind,
182
    region: Region,
183
    mutbl: ast::mutability
184
}
185

186 187
#[auto_encode]
#[auto_decode]
188
pub enum AutoRefKind {
189 190 191
    /// Convert from T to &T
    AutoPtr,

192
    /// Convert from @[]/~[] to &[] (or str)
193
    AutoBorrowVec,
194

195 196 197
    /// Convert from @[]/~[] to &&[] (or str)
    AutoBorrowVecRef,

198 199
    /// Convert from @fn()/~fn() to &fn()
    AutoBorrowFn,
200 201
}

202 203 204 205 206 207
// 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.
208
pub type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;
209 210 211

// Stores the method info and definition ID of the associated trait method for
// each instantiation of each provided method.
212
pub struct ProvidedMethodInfo {
213 214 215 216
    method_info: @MethodInfo,
    trait_method_def_id: def_id
}

217
pub struct ProvidedMethodSource {
218 219 220 221
    method_id: ast::def_id,
    impl_id: ast::def_id
}

222
pub struct InstantiatedTraitRef {
223 224 225 226
    def_id: ast::def_id,
    tpt: ty_param_substs_and_ty
}

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
pub type ctxt = @ctxt_;

struct ctxt_ {
    diag: syntax::diagnostic::span_handler,
    interner: HashMap<intern_key, t_box>,
    mut next_id: uint,
    vecs_implicitly_copyable: bool,
    legacy_modes: bool,
    legacy_records: bool,
    cstore: metadata::cstore::CStore,
    sess: session::Session,
    def_map: resolve::DefMap,

    region_map: middle::region::region_map,
    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.
    node_type_substs: HashMap<node_id, ~[t]>,

    items: ast_map::map,
    intrinsic_defs: HashMap<ast::ident, (ast::def_id, t)>,
    freevars: freevars::freevar_map,
    tcache: type_cache,
    rcache: creader_cache,
    ccache: constness_cache,
    short_names_cache: HashMap<t, @~str>,
    needs_drop_cache: HashMap<t, bool>,
    needs_unwind_cleanup_cache: HashMap<t, bool>,
    kind_cache: HashMap<t, Kind>,
    ast_ty_to_ty_cache: HashMap<@ast::Ty, ast_ty_to_ty_cache_entry>,
    enum_var_cache: HashMap<def_id, @~[VariantInfo]>,
    trait_method_cache: HashMap<def_id, @~[method]>,
    ty_param_bounds: HashMap<ast::node_id, param_bounds>,
    inferred_modes: HashMap<ast::node_id, ast::mode>,
    adjustments: HashMap<ast::node_id, @AutoAdjustment>,
    normalized_cache: HashMap<t, t>,
    lang_items: middle::lang_items::LanguageItems,
    legacy_boxed_traits: HashMap<node_id, ()>,
    // 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,
    provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
    supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,

    // 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.
    destructor_for_type: HashMap<ast::def_id, ast::def_id>,

    // A method will be in this list if and only if it is a destructor.
    destructors: HashMap<ast::def_id, ()>,

    // Maps a trait onto a mapping from self-ty to impl
    trait_impls: HashMap<ast::def_id, HashMap<t, @Impl>>
}
292

293 294 295 296 297
enum tbox_flag {
    has_params = 1,
    has_self = 2,
    needs_infer = 4,
    has_regions = 8,
298
    has_ty_err = 16,
299 300 301 302 303 304

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

305
type t_box = @{sty: sty,
306
               id: uint,
307
               flags: uint,
B
Brian Anderson 已提交
308
               o_def_id: Option<ast::def_id>};
309

310 311 312 313 314 315
// 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 {}
316
pub type t = *t_opaque;
317

318
pub pure fn get(t: t) -> t_box {
319 320 321 322 323 324
    unsafe {
        let t2 = cast::reinterpret_cast::<t, t_box>(&t);
        let t3 = t2;
        cast::forget(move t2);
        t3
    }
325 326
}

327
pub pure fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
328 329
    (tb.flags & (flag as uint)) != 0u
}
P
Patrick Walton 已提交
330 331 332
pub pure fn type_has_params(t: t) -> bool {
    tbox_has_flag(get(t), has_params)
}
333 334 335 336 337 338 339 340 341 342 343 344
pub pure fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
pub pure fn type_needs_infer(t: t) -> bool {
    tbox_has_flag(get(t), needs_infer)
}
pub pure fn type_has_regions(t: t) -> bool {
    tbox_has_flag(get(t), has_regions)
}
pub pure fn type_contains_err(t: t) -> bool {
    tbox_has_flag(get(t), has_ty_err)
}
pub pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
pub pure fn type_id(t: t) -> uint { get(t).id }
345

346 347 348 349 350
/**
 * Meta information about a closure.
 *
 * - `purity` is the function's effect (pure, impure, unsafe).
 * - `proto` is the protocol (fn@, fn~, etc).
351 352
 * - `onceness` indicates whether the function can be called one time or many
 *   times.
353
 * - `region` is the region bound on the function's upvars (often &static).
354
 * - `bounds` is the parameter bounds on the function's upvars. */
355
#[deriving_eq]
356
pub struct FnMeta {
357
    purity: ast::purity,
358
    proto: ast::Proto,
359
    onceness: ast::Onceness,
360
    region: Region,
361
    bounds: @~[param_bound]
362 363 364 365 366 367 368 369
}

/**
 * Signature of a function type, which I have arbitrarily
 * decided to use to refer to the input/output types.
 *
 * - `inputs` is the list of arguments and their modes.
 * - `output` is the return type. */
370
#[deriving_eq]
371
pub struct FnSig {
372 373
    inputs: ~[arg],
    output: t
374 375 376 377 378 379 380
}

/**
 * Function type: combines the meta information and the
 * type signature.  This particular type is parameterized
 * by the meta information because, in some cases, the
 * meta information is inferred. */
381
#[deriving_eq]
382
pub struct FnTyBase<M> {
383 384 385 386 387 388 389 390
    meta: M,        // Either FnMeta or FnVid
    sig: FnSig      // Types of arguments/return type
}

impl<M: to_bytes::IterBytes> FnTyBase<M> : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_2(&self.meta, &self.sig, lsb0, f)
    }
391 392
}

393
pub type FnTy = FnTyBase<FnMeta>;
394

395
#[deriving_eq]
396
pub struct param_ty {
397 398
    idx: uint,
    def_id: def_id
399
}
400

401 402 403 404 405
impl param_ty : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_2(&self.idx, &self.def_id, lsb0, f)
    }
}
406 407


408
/// Representation of regions:
409 410
#[auto_encode]
#[auto_decode]
411
pub enum Region {
412 413 414 415 416 417 418 419 420
    /// 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 已提交
421
    re_bound(bound_region),
422 423 424 425

    /// 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.
N
Niko Matsakis 已提交
426
    re_free(node_id, bound_region),
427 428

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

    /// Static data that has an "infinite" lifetime.
    re_static,

    /// A region variable.  Should not exist after typeck.
435
    re_infer(InferRegion)
N
Niko Matsakis 已提交
436 437
}

438 439
#[auto_encode]
#[auto_decode]
440
pub enum bound_region {
441
    /// The self region for structs, impls (&T in a type defn or &self/T)
442 443
    br_self,

444 445
    /// An anonymous region parameter for a given fn (&T)
    br_anon(uint),
446 447 448 449

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

450 451 452
    /// Fresh bound identifiers created during GLB computations.
    br_fresh(uint),

453 454 455 456 457 458 459 460 461
    /**
     * 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. */
462
    br_cap_avoid(ast::node_id, @bound_region),
463 464
}

465
type opt_region = Option<Region>;
466

467 468 469 470 471 472 473 474 475
/**
 * 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
476
 *   types (enums, structs) declared as having a region parameter.  `self_r`
477 478 479 480 481 482 483
 *   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. */
484
#[deriving_eq]
485
pub struct substs {
486
    self_r: opt_region,
B
Brian Anderson 已提交
487
    self_ty: Option<ty::t>,
488
    tps: ~[t]
489
}
490

491
// NB: If you change this, you'll probably want to change the corresponding
492
// AST structure in libsyntax/ast.rs as well.
493
pub enum sty {
P
Patrick Walton 已提交
494 495 496 497 498 499
    ty_nil,
    ty_bot,
    ty_bool,
    ty_int(ast::int_ty),
    ty_uint(ast::uint_ty),
    ty_float(ast::float_ty),
500
    ty_estr(vstore),
501
    ty_enum(def_id, substs),
P
Patrick Walton 已提交
502 503
    ty_box(mt),
    ty_uniq(mt),
504
    ty_evec(mt, vstore),
P
Patrick Walton 已提交
505
    ty_ptr(mt),
506
    ty_rptr(Region, mt),
507
    ty_rec(~[field]),
508
    ty_fn(FnTy),
509
    ty_trait(def_id, substs, vstore),
510
    ty_struct(def_id, substs),
511
    ty_tup(~[t]),
P
Patrick Walton 已提交
512

513
    ty_param(param_ty), // type parameter
514
    ty_self, // special, implicit `self` type parameter
P
Patrick Walton 已提交
515

516
    ty_infer(InferTy), // something used only during inference/typeck
517 518 519
    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)
520

M
Michael Sullivan 已提交
521
    // "Fake" types, used for trans purposes
P
Patrick Walton 已提交
522
    ty_type, // type_desc*
523
    ty_opaque_box, // used by monomorphizer to represent any @ box
524
    ty_opaque_closure_ptr(ast::Proto), // ptr to env for fn, fn@, fn~
M
Michael Sullivan 已提交
525
    ty_unboxed_vec(mt),
526 527
}

528
#[deriving_eq]
529
pub enum IntVarValue {
530 531 532 533
    IntType(ast::int_ty),
    UintType(ast::uint_ty),
}

534
pub enum terr_vstore_kind {
535
    terr_vec, terr_str, terr_fn, terr_trait
536 537
}

538
pub struct expected_found<T> {
539 540
    expected: T,
    found: T
541 542
}

543
// Data structures used in type unification
544
pub enum type_err {
P
Patrick Walton 已提交
545
    terr_mismatch,
546
    terr_purity_mismatch(expected_found<purity>),
547
    terr_onceness_mismatch(expected_found<Onceness>),
548
    terr_mutability,
549
    terr_proto_mismatch(expected_found<ast::Proto>),
P
Patrick Walton 已提交
550
    terr_box_mutability,
M
Marijn Haverbeke 已提交
551
    terr_ptr_mutability,
552
    terr_ref_mutability,
P
Patrick Walton 已提交
553
    terr_vec_mutability,
554 555 556
    terr_tuple_size(expected_found<uint>),
    terr_ty_param_size(expected_found<uint>),
    terr_record_size(expected_found<uint>),
P
Patrick Walton 已提交
557
    terr_record_mutability,
558
    terr_record_fields(expected_found<ident>),
P
Patrick Walton 已提交
559
    terr_arg_count,
560
    terr_mode_mismatch(expected_found<mode>),
561 562 563
    terr_regions_does_not_outlive(Region, Region),
    terr_regions_not_same(Region, Region),
    terr_regions_no_overlap(Region, Region),
564 565
    terr_regions_insufficiently_polymorphic(bound_region, Region),
    terr_regions_overly_polymorphic(bound_region, Region),
566
    terr_vstores_differ(terr_vstore_kind, expected_found<vstore>),
B
Brian Anderson 已提交
567
    terr_in_field(@type_err, ast::ident),
568
    terr_sorts(expected_found<t>),
569
    terr_self_substs,
570
    terr_integer_as_char,
571 572
    terr_int_mismatch(expected_found<IntVarValue>),
    terr_float_mismatch(expected_found<ast::float_ty>)
573 574
}

575
pub enum param_bound {
P
Patrick Walton 已提交
576
    bound_copy,
B
Brian Anderson 已提交
577
    bound_durable,
B
Brian Anderson 已提交
578
    bound_owned,
579
    bound_const,
580
    bound_trait(t),
581 582
}

583
#[deriving_eq]
584
pub enum TyVid = uint;
585 586

#[deriving_eq]
587
pub enum IntVid = uint;
588 589

#[deriving_eq]
590
pub enum FloatVid = uint;
591 592

#[deriving_eq]
593 594
#[auto_encode]
#[auto_decode]
595
pub enum RegionVid = uint;
N
Niko Matsakis 已提交
596

597
#[deriving_eq]
598
pub enum InferTy {
599
    TyVar(TyVid),
600 601
    IntVar(IntVid),
    FloatVar(FloatVid)
602 603
}

604 605 606 607 608
impl InferTy : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
          IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f),
609
          FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f),
610 611 612
        }
    }
}
613

614 615
#[auto_encode]
#[auto_decode]
616
pub enum InferRegion {
617 618 619 620
    ReVar(RegionVid),
    ReSkolemized(uint, bound_region)
}

621 622 623 624 625 626 627 628
impl InferRegion : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
            ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f),
            ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f)
        }
    }
}
629 630

impl InferRegion : cmp::Eq {
631 632 633 634 635 636 637 638 639 640 641 642 643 644
    pure fn eq(&self, other: &InferRegion) -> bool {
        match ((*self), *other) {
            (ReVar(rva), ReVar(rvb)) => {
                rva == rvb
            }
            (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
                rva == rvb
            }
            _ => false
        }
    }
    pure fn ne(&self, other: &InferRegion) -> bool {
        !((*self) == (*other))
    }
645 646
}

647 648 649 650
impl param_bound : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          bound_copy => 0u8.iter_bytes(lsb0, f),
B
Brian Anderson 已提交
651
          bound_durable => 1u8.iter_bytes(lsb0, f),
B
Brian Anderson 已提交
652
          bound_owned => 2u8.iter_bytes(lsb0, f),
653 654 655 656 657 658
          bound_const => 3u8.iter_bytes(lsb0, f),
          bound_trait(ref t) =>
          to_bytes::iter_bytes_2(&4u8, t, lsb0, f)
        }
    }
}
659

660
pub trait Vid {
661
    pure fn to_uint() -> uint;
N
Niko Matsakis 已提交
662 663
}

664
pub impl TyVid: Vid {
665
    pure fn to_uint() -> uint { *self }
666 667
}

668
pub impl TyVid: ToStr {
P
Paul Stansifer 已提交
669
    pure fn to_str() -> ~str { fmt!("<V%u>", self.to_uint()) }
N
Niko Matsakis 已提交
670 671
}

672
pub impl IntVid: Vid {
673
    pure fn to_uint() -> uint { *self }
674 675
}

676
pub impl IntVid: ToStr {
P
Paul Stansifer 已提交
677
    pure fn to_str() -> ~str { fmt!("<VI%u>", self.to_uint()) }
678 679
}

680
pub impl FloatVid: Vid {
681
    pure fn to_uint() -> uint { *self }
682 683
}

684
pub impl FloatVid: ToStr {
685 686 687
    pure fn to_str() -> ~str { fmt!("<VF%u>", self.to_uint()) }
}

688
pub impl RegionVid: Vid {
689
    pure fn to_uint() -> uint { *self }
N
Niko Matsakis 已提交
690 691
}

692
pub impl RegionVid: ToStr {
693 694
    pure fn to_str() -> ~str { fmt!("%?", self) }
}
695

696
pub impl FnSig : ToStr {
697
    pure fn to_str() -> ~str {
698 699
        // grr, without tcx not much we can do.
        return ~"(...)";
700 701 702
    }
}

703
pub impl InferTy: ToStr {
704
    pure fn to_str() -> ~str {
705 706 707 708 709
        match self {
            TyVar(ref v) => v.to_str(),
            IntVar(ref v) => v.to_str(),
            FloatVar(ref v) => v.to_str()
        }
N
Niko Matsakis 已提交
710 711 712
    }
}

713
pub impl IntVarValue : ToStr {
714 715 716 717 718
    pure fn to_str() -> ~str {
        match self {
            IntType(ref v) => v.to_str(),
            UintType(ref v) => v.to_str(),
        }
719 720
    }
}
721

722
pub impl TyVid : to_bytes::IterBytes {
723
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
724
        self.to_uint().iter_bytes(lsb0, f)
725 726
    }
}
727

728
pub impl IntVid : to_bytes::IterBytes {
729
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
730
        self.to_uint().iter_bytes(lsb0, f)
731 732
    }
}
733

734
pub impl FloatVid : to_bytes::IterBytes {
735
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
736
        self.to_uint().iter_bytes(lsb0, f)
737 738
    }
}
739

740
pub impl RegionVid : to_bytes::IterBytes {
741
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
742
        self.to_uint().iter_bytes(lsb0, f)
743 744
    }
}
745

746
pub fn param_bounds_to_kind(bounds: param_bounds) -> Kind {
747
    let mut kind = kind_noncopyable();
748
    for vec::each(*bounds) |bound| {
749
        match *bound {
B
Brian Anderson 已提交
750
          bound_copy => {
751
            kind = raise_kind(kind, kind_implicitly_copyable());
752
          }
B
Brian Anderson 已提交
753 754
          bound_durable => {
            kind = raise_kind(kind, kind_durable());
755
          }
B
Brian Anderson 已提交
756 757
          bound_owned => {
            kind = raise_kind(kind, kind_owned_only() | kind_durable());
758
          }
B
Brian Anderson 已提交
759
          bound_const => {
760 761
            kind = raise_kind(kind, kind_const());
          }
B
Brian Anderson 已提交
762
          bound_trait(_) => ()
763 764 765 766 767
        }
    }
    kind
}

768 769 770 771 772 773 774 775 776 777
/// 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
778 779 780
pub type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
                                   region_param: Option<region_variance>,
                                   ty: t};
781

782
pub type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t};
783

B
Brian Anderson 已提交
784
type type_cache = HashMap<ast::def_id, ty_param_bounds_and_ty>;
785

B
Brian Anderson 已提交
786
type constness_cache = HashMap<ast::def_id, const_eval::constness>;
787

788
pub type node_type_table = @oldsmallintmap::SmallIntMap<t>;
789

790
fn mk_rcache() -> creader_cache {
M
Marijn Haverbeke 已提交
791
    type val = {cnum: int, pos: uint, len: uint};
B
Brian Anderson 已提交
792
    return map::HashMap();
793
}
794

795
pub fn new_ty_hash<V: Copy>() -> map::HashMap<t, V> {
B
Brian Anderson 已提交
796
    map::HashMap()
797
}
798

799 800 801 802 803 804 805 806 807
pub fn mk_ctxt(s: session::Session,
               dm: resolve::DefMap,
               amap: ast_map::map,
               freevars: freevars::freevar_map,
               region_map: middle::region::region_map,
               region_paramd_items: middle::region::region_paramd_items,
               +lang_items: middle::lang_items::LanguageItems,
               crate: @ast::crate)
            -> ctxt {
808
    let mut legacy_modes = false;
809
    let mut legacy_records = false;
810 811
    for crate.node.attrs.each |attribute| {
        match attribute.node.value.node {
812
            ast::meta_word(ref w) if (*w) == ~"legacy_modes" => {
813
                legacy_modes = true;
814 815 816 817 818
                if legacy_records { break; }
            }
            ast::meta_word(ref w) if (*w) == ~"legacy_records" => {
                legacy_records = true;
                if legacy_modes { break; }
819 820 821 822 823
            }
            _ => {}
        }
    }

B
Brian Anderson 已提交
824
    let interner = map::HashMap();
825
    let vecs_implicitly_copyable =
826 827
        get_lint_level(s.lint_settings.default_settings,
                       lint::vecs_implicitly_copyable) == allow;
828 829 830 831 832 833 834 835 836 837 838 839
    @ctxt_ {
        diag: s.diagnostic(),
        interner: interner,
        mut next_id: 0u,
        vecs_implicitly_copyable: vecs_implicitly_copyable,
        legacy_modes: legacy_modes,
        legacy_records: legacy_records,
        cstore: s.cstore,
        sess: s,
        def_map: dm,
        region_map: region_map,
        region_paramd_items: region_paramd_items,
840
        node_types: @oldsmallintmap::mk(),
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
        node_type_substs: map::HashMap(),
        items: amap,
        intrinsic_defs: map::HashMap(),
        freevars: freevars,
        tcache: HashMap(),
        rcache: mk_rcache(),
        ccache: HashMap(),
        short_names_cache: new_ty_hash(),
        needs_drop_cache: new_ty_hash(),
        needs_unwind_cleanup_cache: new_ty_hash(),
        kind_cache: new_ty_hash(),
        ast_ty_to_ty_cache: HashMap(),
        enum_var_cache: HashMap(),
        trait_method_cache: HashMap(),
        ty_param_bounds: HashMap(),
        inferred_modes: HashMap(),
        adjustments: HashMap(),
        normalized_cache: new_ty_hash(),
        lang_items: move lang_items,
        legacy_boxed_traits: HashMap(),
        provided_methods: HashMap(),
        provided_method_sources: HashMap(),
        supertraits: HashMap(),
        destructor_for_type: HashMap(),
        destructors: HashMap(),
        trait_impls: HashMap()
867
     }
868
}
869 870


871
// Type constructors
B
Brian Anderson 已提交
872
fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) }
873 874 875

// 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).
B
Brian Anderson 已提交
876
fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
877
    let key = intern_key { sty: to_unsafe_ptr(&st), o_def_id: o_def_id };
878
    match cx.interner.find(key) {
879
      Some(t) => unsafe { return cast::reinterpret_cast(&t); },
B
Brian Anderson 已提交
880
      _ => ()
881
    }
882

883
    let mut flags = 0u;
884
    fn rflags(r: Region) -> uint {
885
        (has_regions as uint) | {
886
            match r {
887
              ty::re_infer(_) => needs_infer as uint,
B
Brian Anderson 已提交
888
              _ => 0u
889
            }
N
Niko Matsakis 已提交
890 891
        }
    }
N
Niko Matsakis 已提交
892
    fn sflags(substs: &substs) -> uint {
893
        let mut f = 0u;
894
        for substs.tps.each |tt| { f |= get(*tt).flags; }
B
Brian Anderson 已提交
895
        substs.self_r.iter(|r| f |= rflags(*r));
B
Brian Anderson 已提交
896
        return f;
N
Niko Matsakis 已提交
897
    }
898 899
    match &st {
      &ty_estr(vstore_slice(r)) => {
900
        flags |= rflags(r);
901
      }
902
      &ty_evec(ref mt, vstore_slice(r)) => {
903 904
        flags |= rflags(r);
        flags |= get(mt.ty).flags;
905
      }
906 907
      &ty_nil | &ty_bot | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
      &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
908 909
      &ty_opaque_box => (),
      &ty_err => flags |= has_ty_err as uint,
910 911 912 913 914
      &ty_param(_) => flags |= has_params as uint,
      &ty_infer(_) => flags |= needs_infer as uint,
      &ty_self => flags |= has_self as uint,
      &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
      &ty_trait(_, ref substs, _) => {
915
        flags |= sflags(substs);
916
      }
917 918
      &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
      &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
919
        flags |= get(m.ty).flags;
920
      }
921
      &ty_rptr(r, ref m) => {
922 923
        flags |= rflags(r);
        flags |= get(m.ty).flags;
M
Marijn Haverbeke 已提交
924
      }
925 926 927
      &ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
      &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
      &ty_fn(ref f) => {
928
        flags |= rflags(f.meta.region);
929 930
        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
        flags |= get(f.sig.output).flags;
M
Marijn Haverbeke 已提交
931
      }
932
    }
933 934 935

    let t = @{sty: move st, id: cx.next_id, flags: flags, o_def_id: o_def_id};

936
    let key = intern_key {sty: to_unsafe_ptr(&t.sty), o_def_id: o_def_id};
937 938
    cx.interner.insert(move key, t);

939
    cx.next_id += 1u;
940
    unsafe { cast::reinterpret_cast(&t) }
941 942
}

943
pub fn mk_nil(cx: ctxt) -> t { mk_t(cx, ty_nil) }
P
Patrick Walton 已提交
944

945
pub fn mk_err(cx: ctxt) -> t { mk_t(cx, ty_err) }
946

947
pub fn mk_bot(cx: ctxt) -> t { mk_t(cx, ty_bot) }
948

949
pub fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) }
950

951
pub fn mk_int(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i)) }
952

953
pub fn mk_i8(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i8)) }
954

955
pub fn mk_i16(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i16)) }
956

957
pub fn mk_i32(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i32)) }
958

959
pub fn mk_i64(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i64)) }
960

961
pub fn mk_float(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f)) }
962

963
pub fn mk_uint(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u)) }
964

965
pub fn mk_u8(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u8)) }
966

967
pub fn mk_u16(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u16)) }
968

969
pub fn mk_u32(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u32)) }
970

971
pub fn mk_u64(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u64)) }
972

973
pub fn mk_f32(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f32)) }
974

975
pub fn mk_f64(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f64)) }
976

977
pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { mk_t(cx, ty_int(tm)) }
978

979
pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { mk_t(cx, ty_uint(tm)) }
980

981 982 983
pub fn mk_mach_float(cx: ctxt, tm: ast::float_ty) -> t {
    mk_t(cx, ty_float(tm))
}
984

985
pub fn mk_char(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_char)) }
986

987
pub fn mk_estr(cx: ctxt, t: vstore) -> t {
988 989 990
    mk_t(cx, ty_estr(t))
}

991
pub fn mk_enum(cx: ctxt, did: ast::def_id, +substs: substs) -> t {
N
Niko Matsakis 已提交
992
    // take a copy of substs so that we own the vectors inside
993
    mk_t(cx, ty_enum(did, substs))
994
}
995

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

998
pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
999 1000
    mk_box(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1001

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

1004
pub fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
1005 1006
    mk_uniq(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1007

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

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

1012
pub fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1013
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_mutbl})
1014
}
1015
pub fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1016
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_imm})
1017 1018
}

1019
pub fn mk_mut_ptr(cx: ctxt, ty: t) -> t {
1020 1021
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_mutbl})
}
1022

1023
pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
1024
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_imm})
1025 1026
}

1027
pub fn mk_nil_ptr(cx: ctxt) -> t {
1028
    mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::m_imm})
1029 1030
}

1031
pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
1032 1033 1034
    mk_t(cx, ty_evec(tm, t))
}

1035
pub fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
M
Michael Sullivan 已提交
1036 1037
    mk_t(cx, ty_unboxed_vec(tm))
}
1038
pub fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
1039
    mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::m_imm}))
1040
}
M
Michael Sullivan 已提交
1041

1042
pub fn mk_rec(cx: ctxt, +fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) }
1043

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

N
Niko Matsakis 已提交
1046
// take a copy because we want to own the various vectors inside
1047
pub fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) }
1048

1049
pub fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
1050
         -> t {
N
Niko Matsakis 已提交
1051
    // take a copy of substs so that we own the vectors inside
1052
    mk_t(cx, ty_trait(did, substs, vstore))
1053 1054
}

1055
pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, +substs: substs) -> t {
N
Niko Matsakis 已提交
1056
    // take a copy of substs so that we own the vectors inside
1057
    mk_t(cx, ty_struct(struct_id, substs))
T
Tim Chevalier 已提交
1058 1059
}

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

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

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

1066
pub fn mk_infer(cx: ctxt, +it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
1067

1068
pub fn mk_self(cx: ctxt) -> t { mk_t(cx, ty_self) }
M
Marijn Haverbeke 已提交
1069

1070
pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
1071
    mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
1072
}
1073

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

1076
pub fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t {
1077
    mk_t(cx, ty_opaque_closure_ptr(proto))
1078 1079
}

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

1082
pub fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t {
1083
    mk_t_with_id(cx, /*bad*/copy get(base).sty, Some(def_id))
1084 1085 1086
}

// Converts s to its machine type equivalent
1087
pub pure fn mach_sty(cfg: @session::config, t: t) -> sty {
1088
    match get(t).sty {
B
Brian Anderson 已提交
1089 1090 1091
      ty_int(ast::ty_i) => ty_int(cfg.int_type),
      ty_uint(ast::ty_u) => ty_uint(cfg.uint_type),
      ty_float(ast::ty_f) => ty_float(cfg.float_type),
1092
      ref s => (/*bad*/copy *s)
1093 1094 1095
    }
}

1096
pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
1097 1098 1099 1100
        // FIXME(#2202) --- We retain by-ref for fn& things to workaround a
        // memory leak that otherwise results when @fn is upcast to &fn.
    if type_is_fn(ty) {
        match ty_fn_proto(ty) {
1101 1102 1103 1104
            ast::ProtoBorrowed => {
                return ast::by_ref;
            }
            _ => {}
1105 1106 1107
        }
    }
    return if tcx.legacy_modes {
1108 1109 1110 1111 1112 1113 1114 1115 1116
        if type_is_borrowed(ty) {
            // the old mode default was ++ for things like &ptr, but to be
            // forward-compatible with non-legacy, we should use +
            ast::by_copy
        } else if ty::type_is_immediate(ty) {
            ast::by_val
        } else {
            ast::by_ref
        }
1117 1118
    } else {
        ast::by_copy
1119 1120 1121 1122 1123 1124 1125
    };

    fn type_is_fn(ty: t) -> bool {
        match get(ty).sty {
            ty_fn(*) => true,
            _ => false
        }
1126
    }
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138

    fn type_is_borrowed(ty: t) -> bool {
        match ty::get(ty).sty {
            ty::ty_rptr(*) => true,
            ty_evec(_, vstore_slice(_)) => true,
            ty_estr(vstore_slice(_)) => true,

            // technically, we prob ought to include
            // &fn(), but that is treated specially due to #2202
            _ => false
        }
    }
1139 1140
}

1141 1142
// Returns the narrowest lifetime enclosing the evaluation of the expression
// with id `id`.
1143
pub fn encl_region(cx: ctxt, id: ast::node_id) -> ty::Region {
1144
    match cx.region_map.find(id) {
B
Brian Anderson 已提交
1145 1146
      Some(encl_scope) => ty::re_scope(encl_scope),
      None => ty::re_static
1147 1148 1149
    }
}

1150
pub fn walk_ty(ty: t, f: fn(t)) {
B
Brian Anderson 已提交
1151
    maybe_walk_ty(ty, |t| { f(t); true });
1152 1153
}

1154
pub fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
B
Brian Anderson 已提交
1155
    if !f(ty) { return; }
1156
    match /*bad*/copy get(ty).sty {
1157
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
M
Michael Sullivan 已提交
1158
      ty_estr(_) | ty_type | ty_opaque_box | ty_self |
1159
      ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1160
      }
M
Michael Sullivan 已提交
1161
      ty_box(tm) | ty_evec(tm, _) | ty_unboxed_vec(tm) |
B
Brian Anderson 已提交
1162
      ty_ptr(tm) | ty_rptr(_, tm) => {
1163
        maybe_walk_ty(tm.ty, f);
1164
      }
1165
      ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1166 1167
      ty_trait(_, ref substs, _) => {
        for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); }
1168
      }
B
Brian Anderson 已提交
1169
      ty_rec(fields) => {
B
Brian Anderson 已提交
1170
        for fields.each |fl| { maybe_walk_ty(fl.mt.ty, f); }
M
Marijn Haverbeke 已提交
1171
      }
1172
      ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
N
Niko Matsakis 已提交
1173
      ty_fn(ref ft) => {
1174 1175
        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
        maybe_walk_ty(ft.sig.output, f);
M
Marijn Haverbeke 已提交
1176
      }
B
Brian Anderson 已提交
1177
      ty_uniq(tm) => { maybe_walk_ty(tm.ty, f); }
1178 1179 1180
    }
}

1181
pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: fn(t) -> t) -> t {
N
Niko Matsakis 已提交
1182
    mk_t(tcx, fold_sty(sty, foldop))
1183
}
1184

1185
pub fn fold_sig(sig: &FnSig, fldop: fn(t) -> t) -> FnSig {
1186
    let args = do sig.inputs.map |arg| {
1187
        arg { mode: arg.mode, ty: fldop(arg.ty) }
1188 1189 1190 1191 1192 1193 1194 1195
    };

    FnSig {
        inputs: move args,
        output: fldop(sig.output)
    }
}

N
Niko Matsakis 已提交
1196 1197
fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
    fn fold_substs(substs: &substs, fldop: fn(t) -> t) -> substs {
1198 1199 1200
        substs {self_r: substs.self_r,
                self_ty: substs.self_ty.map(|t| fldop(*t)),
                tps: substs.tps.map(|t| fldop(*t))}
1201 1202
    }

1203
    match /*bad*/copy *sty {
1204
        ty_box(tm) => {
1205
            ty_box(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1206 1207
        }
        ty_uniq(tm) => {
1208
            ty_uniq(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1209 1210
        }
        ty_ptr(tm) => {
1211
            ty_ptr(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1212 1213
        }
        ty_unboxed_vec(tm) => {
1214
            ty_unboxed_vec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1215 1216
        }
        ty_evec(tm, vst) => {
1217
            ty_evec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
        }
        ty_enum(tid, ref substs) => {
            ty_enum(tid, fold_substs(substs, fldop))
        }
        ty_trait(did, ref substs, vst) => {
            ty_trait(did, fold_substs(substs, fldop), vst)
        }
        ty_rec(fields) => {
            let new_fields = do vec::map(fields) |fl| {
                let new_ty = fldop(fl.mt.ty);
1228 1229
                let new_mt = mt { ty: new_ty, mutbl: fl.mt.mutbl };
                field { ident: fl.ident, mt: new_mt }
1230 1231 1232 1233
            };
            ty_rec(new_fields)
        }
        ty_tup(ts) => {
1234
            let new_ts = vec::map(ts, |tt| fldop(*tt));
1235 1236 1237
            ty_tup(new_ts)
        }
        ty_fn(ref f) => {
1238 1239
            let sig = fold_sig(&f.sig, fldop);
            ty_fn(FnTyBase {meta: f.meta, sig: sig})
1240 1241
        }
        ty_rptr(r, tm) => {
1242
            ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1243
        }
1244 1245
        ty_struct(did, ref substs) => {
            ty_struct(did, fold_substs(substs, fldop))
1246 1247
        }
        ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1248
        ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1249
        ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
1250
            /*bad*/copy *sty
1251
        }
N
Niko Matsakis 已提交
1252 1253
    }
}
1254

N
Niko Matsakis 已提交
1255
// Folds types from the bottom up.
1256
pub fn fold_ty(cx: ctxt, t0: t, fldop: fn(t) -> t) -> t {
1257
    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
N
Niko Matsakis 已提交
1258 1259
    fldop(mk_t(cx, sty))
}
1260

1261
pub fn walk_regions_and_ty(
1262 1263
    cx: ctxt,
    ty: t,
1264
    walkr: fn(r: Region),
1265 1266 1267 1268 1269
    walkt: fn(t: t) -> bool) {

    if (walkt(ty)) {
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1270 1271 1272
            |r| { walkr(r); r },
            |t| { walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t },
            |t| { walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t });
1273 1274 1275
    }
}

1276
pub fn fold_regions_and_ty(
1277 1278
    cx: ctxt,
    ty: t,
1279
    fldr: fn(r: Region) -> Region,
1280 1281 1282 1283
    fldfnt: fn(t: t) -> t,
    fldt: fn(t: t) -> t) -> t {

    fn fold_substs(
N
Niko Matsakis 已提交
1284
        substs: &substs,
1285
        fldr: fn(r: Region) -> Region,
1286 1287 1288 1289 1290 1291 1292
        fldt: fn(t: t) -> t)
     -> 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))
        }
1293 1294 1295
    }

    let tb = ty::get(ty);
1296
    match tb.sty {
B
Brian Anderson 已提交
1297
      ty::ty_rptr(r, mt) => {
1298 1299
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1300
        ty::mk_rptr(cx, m_r, mt {ty: m_t, mutbl: mt.mutbl})
1301
      }
B
Brian Anderson 已提交
1302
      ty_estr(vstore_slice(r)) => {
1303 1304 1305
        let m_r = fldr(r);
        ty::mk_estr(cx, vstore_slice(m_r))
      }
B
Brian Anderson 已提交
1306
      ty_evec(mt, vstore_slice(r)) => {
1307 1308
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1309
        ty::mk_evec(cx, mt {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
1310
      }
N
Niko Matsakis 已提交
1311
      ty_enum(def_id, ref substs) => {
1312 1313
        ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
      }
1314 1315
      ty_struct(def_id, ref substs) => {
        ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1316
      }
1317 1318
      ty_trait(def_id, ref substs, vst) => {
        ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
1319
      }
1320
      ty_fn(ref f) => {
1321 1322 1323
          ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region),
                                                ..f.meta},
                                  sig: fold_sig(&f.sig, fldfnt)})
1324
      }
N
Niko Matsakis 已提交
1325
      ref sty => {
B
Brian Anderson 已提交
1326
        fold_sty_to_ty(cx, sty, |t| fldt(t))
1327 1328 1329 1330
      }
    }
}

1331 1332 1333 1334 1335 1336 1337
/* A little utility: it often happens that I have a `fn_ty`,
 * but I want to use some function like `fold_regions_and_ty()`
 * that is defined over all types.  This utility converts to
 * a full type and back.  It's not the best way to do this (somewhat
 * inefficient to do the conversion), it would be better to refactor
 * all this folding business.  However, I've been waiting on that
 * until trait support is improved. */
1338
pub fn apply_op_on_t_to_ty_fn(
1339 1340 1341 1342
    cx: ctxt,
    f: &FnTy,
    t_op: fn(t) -> t) -> FnTy
{
1343
    let t0 = ty::mk_fn(cx, /*bad*/copy *f);
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354
    let t1 = t_op(t0);
    match ty::get(t1).sty {
        ty::ty_fn(copy f) => {
            move f
        }
        _ => {
            cx.sess.bug(~"`t_op` did not return a function type");
        }
    }
}

1355 1356
// n.b. this function is intended to eventually replace fold_region() below,
// that is why its name is so similar.
1357
pub fn fold_regions(
1358 1359
    cx: ctxt,
    ty: t,
1360
    fldr: fn(r: Region, in_fn: bool) -> Region) -> t {
1361
    fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1362
               fldr: fn(Region, bool) -> Region) -> t {
1363
        debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
B
Brian Anderson 已提交
1364
        if !type_has_regions(ty) { return ty; }
1365 1366
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1367 1368 1369
            |r| fldr(r, in_fn),
            |t| do_fold(cx, t, true, fldr),
            |t| do_fold(cx, t, in_fn, fldr))
1370 1371 1372 1373
    }
    do_fold(cx, ty, false, fldr)
}

1374
pub fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t {
N
Niko Matsakis 已提交
1375
    fn do_fold(cx: ctxt, t0: t, under_r: bool,
1376
               fldop: fn(Region, bool) -> Region) -> t {
N
Niko Matsakis 已提交
1377
        let tb = get(t0);
B
Brian Anderson 已提交
1378
        if !tbox_has_flag(tb, has_regions) { return t0; }
1379
        match tb.sty {
1380
          ty_rptr(r, mt {ty: t1, mutbl: m}) => {
N
Niko Matsakis 已提交
1381 1382
            let m_r = fldop(r, under_r);
            let m_t1 = do_fold(cx, t1, true, fldop);
1383
            ty::mk_rptr(cx, m_r, mt {ty: m_t1, mutbl: m})
1384
          }
B
Brian Anderson 已提交
1385
          ty_estr(vstore_slice(r)) => {
1386 1387 1388
            let m_r = fldop(r, under_r);
            ty::mk_estr(cx, vstore_slice(m_r))
          }
1389
          ty_evec(mt {ty: t1, mutbl: m}, vstore_slice(r)) => {
1390 1391
            let m_r = fldop(r, under_r);
            let m_t1 = do_fold(cx, t1, true, fldop);
1392
            ty::mk_evec(cx, mt {ty: m_t1, mutbl: m}, vstore_slice(m_r))
1393
          }
B
Brian Anderson 已提交
1394
          ty_fn(_) => {
N
Niko Matsakis 已提交
1395 1396
            // do not recurse into functions, which introduce fresh bindings
            t0
1397
          }
N
Niko Matsakis 已提交
1398
          ref sty => {
B
Brian Anderson 已提交
1399
            do fold_sty_to_ty(cx, sty) |t| {
N
Niko Matsakis 已提交
1400
                do_fold(cx, t, under_r, fldop)
1401
            }
1402
          }
N
Niko Matsakis 已提交
1403
      }
1404
    }
1405

N
Niko Matsakis 已提交
1406
    do_fold(cx, t0, false, fldop)
1407 1408
}

1409
// Substitute *only* type parameters.  Used in trans where regions are erased.
1410
pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
1411
    if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1412
    let tb = ty::get(typ);
1413
    if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1414
    match tb.sty {
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
        ty_param(p) => tps[p.idx],
        ty_self => {
            match self_ty_opt {
                None => cx.sess.bug(~"ty_self unexpected here"),
                Some(self_ty) => {
                    subst_tps(cx, tps, self_ty_opt, self_ty)
                }
            }
        }
        ref sty => {
            fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t))
        }
1427 1428 1429
    }
}

1430
pub fn substs_is_noop(substs: &substs) -> bool {
1431 1432 1433
    substs.tps.len() == 0u &&
        substs.self_r.is_none() &&
        substs.self_ty.is_none()
1434 1435
}

1436
pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
P
Paul Stansifer 已提交
1437
    fmt!("substs(self_r=%s, self_ty=%s, tps=%?)",
1438
         substs.self_r.map_default(~"none", |r| region_to_str(cx, *r)),
1439 1440
         substs.self_ty.map_default(~"none",
                                    |t| ::util::ppaux::ty_to_str(cx, *t)),
1441
         tys_to_str(cx, substs.tps))
1442 1443
}

1444
pub fn param_bound_to_str(cx: ctxt, pb: &param_bound) -> ~str {
1445 1446
    match *pb {
        bound_copy => ~"copy",
1447
        bound_durable => ~"&static",
B
Brian Anderson 已提交
1448
        bound_owned => ~"owned",
1449
        bound_const => ~"const",
1450
        bound_trait(t) => ::util::ppaux::ty_to_str(cx, t)
1451 1452 1453
    }
}

1454
pub fn param_bounds_to_str(cx: ctxt, pbs: param_bounds) -> ~str {
1455
    fmt!("%?", pbs.map(|pb| param_bound_to_str(cx, pb)))
1456 1457
}

1458 1459 1460 1461
pub fn subst(cx: ctxt,
             substs: &substs,
             typ: t)
          -> t {
P
Paul Stansifer 已提交
1462
    debug!("subst(substs=%s, typ=%s)",
1463
           substs_to_str(cx, substs),
1464
           ::util::ppaux::ty_to_str(cx, typ));
N
Niko Matsakis 已提交
1465

B
Brian Anderson 已提交
1466
    if substs_is_noop(substs) { return typ; }
1467
    let r = do_subst(cx, substs, typ);
1468
    debug!("  r = %s", ::util::ppaux::ty_to_str(cx, r));
B
Brian Anderson 已提交
1469
    return r;
1470 1471

    fn do_subst(cx: ctxt,
N
Niko Matsakis 已提交
1472
                substs: &substs,
1473 1474
                typ: t) -> t {
        let tb = get(typ);
B
Brian Anderson 已提交
1475
        if !tbox_has_flag(tb, needs_subst) { return typ; }
1476
        match tb.sty {
B
Brian Anderson 已提交
1477 1478 1479
          ty_param(p) => substs.tps[p.idx],
          ty_self => substs.self_ty.get(),
          _ => {
1480 1481
            fold_regions_and_ty(
                cx, typ,
1482
                |r| match r {
1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
                    re_bound(br_self) => {
                        match substs.self_r {
                            None => {
                                cx.sess.bug(
                                    fmt!("ty::subst: \
                                  Reference to self region when given substs \
                                  with no self region, ty = %s",
                                  ::util::ppaux::ty_to_str(cx, typ)))
                            }
                            Some(self_r) => self_r
                        }
                    }
B
Brian Anderson 已提交
1495
                    _ => r
1496
                },
B
Brian Anderson 已提交
1497 1498
                |t| do_subst(cx, substs, t),
                |t| do_subst(cx, substs, t))
1499 1500
          }
        }
N
Niko Matsakis 已提交
1501 1502
    }
}
1503

Y
Youngsoo Son 已提交
1504
// Performs substitutions on a set of substitutions (result = sup(sub)) to
1505
// yield a new set of substitutions. This is used in trait inheritance.
1506
pub fn subst_substs(cx: ctxt, sup: &substs, sub: &substs) -> substs {
1507
    substs {
Y
Youngsoo Son 已提交
1508 1509 1510
        self_r: sup.self_r,
        self_ty: sup.self_ty.map(|typ| subst(cx, sub, *typ)),
        tps: sup.tps.map(|typ| subst(cx, sub, *typ))
1511 1512 1513
    }
}

1514
// Type utilities
1515

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

1518
pub fn type_is_bot(ty: t) -> bool { get(ty).sty == ty_bot }
1519

1520
pub fn type_is_ty_var(ty: t) -> bool {
1521
    match get(ty).sty {
1522
      ty_infer(TyVar(_)) => true,
B
Brian Anderson 已提交
1523
      _ => false
1524 1525 1526
    }
}

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

1529
pub fn type_is_structural(ty: t) -> bool {
1530
    match get(ty).sty {
1531
      ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_fn(_) |
1532 1533 1534
      ty_trait(*) |
      ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
B
Brian Anderson 已提交
1535 1536
      => true,
      _ => false
1537 1538 1539
    }
}

1540
pub fn type_is_copyable(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
1541
    return kind_can_be_copied(type_kind(cx, ty));
1542 1543
}

1544
pub fn type_is_sequence(ty: t) -> bool {
1545
    match get(ty).sty {
B
Brian Anderson 已提交
1546 1547
      ty_estr(_) | ty_evec(_, _) => true,
      _ => false
1548 1549 1550
    }
}

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

1558
pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
1559
    match get(ty).sty {
B
Brian Anderson 已提交
1560 1561 1562 1563
      ty_estr(_) => return mk_mach_uint(cx, ast::ty_u8),
      ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
      _ => cx.sess.bug(
          ~"sequence_element_type called on non-sequence value"),
1564 1565 1566
    }
}

1567
pub fn get_element_type(ty: t, i: uint) -> t {
1568
    match /*bad*/copy get(ty).sty {
B
Brian Anderson 已提交
1569 1570
      ty_rec(flds) => return flds[i].mt.ty,
      ty_tup(ts) => return ts[i],
1571
      _ => die!(~"get_element_type called on invalid type")
1572 1573 1574
    }
}

1575
pub pure fn type_is_box(ty: t) -> bool {
1576
    match get(ty).sty {
B
Brian Anderson 已提交
1577 1578
      ty_box(_) => return true,
      _ => return false
1579
    }
M
Marijn Haverbeke 已提交
1580 1581
}

1582
pub pure fn type_is_boxed(ty: t) -> bool {
1583
    match get(ty).sty {
1584
      ty_box(_) | ty_opaque_box |
B
Brian Anderson 已提交
1585 1586
      ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
      _ => false
1587 1588 1589
    }
}

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

1597
pub pure fn type_is_slice(ty: t) -> bool {
1598
    match get(ty).sty {
B
Brian Anderson 已提交
1599 1600
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
      _ => return false
1601 1602 1603
    }
}

1604
pub pure fn type_is_unique_box(ty: t) -> bool {
1605
    match get(ty).sty {
B
Brian Anderson 已提交
1606 1607
      ty_uniq(_) => return true,
      _ => return false
1608
    }
M
Marijn Haverbeke 已提交
1609
}
1610

1611
pub pure fn type_is_unsafe_ptr(ty: t) -> bool {
1612
    match get(ty).sty {
B
Brian Anderson 已提交
1613 1614
      ty_ptr(_) => return true,
      _ => return false
1615 1616 1617
    }
}

1618
pub pure fn type_is_vec(ty: t) -> bool {
1619
    return match get(ty).sty {
B
Brian Anderson 已提交
1620 1621 1622
          ty_evec(_, _) | ty_unboxed_vec(_) => true,
          ty_estr(_) => true,
          _ => false
B
Brian Anderson 已提交
1623
        };
M
Marijn Haverbeke 已提交
1624 1625
}

1626
pub pure fn type_is_unique(ty: t) -> bool {
1627
    match get(ty).sty {
B
Brian Anderson 已提交
1628 1629 1630 1631
      ty_uniq(_) => return true,
      ty_evec(_, vstore_uniq) => true,
      ty_estr(vstore_uniq) => true,
      _ => return false
B
Brian Anderson 已提交
1632
    }
1633 1634
}

1635 1636 1637 1638 1639
/*
 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.)
*/
1640
pub pure fn type_is_scalar(ty: t) -> bool {
1641
    match get(ty).sty {
1642
      ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1643 1644
      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
      ty_ptr(_) => true,
B
Brian Anderson 已提交
1645
      _ => false
M
Marijn Haverbeke 已提交
1646
    }
1647 1648
}

1649
pub fn type_is_immediate(ty: t) -> bool {
B
Brian Anderson 已提交
1650
    return type_is_scalar(ty) || type_is_boxed(ty) ||
1651
        type_is_unique(ty) || type_is_region_ptr(ty);
1652 1653
}

1654
pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1655
    match cx.needs_drop_cache.find(ty) {
B
Brian Anderson 已提交
1656 1657
      Some(result) => return result,
      None => {/* fall through */ }
M
Marijn Haverbeke 已提交
1658 1659
    }

1660
    let mut accum = false;
1661
    let result = match /*bad*/copy get(ty).sty {
M
Marijn Haverbeke 已提交
1662
      // scalar types
1663
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1664
      ty_type | ty_ptr(_) | ty_rptr(_, _) |
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676
      ty_estr(vstore_fixed(_)) |
      ty_estr(vstore_slice(_)) |
      ty_evec(_, vstore_slice(_)) |
      ty_self => false,

      ty_box(_) | ty_uniq(_) |
      ty_opaque_box | ty_opaque_closure_ptr(*) |
      ty_estr(vstore_uniq) |
      ty_estr(vstore_box) |
      ty_evec(_, vstore_uniq) |
      ty_evec(_, vstore_box) => true,

1677 1678 1679 1680
      ty_trait(_, _, vstore_box) |
      ty_trait(_, _, vstore_uniq) => true,
      ty_trait(_, _, vstore_fixed(_)) |
      ty_trait(_, _, vstore_slice(_)) => false,
1681

1682
      ty_param(*) | ty_infer(*) | ty_err => true,
1683

B
Brian Anderson 已提交
1684 1685 1686
      ty_evec(mt, vstore_fixed(_)) => type_needs_drop(cx, mt.ty),
      ty_unboxed_vec(mt) => type_needs_drop(cx, mt.ty),
      ty_rec(flds) => {
B
Brian Anderson 已提交
1687 1688 1689
        for flds.each |f| {
            if type_needs_drop(cx, f.mt.ty) { accum = true; }
        }
1690
        accum
M
Marijn Haverbeke 已提交
1691
      }
1692 1693
      ty_struct(did, ref substs) => {
         // Any struct with a dtor needs a drop
1694
         ty_dtor(cx, did).is_present() || {
1695
             for vec::each(ty::struct_fields(cx, did, substs)) |f| {
1696 1697 1698
                 if type_needs_drop(cx, f.mt.ty) { accum = true; }
             }
             accum
1699
         }
1700
      }
B
Brian Anderson 已提交
1701
      ty_tup(elts) => {
1702
          for elts.each |m| { if type_needs_drop(cx, *m) { accum = true; } }
1703
        accum
1704
      }
N
Niko Matsakis 已提交
1705
      ty_enum(did, ref substs) => {
1706
        let variants = enum_variants(cx, did);
1707
          for vec::each(*variants) |variant| {
B
Brian Anderson 已提交
1708
              for variant.args.each |aty| {
M
Marijn Haverbeke 已提交
1709
                // Perform any type parameter substitutions.
1710
                let arg_ty = subst(cx, substs, *aty);
1711
                if type_needs_drop(cx, arg_ty) { accum = true; }
1712
            }
1713
            if accum { break; }
1714
        }
1715
        accum
M
Marijn Haverbeke 已提交
1716
      }
N
Niko Matsakis 已提交
1717
      ty_fn(ref fty) => {
1718
        match fty.meta.proto {
1719 1720
          ast::ProtoBare | ast::ProtoBorrowed => false,
          ast::ProtoBox | ast::ProtoUniq => true,
1721 1722
        }
      }
1723
    };
1724

1725
    cx.needs_drop_cache.insert(ty, result);
B
Brian Anderson 已提交
1726
    return result;
1727 1728
}

1729 1730 1731 1732
// 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.
1733
pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1734
    match cx.needs_unwind_cleanup_cache.find(ty) {
B
Brian Anderson 已提交
1735 1736
      Some(result) => return result,
      None => ()
1737 1738
    }

1739 1740 1741 1742
    let tycache = new_ty_hash();
    let needs_unwind_cleanup =
        type_needs_unwind_cleanup_(cx, ty, tycache, false);
    cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
B
Brian Anderson 已提交
1743
    return needs_unwind_cleanup;
1744 1745 1746
}

fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
B
Brian Anderson 已提交
1747
                              tycache: map::HashMap<t, ()>,
1748 1749
                              encountered_box: bool) -> bool {

1750
    // Prevent infinite recursion
1751
    match tycache.find(ty) {
B
Brian Anderson 已提交
1752 1753
      Some(_) => return false,
      None => { tycache.insert(ty, ()); }
1754
    }
1755

1756
    let mut encountered_box = encountered_box;
1757
    let mut needs_unwind_cleanup = false;
B
Brian Anderson 已提交
1758
    do maybe_walk_ty(ty) |ty| {
1759
        let old_encountered_box = encountered_box;
1760
        let result = match get(ty).sty {
B
Brian Anderson 已提交
1761
          ty_box(_) | ty_opaque_box => {
1762 1763 1764
            encountered_box = true;
            true
          }
1765 1766
          ty_nil | ty_bot | ty_bool |
          ty_int(_) | ty_uint(_) | ty_float(_) |
B
Brian Anderson 已提交
1767
          ty_rec(_) | ty_tup(_) | ty_ptr(_) => {
1768 1769
            true
          }
N
Niko Matsakis 已提交
1770
          ty_enum(did, ref substs) => {
1771
            for vec::each(*enum_variants(cx, did)) |v| {
B
Brian Anderson 已提交
1772
                for v.args.each |aty| {
1773
                    let t = subst(cx, substs, *aty);
1774 1775 1776
                    needs_unwind_cleanup |=
                        type_needs_unwind_cleanup_(cx, t, tycache,
                                                   encountered_box);
1777 1778 1779 1780
                }
            }
            !needs_unwind_cleanup
          }
M
Michael Sullivan 已提交
1781
          ty_uniq(_) |
1782 1783 1784 1785
          ty_estr(vstore_uniq) |
          ty_estr(vstore_box) |
          ty_evec(_, vstore_uniq) |
          ty_evec(_, vstore_box)
B
Brian Anderson 已提交
1786
          => {
1787 1788 1789 1790 1791 1792 1793 1794 1795
            // 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 已提交
1796
          _ => {
1797 1798 1799
            needs_unwind_cleanup = true;
            false
          }
1800 1801 1802 1803
        };

        encountered_box = old_encountered_box;
        result
1804 1805
    }

B
Brian Anderson 已提交
1806
    return needs_unwind_cleanup;
1807 1808
}

1809
pub enum Kind { kind_(u32) }
1810

1811
/// can be copied (implicitly or explicitly)
1812
const KIND_MASK_COPY         : u32 = 0b000000000000000000000000001_u32;
1813

B
Brian Anderson 已提交
1814 1815
/// no shared box, borrowed ptr (must imply DURABLE)
const KIND_MASK_OWNED         : u32 = 0b000000000000000000000000010_u32;
1816

B
Brian Anderson 已提交
1817 1818
/// is durable (no borrowed ptrs)
const KIND_MASK_DURABLE      : u32 = 0b000000000000000000000000100_u32;
1819 1820

/// is deeply immutable
1821
const KIND_MASK_CONST        : u32 = 0b000000000000000000000001000_u32;
1822 1823

/// can be implicitly copied (must imply COPY)
1824 1825 1826 1827
const KIND_MASK_IMPLICIT     : u32 = 0b000000000000000000000010000_u32;

/// safe for default mode (subset of KIND_MASK_IMPLICIT)
const KIND_MASK_DEFAULT_MODE : u32 = 0b000000000000000000000100000_u32;
1828

1829
pub fn kind_noncopyable() -> Kind {
1830 1831 1832
    kind_(0u32)
}

1833
pub fn kind_copyable() -> Kind {
1834 1835 1836
    kind_(KIND_MASK_COPY)
}

1837
pub fn kind_implicitly_copyable() -> Kind {
1838 1839 1840
    kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY)
}

1841
fn kind_safe_for_default_mode() -> Kind {
1842 1843 1844 1845
    // similar to implicit copy, but always includes vectors and strings
    kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY)
}

1846
fn kind_implicitly_sendable() -> Kind {
B
Brian Anderson 已提交
1847
    kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_OWNED)
1848 1849
}

1850
fn kind_safe_for_default_mode_send() -> Kind {
1851 1852
    // similar to implicit copy, but always includes vectors and strings
    kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT |
B
Brian Anderson 已提交
1853
          KIND_MASK_COPY | KIND_MASK_OWNED)
1854 1855 1856
}


B
Brian Anderson 已提交
1857 1858
fn kind_owned_copy() -> Kind {
    kind_(KIND_MASK_COPY | KIND_MASK_OWNED)
1859
}
1860

B
Brian Anderson 已提交
1861 1862
fn kind_owned_only() -> Kind {
    kind_(KIND_MASK_OWNED)
1863 1864
}

1865
pub fn kind_const() -> Kind {
1866 1867 1868
    kind_(KIND_MASK_CONST)
}

B
Brian Anderson 已提交
1869 1870
fn kind_durable() -> Kind {
    kind_(KIND_MASK_DURABLE)
1871 1872
}

1873
fn kind_top() -> Kind {
1874 1875 1876
    kind_(0xffffffffu32)
}

1877
fn remove_const(k: Kind) -> Kind {
1878
    k - kind_const()
1879 1880
}

1881
fn remove_implicit(k: Kind) -> Kind {
1882
    k - kind_(KIND_MASK_IMPLICIT | KIND_MASK_DEFAULT_MODE)
1883 1884
}

B
Brian Anderson 已提交
1885 1886
fn remove_owned(k: Kind) -> Kind {
    k - kind_(KIND_MASK_OWNED)
1887 1888
}

B
Brian Anderson 已提交
1889 1890
fn remove_durable_owned(k: Kind) -> Kind {
    k - kind_(KIND_MASK_DURABLE) - kind_(KIND_MASK_OWNED)
1891 1892
}

1893
fn remove_copyable(k: Kind) -> Kind {
1894
    k - kind_(KIND_MASK_COPY | KIND_MASK_DEFAULT_MODE)
1895 1896
}

1897
impl Kind : ops::BitAnd<Kind,Kind> {
1898
    pure fn bitand(&self, other: &Kind) -> Kind {
1899
        unsafe {
1900
            lower_kind(*self, *other)
1901 1902 1903
        }
    }
}
1904

1905
impl Kind : ops::BitOr<Kind,Kind> {
1906
    pure fn bitor(&self, other: &Kind) -> Kind {
1907
        unsafe {
1908
            raise_kind(*self, *other)
1909 1910 1911
        }
    }
}
1912

1913
impl Kind : ops::Sub<Kind,Kind> {
1914
    pure fn sub(&self, other: &Kind) -> Kind {
1915
        unsafe {
1916
            kind_(**self & !**other)
1917 1918 1919
        }
    }
}
1920

1921
// Using these query functions is preferable to direct comparison or matching
1922 1923
// against the kind constants, as we may modify the kind hierarchy in the
// future.
1924
pub pure fn kind_can_be_implicitly_copied(k: Kind) -> bool {
1925
    *k & KIND_MASK_IMPLICIT == KIND_MASK_IMPLICIT
1926 1927
}

1928
pub pure fn kind_is_safe_for_default_mode(k: Kind) -> bool {
1929 1930 1931
    *k & KIND_MASK_DEFAULT_MODE == KIND_MASK_DEFAULT_MODE
}

1932
pub pure fn kind_can_be_copied(k: Kind) -> bool {
1933
    *k & KIND_MASK_COPY == KIND_MASK_COPY
1934 1935
}

1936
pub pure fn kind_can_be_sent(k: Kind) -> bool {
B
Brian Anderson 已提交
1937
    *k & KIND_MASK_OWNED == KIND_MASK_OWNED
1938 1939
}

1940
pub pure fn kind_is_durable(k: Kind) -> bool {
B
Brian Anderson 已提交
1941
    *k & KIND_MASK_DURABLE == KIND_MASK_DURABLE
1942 1943
}

1944
pub fn meta_kind(p: FnMeta) -> Kind {
1945
    match p.proto { // XXX consider the kind bounds!
1946
        ast::ProtoBare => {
B
Brian Anderson 已提交
1947
            kind_safe_for_default_mode_send() | kind_const() | kind_durable()
1948 1949 1950 1951 1952
        }
        ast::ProtoBorrowed => {
            kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE)
        }
        ast::ProtoBox => {
B
Brian Anderson 已提交
1953
            kind_safe_for_default_mode() | kind_durable()
1954 1955
        }
        ast::ProtoUniq => {
B
Brian Anderson 已提交
1956
            kind_owned_copy() | kind_durable()
1957
        }
1958 1959 1960
    }
}

1961
pub fn kind_lteq(a: Kind, b: Kind) -> bool {
1962
    *a & *b == *a
M
Marijn Haverbeke 已提交
1963 1964
}

1965
fn lower_kind(a: Kind, b: Kind) -> Kind {
1966 1967 1968
    kind_(*a & *b)
}

1969
fn raise_kind(a: Kind, b: Kind) -> Kind {
1970
    kind_(*a | *b)
M
Marijn Haverbeke 已提交
1971 1972
}

1973 1974
#[test]
fn test_kinds() {
1975 1976
    // The kind "lattice" is defined by the subset operation on the
    // set of permitted operations.
B
Brian Anderson 已提交
1977 1978
    assert kind_lteq(kind_owned_copy(), kind_owned_copy());
    assert kind_lteq(kind_copyable(), kind_owned_copy());
1979
    assert kind_lteq(kind_copyable(), kind_copyable());
B
Brian Anderson 已提交
1980
    assert kind_lteq(kind_noncopyable(), kind_owned_copy());
1981 1982
    assert kind_lteq(kind_noncopyable(), kind_copyable());
    assert kind_lteq(kind_noncopyable(), kind_noncopyable());
1983 1984
    assert kind_lteq(kind_copyable(), kind_implicitly_copyable());
    assert kind_lteq(kind_copyable(), kind_implicitly_sendable());
B
Brian Anderson 已提交
1985 1986 1987
    assert kind_lteq(kind_owned_copy(), kind_implicitly_sendable());
    assert !kind_lteq(kind_owned_copy(), kind_implicitly_copyable());
    assert !kind_lteq(kind_copyable(), kind_owned_only());
1988 1989 1990 1991 1992
}

// Return the most permissive kind that a composite object containing a field
// with the given mutability can have.
// This is used to prevent objects containing mutable state from being
1993
// implicitly copied and to compute whether things have const kind.
1994
fn mutability_kind(m: mutability) -> Kind {
1995
    match (m) {
B
Brian Anderson 已提交
1996 1997 1998
      m_mutbl => remove_const(remove_implicit(kind_top())),
      m_const => remove_implicit(kind_top()),
      m_imm => kind_top()
1999 2000 2001
    }
}

2002
fn mutable_type_kind(cx: ctxt, ty: mt) -> Kind {
2003
    lower_kind(mutability_kind(ty.mutbl), type_kind(cx, ty.ty))
2004 2005
}

2006
pub fn type_kind(cx: ctxt, ty: t) -> Kind {
2007 2008 2009 2010 2011
    type_kind_ext(cx, ty, false)
}

// If `allow_ty_var` is true, then this is a conservative assumption; we
// assume that type variables *do* have all kinds.
2012
pub fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
2013
    match cx.kind_cache.find(ty) {
B
Brian Anderson 已提交
2014 2015
      Some(result) => return result,
      None => {/* fall through */ }
2016 2017 2018
    }

    // Insert a default in case we loop back on self recursively.
2019
    cx.kind_cache.insert(ty, kind_top());
2020

2021
    let mut result = match /*bad*/copy get(ty).sty {
2022
      // Scalar and unique types are sendable, constant, and owned
2023
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
B
Brian Anderson 已提交
2024
      ty_ptr(_) => {
B
Brian Anderson 已提交
2025
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2026 2027
      }

2028
      // Implicit copyability of strs is configurable
B
Brian Anderson 已提交
2029
      ty_estr(vstore_uniq) => {
2030
        if cx.vecs_implicitly_copyable {
B
Brian Anderson 已提交
2031
            kind_implicitly_sendable() | kind_const() | kind_durable()
2032
        } else {
B
Brian Anderson 已提交
2033
            kind_owned_copy() | kind_const() | kind_durable()
2034
        }
2035
      }
2036 2037

      // functions depend on the protocol
2038
      ty_fn(ref f) => meta_kind(f.meta),
2039 2040 2041

      // Those with refcounts raise noncopyable to copyable,
      // lower sendable to copyable. Therefore just set result to copyable.
B
Brian Anderson 已提交
2042
      ty_box(tm) => {
B
Brian Anderson 已提交
2043
        remove_owned(mutable_type_kind(cx, tm) | kind_safe_for_default_mode())
2044
      }
2045

2046
      // XXX: This is wrong for ~Trait and &Trait!
2047
      ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_durable(),
2048

2049 2050 2051 2052
      // Static region pointers are copyable and sendable, but not owned
      ty_rptr(re_static, mt) =>
      kind_safe_for_default_mode() | mutable_type_kind(cx, mt),

2053 2054 2055 2056 2057 2058 2059 2060 2061
      ty_rptr(_, mt) => {
        if mt.mutbl == ast::m_mutbl {
            // Mutable region pointers are noncopyable
            kind_noncopyable()
        } else {
            // General region pointers are copyable but NOT owned nor sendable
            kind_safe_for_default_mode()
        }
      }
2062

2063 2064
      // Unique boxes and vecs have the kind of their contained type,
      // but unique boxes can't be implicitly copyable.
B
Brian Anderson 已提交
2065
      ty_uniq(tm) => remove_implicit(mutable_type_kind(cx, tm)),
2066

2067
      // Implicit copyability of vecs is configurable
B
Brian Anderson 已提交
2068
      ty_evec(tm, vstore_uniq) => {
2069
          if cx.vecs_implicitly_copyable {
2070
              mutable_type_kind(cx, tm)
2071 2072 2073
          } else {
              remove_implicit(mutable_type_kind(cx, tm))
          }
2074
      }
2075

2076 2077 2078
      // Slices, refcounted evecs are copyable; uniques depend on the their
      // contained type, but aren't implicitly copyable.  Fixed vectors have
      // the kind of the element they contain, taking mutability into account.
B
Brian Anderson 已提交
2079
      ty_evec(tm, vstore_box) => {
B
Brian Anderson 已提交
2080
        remove_owned(kind_safe_for_default_mode() | mutable_type_kind(cx, tm))
2081
      }
2082 2083 2084
      ty_evec(tm, vstore_slice(re_static)) => {
        kind_safe_for_default_mode() | mutable_type_kind(cx, tm)
      }
B
Brian Anderson 已提交
2085
      ty_evec(tm, vstore_slice(_)) => {
B
Brian Anderson 已提交
2086
        remove_durable_owned(kind_safe_for_default_mode() |
B
Brian Anderson 已提交
2087
                           mutable_type_kind(cx, tm))
2088
      }
B
Brian Anderson 已提交
2089
      ty_evec(tm, vstore_fixed(_)) => {
2090
        mutable_type_kind(cx, tm)
2091
      }
2092 2093

      // All estrs are copyable; uniques and interiors are sendable.
B
Brian Anderson 已提交
2094
      ty_estr(vstore_box) => {
B
Brian Anderson 已提交
2095
        kind_safe_for_default_mode() | kind_const() | kind_durable()
2096
      }
2097
      ty_estr(vstore_slice(re_static)) => {
B
Brian Anderson 已提交
2098
        kind_safe_for_default_mode() | kind_owned_copy() | kind_const()
2099
      }
B
Brian Anderson 已提交
2100
      ty_estr(vstore_slice(_)) => {
2101
        kind_safe_for_default_mode() | kind_const()
2102
      }
B
Brian Anderson 已提交
2103
      ty_estr(vstore_fixed(_)) => {
B
Brian Anderson 已提交
2104
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2105
      }
2106

2107
      // Records lower to the lowest of their members.
B
Brian Anderson 已提交
2108
      ty_rec(flds) => {
2109
        let mut lowest = kind_top();
B
Brian Anderson 已提交
2110
        for flds.each |f| {
2111
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
2112
        }
M
Marijn Haverbeke 已提交
2113
        lowest
2114
      }
2115

2116 2117
      ty_struct(did, ref substs) => {
        // Structs are sendable if all their fields are sendable,
2118
        // likewise for copyable...
2119 2120
        // also factor out this code, copied from the records case
        let mut lowest = kind_top();
2121
        let flds = struct_fields(cx, did, substs);
B
Brian Anderson 已提交
2122
        for flds.each |f| {
2123 2124
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
        }
2125
        // ...but structs with dtors are never copyable (they can be
2126 2127
        // sendable)
        if ty::has_dtor(cx, did) {
2128
           lowest = remove_copyable(lowest);
2129
        }
2130
        lowest
2131
      }
2132

2133
      // Tuples lower to the lowest of their members.
B
Brian Anderson 已提交
2134
      ty_tup(tys) => {
2135
        let mut lowest = kind_top();
2136
        for tys.each |ty| { lowest = lower_kind(lowest, type_kind(cx, *ty)); }
M
Marijn Haverbeke 已提交
2137
        lowest
2138
      }
2139

2140
      // Enums lower to the lowest of their variants.
N
Niko Matsakis 已提交
2141
      ty_enum(did, ref substs) => {
2142
        let mut lowest = kind_top();
2143
        let variants = enum_variants(cx, did);
2144
        if variants.is_empty() {
B
Brian Anderson 已提交
2145
            lowest = kind_owned_only() | kind_durable();
2146
        } else {
2147
            for variants.each |variant| {
B
Brian Anderson 已提交
2148
                for variant.args.each |aty| {
2149
                    // Perform any type parameter substitutions.
2150
                    let arg_ty = subst(cx, substs, *aty);
2151
                    lowest = lower_kind(lowest, type_kind(cx, arg_ty));
2152
                    if lowest == kind_noncopyable() { break; }
2153
                }
2154 2155
            }
        }
M
Marijn Haverbeke 已提交
2156
        lowest
2157
      }
2158

B
Brian Anderson 已提交
2159
      ty_param(p) => {
2160 2161 2162 2163 2164 2165 2166 2167
          // 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.
          assert p.def_id.crate == ast::local_crate;

          param_bounds_to_kind(cx.ty_param_bounds.get(p.def_id.node))
2168
      }
2169

2170
      // self is a special type parameter that can only appear in traits; it
2171
      // is never bounded in any way, hence it has the bottom kind.
B
Brian Anderson 已提交
2172
      ty_self => kind_noncopyable(),
2173

2174
      ty_infer(_) => {
2175 2176 2177 2178 2179
        if allow_ty_var {
            kind_top()
        } else {
            cx.sess.bug(~"Asked to compute kind of a type variable")
        }
2180
      }
2181

B
Brian Anderson 已提交
2182
      ty_type | ty_opaque_closure_ptr(_)
2183
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2184
        cx.sess.bug(~"Asked to compute kind of fictitious type");
2185
      }
M
Marijn Haverbeke 已提交
2186
    };
2187

2188 2189 2190
    // arbitrary threshold to prevent by-value copying of big records
    if kind_is_safe_for_default_mode(result) {
        if type_size(cx, ty) > 4 {
2191
            result = result - kind_(KIND_MASK_DEFAULT_MODE);
2192 2193 2194
        }
    }

2195
    cx.kind_cache.insert(ty, result);
B
Brian Anderson 已提交
2196
    return result;
2197 2198
}

2199
pub fn type_implicitly_moves(cx: ctxt, ty: t) -> bool {
2200 2201 2202 2203
    let kind = type_kind(cx, ty);
    !(kind_can_be_copied(kind) && kind_can_be_implicitly_copied(kind))
}

2204 2205 2206
/// gives a rough estimate of how much space it takes to represent
/// an instance of `ty`.  Used for the mode transition.
fn type_size(cx: ctxt, ty: t) -> uint {
2207
    match /*bad*/copy get(ty).sty {
2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
      ty_ptr(_) | ty_box(_) | ty_uniq(_) | ty_estr(vstore_uniq) |
      ty_trait(*) | ty_rptr(*) | ty_evec(_, vstore_uniq) |
      ty_evec(_, vstore_box) | ty_estr(vstore_box) => {
        1
      }

      ty_evec(_, vstore_slice(_)) |
      ty_estr(vstore_slice(_)) |
      ty_fn(_) => {
        2
      }

      ty_evec(t, vstore_fixed(n)) => {
        type_size(cx, t.ty) * n
      }

      ty_estr(vstore_fixed(n)) => {
        n
      }

      ty_rec(flds) => {
T
Tim Chevalier 已提交
2230
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2231 2232
      }

2233 2234
      ty_struct(did, ref substs) => {
        let flds = struct_fields(cx, did, substs);
T
Tim Chevalier 已提交
2235
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2236 2237
      }

B
Brian Anderson 已提交
2238
      ty_tup(tys) => {
T
Tim Chevalier 已提交
2239
        tys.foldl(0, |s, t| *s + type_size(cx, *t))
2240 2241
      }

N
Niko Matsakis 已提交
2242
      ty_enum(did, ref substs) => {
2243 2244 2245
        let variants = substd_enum_variants(cx, did, substs);
        variants.foldl( // find max size of any variant
            0,
T
Tim Chevalier 已提交
2246
            |m, v| uint::max(*m,
2247
                             // find size of this variant:
T
Tim Chevalier 已提交
2248
                             v.args.foldl(0, |s, a| *s + type_size(cx, *a))))
2249 2250
      }

B
Brian Anderson 已提交
2251
      ty_param(_) | ty_self => {
2252 2253 2254
        1
      }

2255
      ty_infer(_) => {
2256 2257
        cx.sess.bug(~"Asked to compute kind of a type variable");
      }
B
Brian Anderson 已提交
2258
      ty_type | ty_opaque_closure_ptr(_)
2259
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2260 2261 2262 2263 2264
        cx.sess.bug(~"Asked to compute kind of fictitious type");
      }
    }
}

2265
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2266
pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
2267
    fn type_requires(cx: ctxt, seen: @mut ~[def_id],
2268
                     r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2269
        debug!("type_requires(%s, %s)?",
2270 2271
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2272 2273

        let r = {
2274
            get(r_ty).sty == get(ty).sty ||
2275 2276 2277
                subtypes_require(cx, seen, r_ty, ty)
        };

P
Paul Stansifer 已提交
2278
        debug!("type_requires(%s, %s)? %b",
2279 2280
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2281
               r);
B
Brian Anderson 已提交
2282
        return r;
2283 2284
    }

2285
    fn subtypes_require(cx: ctxt, seen: @mut ~[def_id],
2286
                        r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2287
        debug!("subtypes_require(%s, %s)?",
2288 2289
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2290

2291
        let r = match /*bad*/copy get(ty).sty {
2292 2293 2294 2295 2296 2297
          ty_nil |
          ty_bot |
          ty_bool |
          ty_int(_) |
          ty_uint(_) |
          ty_float(_) |
2298
          ty_estr(_) |
2299
          ty_fn(_) |
2300
          ty_infer(_) |
2301
          ty_err |
2302
          ty_param(_) |
2303
          ty_self |
2304 2305 2306
          ty_type |
          ty_opaque_box |
          ty_opaque_closure_ptr(_) |
2307
          ty_evec(_, _) |
B
Brian Anderson 已提交
2308
          ty_unboxed_vec(_) => {
2309 2310 2311 2312
            false
          }
          ty_box(mt) |
          ty_uniq(mt) |
B
Brian Anderson 已提交
2313
          ty_rptr(_, mt) => {
B
Brian Anderson 已提交
2314
            return type_requires(cx, seen, r_ty, mt.ty);
2315 2316
          }

2317
          ty_ptr(*) => {
2318 2319 2320
            false           // unsafe ptrs can always be NULL
          }

B
Brian Anderson 已提交
2321
          ty_rec(fields) => {
B
Brian Anderson 已提交
2322
            do vec::any(fields) |field| {
2323 2324 2325 2326
                type_requires(cx, seen, r_ty, field.mt.ty)
            }
          }

2327
          ty_trait(_, _, _) => {
2328 2329 2330
            false
          }

2331
          ty_struct(ref did, _) if vec::contains(*seen, did) => {
2332 2333 2334
            false
          }

2335
          ty_struct(did, ref substs) => {
2336
              seen.push(did);
2337
              let r = vec::any(struct_fields(cx, did, substs),
2338
                               |f| type_requires(cx, seen, r_ty, f.mt.ty));
N
Niko Matsakis 已提交
2339
              seen.pop();
2340 2341 2342
            r
          }

B
Brian Anderson 已提交
2343
          ty_tup(ts) => {
N
Niko Matsakis 已提交
2344
            vec::any(ts, |t| type_requires(cx, seen, r_ty, *t))
2345 2346
          }

N
Niko Matsakis 已提交
2347
          ty_enum(ref did, _) if vec::contains(*seen, did) => {
2348 2349 2350
            false
          }

2351 2352 2353 2354 2355
            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 已提交
2356
                        let sty = subst(cx, substs, *aty);
2357 2358 2359
                        type_requires(cx, seen, r_ty, sty)
                    })
                });
N
Niko Matsakis 已提交
2360
                seen.pop();
2361 2362
                r
            }
2363 2364
        };

P
Paul Stansifer 已提交
2365
        debug!("subtypes_require(%s, %s)? %b",
2366 2367
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2368
               r);
2369

B
Brian Anderson 已提交
2370
        return r;
2371 2372
    }

2373
    let seen = @mut ~[];
2374 2375 2376
    !subtypes_require(cx, seen, r_ty, r_ty)
}

2377 2378 2379 2380
pub fn type_structurally_contains(cx: ctxt,
                                  ty: t,
                                  test: fn(x: &sty) -> bool)
                               -> bool {
2381
    let sty = &get(ty).sty;
2382 2383
    debug!("type_structurally_contains: %s",
           ::util::ppaux::ty_to_str(cx, ty));
B
Brian Anderson 已提交
2384
    if test(sty) { return true; }
2385
    match /*bad*/copy *sty {
N
Niko Matsakis 已提交
2386
      ty_enum(did, ref substs) => {
2387
        for vec::each(*enum_variants(cx, did)) |variant| {
B
Brian Anderson 已提交
2388
            for variant.args.each |aty| {
2389
                let sty = subst(cx, substs, *aty);
B
Brian Anderson 已提交
2390
                if type_structurally_contains(cx, sty, test) { return true; }
2391
            }
2392
        }
B
Brian Anderson 已提交
2393
        return false;
M
Marijn Haverbeke 已提交
2394
      }
B
Brian Anderson 已提交
2395
      ty_rec(fields) => {
B
Brian Anderson 已提交
2396
        for fields.each |field| {
B
Brian Anderson 已提交
2397 2398 2399
            if type_structurally_contains(cx, field.mt.ty, test) {
                return true;
            }
2400
        }
B
Brian Anderson 已提交
2401
        return false;
M
Marijn Haverbeke 已提交
2402
      }
2403 2404
      ty_struct(did, ref substs) => {
        for lookup_struct_fields(cx, did).each |field| {
2405
            let ft = lookup_field_type(cx, did, field.id, substs);
B
Brian Anderson 已提交
2406
            if type_structurally_contains(cx, ft, test) { return true; }
2407
        }
B
Brian Anderson 已提交
2408
        return false;
2409 2410
      }

B
Brian Anderson 已提交
2411
      ty_tup(ts) => {
B
Brian Anderson 已提交
2412
        for ts.each |tt| {
2413
            if type_structurally_contains(cx, *tt, test) { return true; }
2414
        }
B
Brian Anderson 已提交
2415
        return false;
2416
      }
B
Brian Anderson 已提交
2417
      ty_evec(mt, vstore_fixed(_)) => {
B
Brian Anderson 已提交
2418
        return type_structurally_contains(cx, mt.ty, test);
2419
      }
B
Brian Anderson 已提交
2420
      _ => return false
M
Marijn Haverbeke 已提交
2421 2422 2423
    }
}

2424
pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
2425
    return type_structurally_contains(cx, ty, |sty| {
N
Niko Matsakis 已提交
2426
        match *sty {
2427 2428
          ty_uniq(_) |
          ty_evec(_, vstore_uniq) |
B
Brian Anderson 已提交
2429 2430
          ty_estr(vstore_uniq) => true,
          _ => false,
2431
        }
2432
    });
2433 2434
}

2435
pub fn type_is_integral(ty: t) -> bool {
2436
    match get(ty).sty {
2437
      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) | ty_bool => true,
B
Brian Anderson 已提交
2438
      _ => false
M
Marijn Haverbeke 已提交
2439 2440 2441
    }
}

2442
pub fn type_is_char(ty: t) -> bool {
2443 2444 2445 2446 2447 2448
    match get(ty).sty {
        ty_int(ty_char) => true,
        _ => false
    }
}

2449
pub fn type_is_fp(ty: t) -> bool {
2450
    match get(ty).sty {
2451
      ty_infer(FloatVar(_)) | ty_float(_) => true,
B
Brian Anderson 已提交
2452
      _ => false
M
Marijn Haverbeke 已提交
2453 2454 2455
    }
}

2456
pub fn type_is_numeric(ty: t) -> bool {
B
Brian Anderson 已提交
2457
    return type_is_integral(ty) || type_is_fp(ty);
2458 2459
}

2460
pub fn type_is_signed(ty: t) -> bool {
2461
    match get(ty).sty {
B
Brian Anderson 已提交
2462 2463
      ty_int(_) => true,
      _ => false
M
Marijn Haverbeke 已提交
2464 2465 2466
    }
}

2467 2468
// Whether a type is Plain Old Data -- meaning it does not contain pointers
// that the cycle collector might care about.
2469
pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
2470
    let mut result = true;
2471
    match /*bad*/copy get(ty).sty {
B
Brian Anderson 已提交
2472
      // Scalar types
2473
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
B
Brian Anderson 已提交
2474
      ty_type | ty_ptr(_) => result = true,
B
Brian Anderson 已提交
2475
      // Boxed types
M
Michael Sullivan 已提交
2476
      ty_box(_) | ty_uniq(_) | ty_fn(_) |
2477 2478
      ty_estr(vstore_uniq) | ty_estr(vstore_box) |
      ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2479
      ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
B
Brian Anderson 已提交
2480
      // Structural types
N
Niko Matsakis 已提交
2481
      ty_enum(did, ref substs) => {
2482
        let variants = enum_variants(cx, did);
2483
        for vec::each(*variants) |variant| {
2484
            let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
B
Brian Anderson 已提交
2485 2486

            // Perform any type parameter substitutions.
2487
            let tup_ty = subst(cx, substs, tup_ty);
B
Brian Anderson 已提交
2488
            if !type_is_pod(cx, tup_ty) { result = false; }
2489
        }
B
Brian Anderson 已提交
2490
      }
B
Brian Anderson 已提交
2491
      ty_rec(flds) => {
B
Brian Anderson 已提交
2492
        for flds.each |f| {
B
Brian Anderson 已提交
2493
            if !type_is_pod(cx, f.mt.ty) { result = false; }
P
Patrick Walton 已提交
2494
        }
B
Brian Anderson 已提交
2495
      }
B
Brian Anderson 已提交
2496
      ty_tup(elts) => {
2497
        for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
B
Brian Anderson 已提交
2498
      }
B
Brian Anderson 已提交
2499 2500
      ty_estr(vstore_fixed(_)) => result = true,
      ty_evec(mt, vstore_fixed(_)) | ty_unboxed_vec(mt) => {
2501 2502
        result = type_is_pod(cx, mt.ty);
      }
B
Brian Anderson 已提交
2503 2504
      ty_param(_) => result = false,
      ty_opaque_closure_ptr(_) => result = true,
2505 2506
      ty_struct(did, ref substs) => {
        result = vec::any(lookup_struct_fields(cx, did), |f| {
2507 2508 2509
            let fty = ty::lookup_item_type(cx, f.id);
            let sty = subst(cx, substs, fty.ty);
            type_is_pod(cx, sty)
2510
        });
2511
      }
2512

B
Brian Anderson 已提交
2513
      ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2514 2515 2516
        result = false;
      }

2517
      ty_infer(*) | ty_self(*) | ty_err => {
2518
        cx.sess.bug(~"non concrete type in type_is_pod");
2519
      }
P
Patrick Walton 已提交
2520 2521
    }

B
Brian Anderson 已提交
2522
    return result;
P
Patrick Walton 已提交
2523 2524
}

2525
pub fn type_is_enum(ty: t) -> bool {
2526
    match get(ty).sty {
B
Brian Anderson 已提交
2527 2528
      ty_enum(_, _) => return true,
      _ => return false
2529 2530 2531
    }
}

P
Patrick Walton 已提交
2532
// Whether a type is enum like, that is a enum type with only nullary
2533
// constructors
2534
pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2535
    match get(ty).sty {
2536
      ty_enum(did, _) => {
2537
        let variants = enum_variants(cx, did);
B
Brian Anderson 已提交
2538
        let some_n_ary = vec::any(*variants, |v| vec::len(v.args) > 0u);
B
Brian Anderson 已提交
2539
        return !some_n_ary;
2540
      }
B
Brian Anderson 已提交
2541
      _ => return false
2542 2543 2544
    }
}

2545
pub fn type_param(ty: t) -> Option<uint> {
2546
    match get(ty).sty {
B
Brian Anderson 已提交
2547
      ty_param(p) => return Some(p.idx),
B
Brian Anderson 已提交
2548
      _ => {/* fall through */ }
2549
    }
B
Brian Anderson 已提交
2550
    return None;
2551 2552
}

2553 2554
// Returns the type and mutability of *t.
//
2555 2556
// The parameter `explicit` indicates if this is an *explicit* dereference.
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
2557
pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
2558
    deref_sty(cx, &get(t).sty, explicit)
2559
}
2560

2561
pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
N
Niko Matsakis 已提交
2562
    match *sty {
B
Brian Anderson 已提交
2563
      ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
B
Brian Anderson 已提交
2564
        Some(mt)
2565 2566
      }

2567
      ty_ptr(mt) if explicit => {
B
Brian Anderson 已提交
2568
        Some(mt)
2569 2570
      }

N
Niko Matsakis 已提交
2571
      ty_enum(did, ref substs) => {
2572 2573 2574
        let variants = enum_variants(cx, did);
        if vec::len(*variants) == 1u && vec::len(variants[0].args) == 1u {
            let v_t = subst(cx, substs, variants[0].args[0]);
2575
            Some(mt {ty: v_t, mutbl: ast::m_imm})
2576
        } else {
B
Brian Anderson 已提交
2577
            None
2578 2579 2580
        }
      }

2581 2582
      ty_struct(did, ref substs) => {
        let fields = struct_fields(cx, did, substs);
2583 2584
        if fields.len() == 1 && fields[0].ident ==
                syntax::parse::token::special_idents::unnamed_field {
2585
            Some(mt {ty: fields[0].mt.ty, mutbl: ast::m_imm})
2586 2587 2588 2589 2590
        } else {
            None
        }
      }

B
Brian Anderson 已提交
2591
      _ => None
2592 2593 2594
    }
}

2595
pub fn type_autoderef(cx: ctxt, t: t) -> t {
2596
    let mut t = t;
2597
    loop {
2598
        match deref(cx, t, false) {
B
Brian Anderson 已提交
2599 2600
          None => return t,
          Some(mt) => t = mt.ty
2601 2602
        }
    }
2603 2604 2605
}

// Returns the type and mutability of t[i]
2606
pub fn index(cx: ctxt, t: t) -> Option<mt> {
2607
    index_sty(cx, &get(t).sty)
2608 2609
}

2610
pub fn index_sty(cx: ctxt, sty: &sty) -> Option<mt> {
N
Niko Matsakis 已提交
2611
    match *sty {
B
Brian Anderson 已提交
2612
      ty_evec(mt, _) => Some(mt),
2613
      ty_estr(_) => Some(mt {ty: mk_u8(cx), mutbl: ast::m_imm}),
B
Brian Anderson 已提交
2614
      _ => None
2615
    }
2616 2617
}

2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629
impl bound_region : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          ty::br_self => 0u8.iter_bytes(lsb0, f),

          ty::br_anon(ref idx) =>
          to_bytes::iter_bytes_2(&1u8, idx, lsb0, f),

          ty::br_named(ref ident) =>
          to_bytes::iter_bytes_2(&2u8, ident, lsb0, f),

          ty::br_cap_avoid(ref id, ref br) =>
2630 2631 2632 2633
          to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f),

          ty::br_fresh(ref x) =>
          to_bytes::iter_bytes_2(&4u8, x, lsb0, f)
2634 2635 2636
        }
    }
}
2637

2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651
impl Region : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          re_bound(ref br) =>
          to_bytes::iter_bytes_2(&0u8, br, lsb0, f),

          re_free(ref id, ref br) =>
          to_bytes::iter_bytes_3(&1u8, id, br, lsb0, f),

          re_scope(ref id) =>
          to_bytes::iter_bytes_2(&2u8, id, lsb0, f),

          re_infer(ref id) =>
          to_bytes::iter_bytes_2(&3u8, id, lsb0, f),
2652

2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671
          re_static => 4u8.iter_bytes(lsb0, f)
        }
    }
}

impl vstore : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          vstore_fixed(ref u) =>
          to_bytes::iter_bytes_2(&0u8, u, lsb0, f),

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

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

2673 2674 2675 2676 2677 2678 2679
impl substs : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
          to_bytes::iter_bytes_3(&self.self_r,
                                 &self.self_ty,
                                 &self.tps, lsb0, f)
    }
}
2680

2681 2682 2683 2684 2685 2686
impl mt : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
          to_bytes::iter_bytes_2(&self.ty,
                                 &self.mutbl, lsb0, f)
    }
}
2687

2688 2689 2690 2691 2692 2693
impl field : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
          to_bytes::iter_bytes_2(&self.ident,
                                 &self.mt, lsb0, f)
    }
}
2694

2695 2696 2697 2698 2699 2700
impl arg : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_2(&self.mode,
                               &self.ty, lsb0, f)
    }
}
2701

2702 2703
impl FnMeta : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
2704
        to_bytes::iter_bytes_5(&self.purity,
2705
                               &self.proto,
2706
                               &self.onceness,
2707 2708 2709 2710 2711
                               &self.region,
                               &self.bounds,
                               lsb0, f);
    }
}
2712

2713 2714 2715 2716 2717 2718 2719
impl FnSig : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_2(&self.inputs,
                               &self.output,
                               lsb0, f);
    }
}
2720

2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746
impl sty : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          ty_nil => 0u8.iter_bytes(lsb0, f),
          ty_bool => 1u8.iter_bytes(lsb0, f),

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

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

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

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

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

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

          ty_evec(ref mt, ref v) =>
          to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f),
2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757

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

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

          ty_rec(ref fs) =>
          to_bytes::iter_bytes_2(&11u8, fs, lsb0, f),

          ty_fn(ref ft) =>
2758
          to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784

          ty_self => 13u8.iter_bytes(lsb0, f),

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

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

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

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

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

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

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

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

2785
          ty_struct(ref did, ref substs) =>
2786 2787 2788 2789
          to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f),

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

          ty_err => 25u8.iter_bytes(lsb0, f)
2792 2793 2794 2795
        }
    }
}

2796
pub fn br_hashmap<V:Copy>() -> HashMap<bound_region, V> {
B
Brian Anderson 已提交
2797
    map::HashMap()
N
Niko Matsakis 已提交
2798 2799
}

2800
pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
P
Paul Stansifer 已提交
2801
    //io::println(fmt!("%?/%?", id, cx.node_types.size()));
2802
    match oldsmallintmap::find(*cx.node_types, id as uint) {
B
Brian Anderson 已提交
2803 2804
       Some(t) => t,
       None => cx.sess.bug(
2805
           fmt!("node_id_to_type: no type for node `%s`",
P
Paul Stansifer 已提交
2806
                ast_map::node_id_to_str(cx.items, id,
P
Paul Stansifer 已提交
2807
                                        cx.sess.parse_sess.interner)))
T
Tim Chevalier 已提交
2808
    }
2809 2810
}

2811
pub fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2812
    match cx.node_type_substs.find(id) {
B
Brian Anderson 已提交
2813 2814
      None => return ~[],
      Some(ts) => return ts
2815 2816 2817
    }
}

2818
fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
B
Brian Anderson 已提交
2819
    return cx.node_type_substs.contains_key(id);
2820 2821
}

2822
// Type accessors for substructures of types
2823
pub fn ty_fn_args(fty: t) -> ~[arg] {
2824
    match get(fty).sty {
2825
      ty_fn(ref f) => /*bad*/copy f.sig.inputs,
2826
      _ => die!(~"ty_fn_args() called on non-fn type")
2827 2828 2829
    }
}

2830
pub fn ty_fn_proto(fty: t) -> Proto {
2831
    match get(fty).sty {
2832
      ty_fn(ref f) => f.meta.proto,
2833
      _ => die!(~"ty_fn_proto() called on non-fn type")
M
Marijn Haverbeke 已提交
2834
    }
G
Graydon Hoare 已提交
2835 2836
}

2837
pub fn ty_fn_purity(fty: t) -> ast::purity {
2838
    match get(fty).sty {
2839
      ty_fn(ref f) => f.meta.purity,
2840
      _ => die!(~"ty_fn_purity() called on non-fn type")
2841 2842 2843
    }
}

2844
pub pure fn ty_fn_ret(fty: t) -> t {
2845
    match get(fty).sty {
2846
        ty_fn(ref f) => f.sig.output,
2847
        _ => die!(~"ty_fn_ret() called on non-fn type")
2848
    }
G
Graydon Hoare 已提交
2849 2850
}

2851
fn is_fn_ty(fty: t) -> bool {
2852
    match get(fty).sty {
2853 2854 2855 2856 2857
      ty_fn(_) => true,
      _ => false
    }
}

2858
pub pure fn ty_vstore(ty: t) -> vstore {
2859 2860 2861 2862 2863 2864 2865
    match get(ty).sty {
        ty_evec(_, vstore) => vstore,
        ty_estr(vstore) => vstore,
        ref s => fail fmt!("ty_vstore() called on invalid sty: %?", s)
    }
}

2866
pub fn ty_region(ty: t) -> Region {
2867
    match get(ty).sty {
2868
      ty_rptr(r, _) => r,
2869 2870 2871
      ty_evec(_, vstore_slice(r)) => r,
      ty_estr(vstore_slice(r)) => r,
      ref s => fail fmt!("ty_region() invoked on in appropriate ty: %?", (*s))
2872
    }
G
Graydon Hoare 已提交
2873 2874
}

2875
pub fn replace_fn_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895
    /*!
     *
     * Returns a new function type based on `fn_type` but returning a value of
     * type `ret_type` instead. */

    match ty::get(fn_type).sty {
        ty::ty_fn(ref fty) => {
            ty::mk_fn(tcx, FnTyBase {
                meta: fty.meta,
                sig: FnSig {output: ret_type, ..copy fty.sig}
            })
        }
        _ => {
            tcx.sess.bug(fmt!(
                "replace_fn_ret() invoked with non-fn-type: %s",
                ty_to_str(tcx, fn_type)));
        }
    }
}

2896
// Returns a vec of all the input and output types of fty.
2897
pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
2898
    vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
2899 2900
}

2901 2902
// Just checks whether it's a fn that returns bool,
// not its purity.
2903
pub fn is_pred_ty(fty: t) -> bool {
2904
    is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
2905 2906
}

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


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

2919

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

2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040
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);

    return match cx.adjustments.find(expr.id) {
        None => unadjusted_ty,

        Some(adj) => {
            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(
                            expr.span,
                            fmt!("The %uth autoderef failed: %s",
                                 i, ty_to_str(cx,
                                              adjusted_ty)));
                    }
                }
            }

            match adj.autoref {
                None => adjusted_ty,
                Some(ref autoref) => {
                    match autoref.kind {
                        AutoPtr => {
                            mk_rptr(cx, autoref.region,
                                    mt {ty: adjusted_ty,
                                        mutbl: autoref.mutbl})
                        }

                        AutoBorrowVec => {
                            borrow_vec(cx, expr, autoref, adjusted_ty)
                        }

                        AutoBorrowVecRef => {
                            adjusted_ty = borrow_vec(cx, expr, autoref,
                                                     adjusted_ty);
                            mk_rptr(cx, autoref.region,
                                    mt {ty: adjusted_ty, mutbl: ast::m_imm})
                        }

                        AutoBorrowFn => {
                            borrow_fn(cx, expr, autoref, adjusted_ty)
                        }
                    }
                }
            }
        }
    };

    fn borrow_vec(cx: ctxt, expr: @ast::expr,
                  autoref: &AutoRef, ty: ty::t) -> ty::t {
        match get(ty).sty {
            ty_evec(mt, _) => {
                ty::mk_evec(cx, mt {ty: mt.ty, mutbl: autoref.mutbl},
                            vstore_slice(autoref.region))
            }

            ty_estr(_) => {
                ty::mk_estr(cx, vstore_slice(autoref.region))
            }

            ref s => {
                cx.sess.span_bug(
                    expr.span,
                    fmt!("borrow-vec associated with bad sty: %?",
                         s));
            }
        }
    }

    fn borrow_fn(cx: ctxt, expr: @ast::expr,
                 autoref: &AutoRef, ty: ty::t) -> ty::t {
        match get(ty).sty {
            ty_fn(ref fty) => {
                ty::mk_fn(cx, FnTyBase {meta: FnMeta {proto: ProtoBorrowed,
                                                      region: autoref.region,
                                                      ..copy fty.meta},
                                        sig: copy fty.sig})
            }

            ref s => {
                cx.sess.span_bug(
                    expr.span,
                    fmt!("borrow-fn associated with bad sty: %?",
                         s));
            }
        }
    }
}

3041 3042 3043
pub fn expr_ty_params_and_ty(cx: ctxt,
                             expr: @ast::expr)
                          -> {params: ~[t], ty: t} {
B
Brian Anderson 已提交
3044
    return {params: node_id_to_type_params(cx, expr.id),
M
Marijn Haverbeke 已提交
3045
         ty: node_id_to_type(cx, expr.id)};
3046 3047
}

3048
pub fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
B
Brian Anderson 已提交
3049
    return node_id_has_type_params(cx, expr.id);
3050 3051
}

3052 3053
pub fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
                          id: ast::node_id)
B
Brian Anderson 已提交
3054
    -> Option<@~[param_bounds]> {
3055 3056 3057
    do method_map.find(id).map |method| {
        match method.origin {
          typeck::method_static(did) => {
3058 3059
            // n.b.: When we encode impl methods, the bounds
            // that we encode include both the impl bounds
3060 3061 3062
            // and then the method bounds themselves...
            ty::lookup_item_type(tcx, did).bounds
          }
3063 3064 3065
          typeck::method_param(typeck::method_param {
              trait_id: trt_id,
              method_num: n_mth, _}) |
3066
          typeck::method_trait(trt_id, n_mth, _) |
3067 3068
          typeck::method_self(trt_id, n_mth) |
          typeck::method_super(trt_id, n_mth) => {
3069 3070 3071 3072 3073
            // ...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.
            let trt_bounds =
                ty::lookup_item_type(tcx, trt_id).bounds;
3074 3075
            let mth = /*bad*/copy ty::trait_methods(tcx, trt_id)[n_mth];
            @(vec::append(/*bad*/copy *trt_bounds, *mth.tps))
3076 3077 3078 3079 3080
          }
        }
    }
}

3081 3082 3083 3084 3085 3086 3087 3088 3089 3090
fn resolve_expr(tcx: ctxt, expr: @ast::expr) -> ast::def {
    match tcx.def_map.find(expr.id) {
        Some(def) => def,
        None => {
            tcx.sess.span_bug(expr.span, fmt!(
                "No def-map entry for expr %?", expr.id));
        }
    }
}

3091 3092 3093
pub fn expr_is_lval(tcx: ctxt,
                    method_map: typeck::method_map,
                    e: @ast::expr) -> bool {
3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104
    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.
3105
pub enum ExprKind {
3106 3107 3108 3109 3110 3111
    LvalueExpr,
    RvalueDpsExpr,
    RvalueDatumExpr,
    RvalueStmtExpr
}

3112 3113 3114
pub fn expr_kind(tcx: ctxt,
                 method_map: typeck::method_map,
                 expr: @ast::expr) -> ExprKind {
3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128
    if method_map.contains_key(expr.id) {
        // 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 {
        ast::expr_path(*) => {
            match resolve_expr(tcx, expr) {
                ast::def_fn(*) | ast::def_static_method(*) |
3129
                ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155

                // 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,

                move def => {
                    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(*) |
3156
        ast::expr_method_call(*) |
3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168
        ast::expr_rec(*) |
        ast::expr_struct(*) |
        ast::expr_tup(*) |
        ast::expr_if(*) |
        ast::expr_match(*) |
        ast::expr_fn(*) |
        ast::expr_fn_block(*) |
        ast::expr_loop_body(*) |
        ast::expr_do_body(*) |
        ast::expr_block(*) |
        ast::expr_copy(*) |
        ast::expr_repeat(*) |
3169
        ast::expr_lit(@ast::spanned {node: lit_str(_), _}) |
3170
        ast::expr_vstore(_, ast::expr_vstore_slice) |
3171
        ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3172
        ast::expr_vstore(_, ast::expr_vstore_fixed(_)) |
3173 3174 3175 3176 3177
        ast::expr_vec(*) => {
            RvalueDpsExpr
        }

        ast::expr_cast(*) => {
3178
            match oldsmallintmap::find(*tcx.node_types, expr.id as uint) {
3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220
                Some(t) => {
                    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_fail(*) |
        ast::expr_assert(*) |
        ast::expr_while(*) |
        ast::expr_loop(*) |
        ast::expr_assign(*) |
        ast::expr_swap(*) |
        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(*) |
3221
        ast::expr_vstore(_, ast::expr_vstore_box) |
3222
        ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3223
        ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3224 3225 3226
            RvalueDatumExpr
        }

3227 3228
        ast::expr_paren(e) => expr_kind(tcx, method_map, e),

3229 3230 3231 3232 3233
        ast::expr_mac(*) => {
            tcx.sess.span_bug(
                expr.span,
                ~"macro expression remains after expansion");
        }
M
Marijn Haverbeke 已提交
3234 3235 3236
    }
}

3237
pub fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3238
    match s.node {
B
Brian Anderson 已提交
3239
      ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
B
Brian Anderson 已提交
3240
        return id;
3241
      }
3242
      ast::stmt_mac(*) => die!(~"unexpanded macro in trans")
3243 3244 3245
    }
}

3246
pub fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3247
    let mut i = 0u;
B
Brian Anderson 已提交
3248 3249
    for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
    return None;
3250 3251
}

3252 3253
pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
                     -> uint {
3254 3255 3256 3257 3258 3259 3260 3261
    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 `%?`",
        tcx.sess.str_of(id),
        fields.map(|f| tcx.sess.str_of(f.ident))));
}

3262
pub fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field {
3263
    match vec::find(get_fields(rec_ty), |f| f.ident == id) {
B
Brian Anderson 已提交
3264
      Some(f) => f,
3265
      // Do we only call this when we know the field is legit?
3266
      None => die!(fmt!("get_field: ty doesn't have a field %s",
3267
                         tcx.sess.str_of(id)))
T
Tim Chevalier 已提交
3268 3269 3270
    }
}

3271
pub fn get_fields(rec_ty:t) -> ~[field] {
3272
    match /*bad*/copy get(rec_ty).sty {
3273 3274
      ty_rec(fields) => fields,
      // Can we check at the caller?
3275
      _ => die!(~"get_fields: not a record type")
3276 3277 3278
    }
}

3279
pub fn method_idx(id: ast::ident, meths: &[method]) -> Option<uint> {
3280
    let mut i = 0u;
B
Brian Anderson 已提交
3281 3282
    for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; }
    return None;
3283 3284
}

3285 3286 3287
/// 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.
3288
pub fn param_tys_in_type(ty: t) -> ~[param_ty] {
3289 3290
    let mut rslt = ~[];
    do walk_ty(ty) |ty| {
3291
        match get(ty).sty {
B
Brian Anderson 已提交
3292
          ty_param(p) => {
3293
            rslt.push(p);
3294
          }
B
Brian Anderson 已提交
3295
          _ => ()
3296 3297 3298 3299 3300
        }
    }
    rslt
}

3301
pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3302 3303
    // Returns a vec of all the type variables occurring in `ty`. It may
    // contain duplicates.  (Integral type vars aren't counted.)
3304
    fn vars_in_type(ty: t) -> ~[TyVid] {
3305
        let mut rslt = ~[];
B
Brian Anderson 已提交
3306
        do walk_ty(ty) |ty| {
3307
            match get(ty).sty {
3308
              ty_infer(TyVar(v)) => rslt.push(v),
B
Brian Anderson 已提交
3309 3310
              _ => ()
            }
3311 3312 3313 3314
        }
        rslt
    }

3315
    // Fast path
B
Brian Anderson 已提交
3316
    if !type_needs_infer(rt) { return; }
B
Brian Anderson 已提交
3317

T
Tim Chevalier 已提交
3318
    // Occurs check!
N
Niko Matsakis 已提交
3319
    if vec::contains(vars_in_type(rt), &vid) {
T
Tim Chevalier 已提交
3320 3321 3322
            // 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.
3323
            tcx.sess.span_fatal
3324
                (sp, ~"type inference failed because I \
3325
                     could not find a type\n that's both of the form "
3326 3327
                 + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
                 ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
3328
                 ~" - such a type would have to be infinitely large.");
3329
    }
T
Tim Chevalier 已提交
3330
}
3331

3332 3333
// Maintains a little union-set tree for inferred modes.  `canon()` returns
// the current head value for `m0`.
B
Brian Anderson 已提交
3334
fn canon<T:Copy cmp::Eq>(tbl: HashMap<ast::node_id, ast::inferable<T>>,
3335
                         +m0: ast::inferable<T>) -> ast::inferable<T> {
3336 3337
    match m0 {
      ast::infer(id) => match tbl.find(id) {
B
Brian Anderson 已提交
3338
        None => m0,
3339 3340
        Some(ref m1) => {
            let cm1 = canon(tbl, (*m1));
3341
            // path compression:
3342
            if cm1 != (*m1) { tbl.insert(id, cm1); }
3343 3344
            cm1
        }
3345
      },
B
Brian Anderson 已提交
3346
      _ => m0
3347 3348 3349 3350 3351
    }
}

// Maintains a little union-set tree for inferred modes.  `resolve_mode()`
// returns the current head value for `m0`.
3352
pub fn canon_mode(cx: ctxt, m0: ast::mode) -> ast::mode {
3353 3354 3355 3356 3357
    canon(cx.inferred_modes, m0)
}

// Returns the head value for mode, failing if `m` was a infer(_) that
// was never inferred.  This should be safe for use after typeck.
3358
pub fn resolved_mode(cx: ctxt, m: ast::mode) -> ast::rmode {
3359
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3360
      ast::infer(_) => {
P
Paul Stansifer 已提交
3361
        cx.sess.bug(fmt!("mode %? was never resolved", m));
3362
      }
B
Brian Anderson 已提交
3363
      ast::expl(m0) => m0
3364 3365 3366
    }
}

3367
pub fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { resolved_mode(cx, a.mode) }
3368 3369

// Unifies `m1` and `m2`.  Returns unified value or failure code.
3370 3371
pub fn unify_mode(cx: ctxt, modes: expected_found<ast::mode>)
               -> Result<ast::mode, type_err> {
3372 3373
    let m1 = modes.expected;
    let m2 = modes.found;
3374
    match (canon_mode(cx, m1), canon_mode(cx, m2)) {
B
Brian Anderson 已提交
3375
      (m1, m2) if (m1 == m2) => {
3376
        result::Ok(m1)
3377
      }
E
Erick Tryzelaar 已提交
3378
      (ast::infer(_), ast::infer(id2)) => {
3379
        cx.inferred_modes.insert(id2, m1);
3380
        result::Ok(m1)
3381
      }
B
Brian Anderson 已提交
3382
      (ast::infer(id), m) | (m, ast::infer(id)) => {
3383
        cx.inferred_modes.insert(id, m);
3384
        result::Ok(m1)
3385
      }
E
Erick Tryzelaar 已提交
3386
      (_, _) => {
3387
        result::Err(terr_mode_mismatch(modes))
3388 3389 3390 3391 3392 3393
      }
    }
}

// If `m` was never unified, unifies it with `m_def`.  Returns the final value
// for `m`.
3394
pub fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
3395
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3396
      ast::infer(id) => {
3397 3398
        cx.inferred_modes.insert(id, ast::expl(m_def));
      }
B
Brian Anderson 已提交
3399
      ast::expl(_) => ()
3400 3401 3402
    }
}

3403
pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3404
    match get(t).sty {
N
Niko Matsakis 已提交
3405
      ty_nil | ty_bot | ty_bool | ty_int(_) |
M
Michael Sullivan 已提交
3406
      ty_uint(_) | ty_float(_) | ty_estr(_) |
B
Brian Anderson 已提交
3407
      ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
3408
        ::util::ppaux::ty_to_str(cx, t)
N
Niko Matsakis 已提交
3409 3410
      }

P
Paul Stansifer 已提交
3411
      ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3412 3413 3414 3415 3416 3417 3418 3419
      ty_box(_) => ~"@-ptr",
      ty_uniq(_) => ~"~-ptr",
      ty_evec(_, _) => ~"vector",
      ty_unboxed_vec(_) => ~"unboxed vector",
      ty_ptr(_) => ~"*-ptr",
      ty_rptr(_, _) => ~"&-ptr",
      ty_rec(_) => ~"record",
      ty_fn(_) => ~"fn",
P
Paul Stansifer 已提交
3420
      ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3421
      ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3422
      ty_tup(_) => ~"tuple",
3423 3424
      ty_infer(TyVar(_)) => ~"inferred type",
      ty_infer(IntVar(_)) => ~"integral variable",
3425
      ty_infer(FloatVar(_)) => ~"floating-point variable",
B
Brian Anderson 已提交
3426
      ty_param(_) => ~"type parameter",
3427 3428
      ty_self => ~"self",
      ty_err => ~"type error"
N
Niko Matsakis 已提交
3429 3430 3431
    }
}

3432
pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3433 3434 3435 3436 3437 3438 3439 3440 3441
    /*!
     *
     * 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. */

3442
    fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3443 3444 3445
        match k {
            terr_vec => ~"[]",
            terr_str => ~"str",
3446 3447
            terr_fn => ~"fn",
            terr_trait => ~"trait"
3448
        }
3449 3450
    }

N
Niko Matsakis 已提交
3451
    match *err {
3452 3453 3454
        terr_mismatch => ~"types differ",
        terr_purity_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3455
                 values.expected.to_str(), values.found.to_str())
3456
        }
3457 3458
        terr_onceness_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3459
                 values.expected.to_str(), values.found.to_str())
3460
        }
3461 3462
        terr_proto_mismatch(values) => {
            fmt!("expected %s closure, found %s closure",
3463 3464
                 proto_ty_to_str(cx, values.expected, false),
                 proto_ty_to_str(cx, values.found, false))
3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497
        }
        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`",
                 cx.sess.str_of(values.expected),
                 cx.sess.str_of(values.found))
        }
        terr_arg_count => ~"incorrect number of function parameters",
        terr_mode_mismatch(values) => {
            fmt!("expected argument mode %s, but found %s",
3498 3499
                 pprust::mode_to_str(values.expected),
                 pprust::mode_to_str(values.found))
3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519
        }
        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))
        }
3520
        terr_vstores_differ(k, ref values) => {
3521 3522
            fmt!("%s storage differs: expected %s but found %s",
                 terr_vstore_kind_to_str(k),
3523 3524
                 vstore_to_str(cx, (*values).expected),
                 vstore_to_str(cx, (*values).found))
3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537
        }
        terr_in_field(err, fname) => {
            fmt!("in field `%s`, %s", cx.sess.str_of(fname),
                 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))
        }
        terr_self_substs => {
            ~"inconsistent self substitution" // XXX this is more of a bug
        }
3538
        terr_integer_as_char => {
3539
            fmt!("expected an integral type but found char")
3540
        }
3541 3542 3543 3544 3545 3546 3547 3548 3549
        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())
3550
        }
3551 3552 3553
    }
}

3554
pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570
    match *err {
        terr_regions_does_not_outlive(subregion, superregion) => {
            note_and_explain_region(cx, ~"", subregion, ~"...");
            note_and_explain_region(cx, ~"...does not necessarily outlive ",
                                    superregion, ~"");
        }
        terr_regions_not_same(region1, region2) => {
            note_and_explain_region(cx, ~"", region1, ~"...");
            note_and_explain_region(cx, ~"...is not the same lifetime as ",
                                    region2, ~"");
        }
        terr_regions_no_overlap(region1, region2) => {
            note_and_explain_region(cx, ~"", region1, ~"...");
            note_and_explain_region(cx, ~"...does not overlap ",
                                    region2, ~"");
        }
3571 3572 3573 3574 3575 3576 3577 3578 3579 3580
        terr_regions_insufficiently_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
                                    ~"concrete lifetime that was found is ",
                                    conc_region, ~"");
        }
        terr_regions_overly_polymorphic(_, conc_region) => {
            note_and_explain_region(cx,
                                    ~"expected concrete lifetime is ",
                                    conc_region, ~"");
        }
3581 3582 3583 3584
        _ => {}
    }
}

3585
pub fn def_has_ty_params(def: ast::def) -> bool {
3586
    match def {
3587
      ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
B
Brian Anderson 已提交
3588 3589
        => true,
      _ => false
3590 3591 3592
    }
}

3593
pub fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
3594
    cx.trait_method_cache.insert(ast_util::local_def(id), ms);
3595 3596
}

3597
pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3598 3599
    if is_local(id) {
        match cx.items.find(id.node) {
3600
            Some(ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
3601 3602 3603
                        node: item_trait(_, _, ref ms),
                        _
                    }, _)) =>
3604
                match ast_util::split_trait_methods((/*bad*/copy *ms)) {
3605
                   (_, p) => p.map(|method| method.ident)
3606
                },
3607
            _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3608 3609
                                  id))
        }
3610
    } else {
3611
        csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3612 3613 3614
    }
}

3615 3616 3617
pub fn trait_supertraits(cx: ctxt,
                         id: ast::def_id)
                      -> @~[InstantiatedTraitRef] {
3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632
    // Check the cache.
    match cx.supertraits.find(id) {
        Some(instantiated_trait_info) => { return instantiated_trait_info; }
        None => {}  // Continue.
    }

    // Not in the cache. It had better be in the metadata, which means it
    // shouldn't be local.
    assert !is_local(id);

    // Get the supertraits out of the metadata and create the
    // InstantiatedTraitRef for each.
    let result = dvec::DVec();
    for csearch::get_supertraits(cx, id).each |trait_type| {
        match get(*trait_type).sty {
3633
            ty_trait(def_id, ref substs, _) => {
3634 3635
                result.push(InstantiatedTraitRef {
                    def_id: def_id,
3636
                    tpt: { substs: (/*bad*/copy *substs), ty: *trait_type }
3637 3638 3639 3640 3641 3642 3643 3644 3645
                });
            }
            _ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
        }
    }

    // Unwrap and return the result.
    return @dvec::unwrap(move result);
}
3646

3647
pub fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
3648
    match cx.trait_method_cache.find(id) {
3649
      // Local traits are supposed to have been added explicitly.
B
Brian Anderson 已提交
3650
      Some(ms) => ms,
3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662
      _ => {
        // If the lookup in trait_method_cache fails, assume that the trait
        // method we're trying to look up is in a different crate, and look
        // for it there.
        assert id.crate != ast::local_crate;
        let result = csearch::get_trait_methods(cx, id);

        // Store the trait method in the local trait_method_cache so that
        // future lookups succeed.
        cx.trait_method_cache.insert(id, result);
        result
      }
3663 3664
    }
}
3665

3666 3667 3668
/*
  Could this return a list of (def_id, substs) pairs?
 */
3669
pub fn impl_traits(cx: ctxt, id: ast::def_id, vstore: vstore) -> ~[t] {
3670 3671 3672
    fn vstoreify(cx: ctxt, ty: t, vstore: vstore) -> t {
        match ty::get(ty).sty {
            ty::ty_trait(_, _, trait_vstore) if vstore == trait_vstore => ty,
P
Patrick Walton 已提交
3673
            ty::ty_trait(did, ref substs, _) => {
3674
                mk_trait(cx, did, (/*bad*/copy *substs), vstore)
P
Patrick Walton 已提交
3675
            }
3676 3677 3678 3679
            _ => cx.sess.bug(~"impl_traits: not a trait")
        }
    }

3680
    if id.crate == ast::local_crate {
P
Paul Stansifer 已提交
3681
        debug!("(impl_traits) searching for trait impl %?", id);
3682
        match cx.items.find(id.node) {
3683
           Some(ast_map::node_item(@ast::item {
3684
                        node: ast::item_impl(_, opt_trait, _, _),
3685
                        _},
B
Brian Anderson 已提交
3686
                    _)) => {
3687

B
Brian Anderson 已提交
3688
               do option::map_default(&opt_trait, ~[]) |trait_ref| {
3689 3690 3691
                       ~[vstoreify(cx,
                                   node_id_to_type(cx, trait_ref.ref_id),
                                   vstore)]
3692
                   }
3693
           }
B
Brian Anderson 已提交
3694
           _ => ~[]
3695
        }
3696
    } else {
3697 3698
        vec::map(csearch::get_impl_traits(cx, id),
                 |x| vstoreify(cx, *x, vstore))
3699 3700 3701
    }
}

3702
pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3703
    match get(ty).sty {
3704
      ty_trait(id, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
B
Brian Anderson 已提交
3705
      _ => None
3706 3707 3708
    }
}

3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720
/// Returns the def ID of the constructor for the given tuple-like struct, or
/// None if the struct is not tuple-like. Fails if the given def ID does not
/// refer to a struct at all.
fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option<ast::def_id> {
    if struct_did.crate != ast::local_crate {
        // XXX: Cross-crate functionality.
        cx.sess.unimpl(~"constructor ID of cross-crate tuple structs");
    }

    match cx.items.find(struct_did.node) {
        Some(ast_map::node_item(item, _)) => {
            match item.node {
3721
                ast::item_struct(struct_def, _) => {
3722 3723 3724 3725 3726 3727 3728 3729 3730 3731
                    struct_def.ctor_id.map(|ctor_id|
                        ast_util::local_def(*ctor_id))
                }
                _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
            }
        }
        _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
    }
}

3732
// Enum information
3733
pub struct VariantInfo_ {
3734 3735 3736 3737 3738 3739 3740 3741
    args: ~[t],
    ctor_ty: t,
    name: ast::ident,
    id: ast::def_id,
    disr_val: int,
    vis: visibility
}

3742
pub type VariantInfo = @VariantInfo_;
M
Marijn Haverbeke 已提交
3743

3744 3745 3746 3747
pub fn substd_enum_variants(cx: ctxt,
                            id: ast::def_id,
                            substs: &substs)
                         -> ~[VariantInfo] {
B
Brian Anderson 已提交
3748 3749
    do vec::map(*enum_variants(cx, id)) |variant_info| {
        let substd_args = vec::map(variant_info.args,
3750
                                   |aty| subst(cx, substs, *aty));
3751

3752
        let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3753

3754
        @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
3755
                      ../*bad*/copy **variant_info}
3756 3757 3758
    }
}

3759
pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
P
Paul Stansifer 已提交
3760
    ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3761 3762
}

3763
pub enum DtorKind {
3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780
    NoDtor,
    LegacyDtor(def_id),
    TraitDtor(def_id)
}

impl DtorKind {
    pure fn is_not_present(&const self) -> bool {
        match *self {
            NoDtor => true,
            _ => false
        }
    }
    pure fn is_present(&const self) -> bool {
        !self.is_not_present()
    }
}

3781
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
3782
   Otherwise return none. */
3783
pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
3784
    match cx.destructor_for_type.find(struct_id) {
3785
        Some(method_def_id) => return TraitDtor(method_def_id),
3786 3787 3788
        None => {}  // Continue.
    }

3789 3790
    if is_local(struct_id) {
       match cx.items.find(struct_id.node) {
3791
           Some(ast_map::node_item(@ast::item {
3792 3793 3794
               node: ast::item_struct(@ast::struct_def { dtor: Some(ref dtor),
                                                         _ },
                                      _),
3795 3796
               _
           }, _)) =>
3797
               LegacyDtor(local_def((*dtor).node.id)),
3798
           _ =>
3799
               NoDtor
3800 3801 3802
       }
    }
    else {
3803
      match csearch::struct_dtor(cx.sess.cstore, struct_id) {
3804 3805 3806
        None => NoDtor,
        Some(did) => LegacyDtor(did),
      }
3807 3808 3809
    }
}

3810
pub fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
3811
    ty_dtor(cx, struct_id).is_present()
3812 3813
}

3814
pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
3815 3816 3817 3818
    if id.crate != ast::local_crate {
        csearch::get_item_path(cx, id)
    } else {
        let node = cx.items.get(id.node);
3819
        match node {
B
Brian Anderson 已提交
3820
          ast_map::node_item(item, path) => {
3821
            let item_elt = match item.node {
B
Brian Anderson 已提交
3822
              item_mod(_) | item_foreign_mod(_) => {
3823 3824
                ast_map::path_mod(item.ident)
              }
B
Brian Anderson 已提交
3825
              _ => {
3826 3827 3828
                ast_map::path_name(item.ident)
              }
            };
3829
            vec::append_one(/*bad*/copy *path, item_elt)
3830 3831
          }

B
Brian Anderson 已提交
3832
          ast_map::node_foreign_item(nitem, _, path) => {
3833 3834
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(nitem.ident))
3835 3836
          }

B
Brian Anderson 已提交
3837
          ast_map::node_method(method, _, path) => {
3838 3839
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
3840
          }
B
Brian Anderson 已提交
3841
          ast_map::node_trait_method(trait_method, _, path) => {
3842
            let method = ast_util::trait_method_to_ty_method(*trait_method);
3843 3844
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
3845
          }
3846

3847
          ast_map::node_variant(ref variant, _, path) => {
3848
            vec::append_one(vec::init(*path),
3849
                            ast_map::path_name((*variant).node.name))
3850 3851
          }

B
Brian Anderson 已提交
3852
          ast_map::node_dtor(_, _, _, path) => {
3853
            vec::append_one(/*bad*/copy *path, ast_map::path_name(
P
Paul Stansifer 已提交
3854
                syntax::parse::token::special_idents::literally_dtor))
T
Tim Chevalier 已提交
3855 3856
          }

3857
          ast_map::node_struct_ctor(_, item, path) => {
3858
            vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
3859 3860
          }

3861 3862
          ast_map::node_stmt(*) | ast_map::node_expr(*) |
          ast_map::node_arg(*) | ast_map::node_local(*) |
3863
          ast_map::node_block(*) => {
P
Paul Stansifer 已提交
3864
            cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3865 3866 3867 3868 3869
          }
        }
    }
}

3870
pub fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3871
    enum_variants(cx, id).len() == 1
3872 3873
}

3874
pub fn type_is_empty(cx: ctxt, t: t) -> bool {
3875
    match ty::get(t).sty {
B
Brian Anderson 已提交
3876 3877
       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
       _ => false
3878 3879 3880
     }
}

3881
pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3882
    match cx.enum_var_cache.find(id) {
B
Brian Anderson 已提交
3883
      Some(variants) => return variants,
B
Brian Anderson 已提交
3884
      _ => { /* fallthrough */ }
3885
    }
3886

3887
    let result = if ast::local_crate != id.crate {
3888
        @csearch::get_enum_variants(cx, id)
3889
    } else {
3890 3891 3892 3893 3894
        /*
          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
         */
3895
        match cx.items.get(id.node) {
3896
          ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
3897 3898 3899
                    node: ast::item_enum(ref enum_definition, _),
                    _
                }, _) => {
3900
            let variants = /*bad*/copy (*enum_definition).variants;
3901
            let mut disr_val = -1;
B
Brian Anderson 已提交
3902
            @vec::map(variants, |variant| {
3903
                match variant.node.kind {
3904
                    ast::tuple_variant_kind(ref args) => {
3905 3906
                        let ctor_ty = node_id_to_type(cx, variant.node.id);
                        let arg_tys = {
3907
                            if args.len() > 0u {
3908 3909 3910 3911 3912 3913
                                ty_fn_args(ctor_ty).map(|a| a.ty)
                            } else {
                                ~[]
                            }
                        };
                        match variant.node.disr_expr {
B
Brian Anderson 已提交
3914
                          Some (ex) => {
3915 3916 3917 3918 3919 3920 3921 3922
                            disr_val = match const_eval::eval_const_expr(cx,
                                                                         ex) {
                              const_eval::const_int(val) => val as int,
                              _ => cx.sess.bug(~"tag_variants: bad disr expr")
                            }
                          }
                          _ => disr_val += 1
                        }
3923
                        @VariantInfo_{args: arg_tys,
3924 3925 3926
                          ctor_ty: ctor_ty,
                          name: variant.node.name,
                          id: ast_util::local_def(variant.node.id),
3927 3928
                          disr_val: disr_val,
                          vis: variant.node.vis
3929
                         }
3930
                    }
3931
                    ast::struct_variant_kind(_) => {
3932
                        die!(~"struct variant kinds unimpl in enum_variants")
3933 3934
                    }
                    ast::enum_variant_kind(_) => {
3935
                        die!(~"enum variant kinds unimpl in enum_variants")
3936
                    }
3937
                }
3938
            })
M
Marijn Haverbeke 已提交
3939
          }
B
Brian Anderson 已提交
3940
          _ => cx.sess.bug(~"tag_variants: id not bound to an enum")
3941
        }
3942
    };
3943
    cx.enum_var_cache.insert(id, result);
3944
    result
3945 3946
}

3947

P
Patrick Walton 已提交
3948
// Returns information about the enum variant with the given ID:
3949 3950 3951 3952
pub fn enum_variant_with_id(cx: ctxt,
                            enum_id: ast::def_id,
                            variant_id: ast::def_id)
                         -> VariantInfo {
3953
    let variants = enum_variants(cx, enum_id);
3954 3955
    let mut i = 0;
    while i < variants.len() {
B
Brian Anderson 已提交
3956
        let variant = variants[i];
3957
        if variant.id == variant_id { return variant; }
3958
        i += 1;
3959
    }
3960
    cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
3961 3962
}

3963

3964 3965
// 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.
3966 3967 3968
pub fn lookup_item_type(cx: ctxt,
                        did: ast::def_id)
                     -> ty_param_bounds_and_ty {
3969
    match cx.tcache.find(did) {
3970
      Some(tpt) => {
3971 3972
        // The item is in this crate. The caller should have added it to the
        // type cache already
3973 3974 3975
        return tpt;
      }
      None => {
3976
        assert did.crate != ast::local_crate;
M
Marijn Haverbeke 已提交
3977 3978
        let tyt = csearch::get_type(cx, did);
        cx.tcache.insert(did, tyt);
B
Brian Anderson 已提交
3979
        return tyt;
M
Marijn Haverbeke 已提交
3980
      }
3981
    }
T
Tim Chevalier 已提交
3982 3983
}

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

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

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

4055
pure fn is_public(f: field_ty) -> bool {
4056 4057 4058 4059 4060
    // XXX: This is wrong.
    match f.vis {
        public | inherited => true,
        private => false
    }
4061 4062
}

4063
fn struct_field_tys(fields: ~[@struct_field]) -> ~[field_ty] {
4064
    do fields.map |field| {
4065 4066
        match field.node.kind {
            named_field(ident, mutability, visibility) => {
4067 4068 4069 4070 4071 4072
                field_ty {
                    ident: ident,
                    id: ast_util::local_def(field.node.id),
                    vis: visibility,
                    mutability: mutability,
                }
4073
            }
4074
            unnamed_field => {
4075 4076 4077 4078 4079 4080 4081
                field_ty {
                    ident:
                        syntax::parse::token::special_idents::unnamed_field,
                    id: ast_util::local_def(field.node.id),
                    vis: ast::public,
                    mutability: ast::struct_immutable,
                }
4082
            }
4083
        }
T
Tim Chevalier 已提交
4084
    }
T
Tim Chevalier 已提交
4085 4086
}

4087 4088
// Return a list of fields corresponding to the struct's items
// (as if the struct was a record). trans uses this
4089
// Takes a list of substs with which to instantiate field types
4090 4091 4092
// Keep in mind that this function reports that all fields are
// mutable, regardless of how they were declared. It's meant to
// be used in trans.
4093 4094 4095 4096
pub fn struct_mutable_fields(cx: ctxt,
                             did: ast::def_id,
                             substs: &substs)
                          -> ~[field] {
4097
    struct_item_fields(cx, did, substs, |_mt| m_mutbl)
4098 4099
}

4100
// Same as struct_mutable_fields, but doesn't change
4101
// mutability.
4102 4103 4104 4105
pub fn struct_fields(cx: ctxt,
                     did: ast::def_id,
                     substs: &substs)
                  -> ~[field] {
4106 4107 4108
    struct_item_fields(cx, did, substs, |mt| match mt {
      struct_mutable => m_mutbl,
        struct_immutable => m_imm })
4109 4110 4111
}


4112
fn struct_item_fields(cx:ctxt,
N
Niko Matsakis 已提交
4113 4114
                     did: ast::def_id,
                     substs: &substs,
4115
                     frob_mutability: fn(struct_mutability) -> mutability)
4116
    -> ~[field] {
4117
    do lookup_struct_fields(cx, did).map |f| {
G
Graydon Hoare 已提交
4118
       // consider all instance vars mut, because the
T
Tim Chevalier 已提交
4119
       // constructor may mutate all vars
4120
       field {
4121 4122 4123 4124 4125 4126
           ident: f.ident,
            mt: mt {
                ty: lookup_field_type(cx, did, f.id, substs),
                mutbl: frob_mutability(f.mutability)
            }
        }
T
Tim Chevalier 已提交
4127 4128 4129
    }
}

4130
pub fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
M
Marijn Haverbeke 已提交
4131 4132 4133 4134
    const tycat_other: int = 0;
    const tycat_bool: int = 1;
    const tycat_int: int = 2;
    const tycat_float: int = 3;
M
Michael Sullivan 已提交
4135 4136
    const tycat_struct: int = 4;
    const tycat_bot: int = 5;
M
Marijn Haverbeke 已提交
4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147

    const opcat_add: int = 0;
    const opcat_sub: int = 1;
    const opcat_mult: int = 2;
    const opcat_shift: int = 3;
    const opcat_rel: int = 4;
    const opcat_eq: int = 5;
    const opcat_bit: int = 6;
    const opcat_logic: int = 7;

    fn opcat(op: ast::binop) -> int {
4148
        match op {
B
Brian Anderson 已提交
4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166
          ast::add => opcat_add,
          ast::subtract => opcat_sub,
          ast::mul => opcat_mult,
          ast::div => opcat_mult,
          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 已提交
4167 4168 4169
        }
    }

4170
    fn tycat(ty: t) -> int {
4171
        match get(ty).sty {
B
Brian Anderson 已提交
4172
          ty_bool => tycat_bool,
4173
          ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4174
          ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
B
Brian Anderson 已提交
4175 4176 4177
          ty_rec(_) | ty_tup(_) | ty_enum(_, _) => tycat_struct,
          ty_bot => tycat_bot,
          _ => tycat_other
M
Marijn Haverbeke 已提交
4178 4179 4180 4181 4182
        }
    }

    const t: bool = true;
    const f: bool = false;
4183

4184
    let tbl = ~[
4185 4186 4187
    /*.          add,     shift,   bit
      .             sub,     rel,     logic
      .                mult,    eq,         */
4188
    /*other*/   ~[f, f, f, f, f, f, f, f],
4189 4190 4191
    /*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],
4192 4193
    /*bot*/     ~[f, f, f, f, f, f, f, f],
    /*struct*/  ~[t, t, t, t, f, f, t, t]];
B
Brian Anderson 已提交
4194

B
Brian Anderson 已提交
4195
    return tbl[tycat(ty)][opcat(op)];
4196 4197
}

4198
pub fn ty_params_to_tys(tcx: ty::ctxt, tps: ~[ast::ty_param]) -> ~[t] {
B
Brian Anderson 已提交
4199
    vec::from_fn(tps.len(), |i| {
4200 4201 4202
                ty::mk_param(tcx, i, ast_util::local_def(tps[i].id))
        })
}
4203

4204
/// Returns an equivalent type with all the typedefs and self regions removed.
4205
pub fn normalize_ty(cx: ctxt, t: t) -> t {
4206
    fn normalize_mt(cx: ctxt, mt: mt) -> mt {
4207
        mt { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
4208 4209 4210 4211 4212 4213 4214 4215
    }
    fn normalize_vstore(vstore: vstore) -> vstore {
        match vstore {
            vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
            vstore_slice(_) => vstore_slice(re_static)
        }
    }

4216
    match cx.normalized_cache.find(t) {
B
Brian Anderson 已提交
4217 4218
      Some(t) => return t,
      None => ()
B
Brian Anderson 已提交
4219 4220
    }

4221
    let t = match get(t).sty {
4222 4223 4224 4225
        ty_evec(mt, vstore) =>
            // This type has a vstore. Get rid of it
            mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),

4226 4227 4228 4229
        ty_estr(vstore) =>
            // This type has a vstore. Get rid of it
            mk_estr(cx, normalize_vstore(vstore)),

E
Erick Tryzelaar 已提交
4230
        ty_rptr(_, mt) =>
4231
            // This type has a region. Get rid of it
4232 4233
            mk_rptr(cx, re_static, normalize_mt(cx, mt)),

4234 4235
        ty_fn(ref fn_ty) => {
            mk_fn(cx, FnTyBase {
4236 4237 4238 4239
                meta: FnMeta {
                    region: ty::re_static,
                    ..fn_ty.meta
                },
4240
                sig: /*bad*/copy fn_ty.sig
4241 4242
            })
        }
4243

4244 4245
        ty_enum(did, ref r) =>
            match (*r).self_r {
B
Brian Anderson 已提交
4246
                Some(_) =>
4247
                    // Use re_static since trans doesn't care about regions
E
Eric Holk 已提交
4248
                    mk_enum(cx, did,
4249 4250 4251 4252 4253
                     substs {
                        self_r: Some(ty::re_static),
                        self_ty: None,
                        tps: /*bad*/copy (*r).tps
                     }),
B
Brian Anderson 已提交
4254
                None =>
4255 4256 4257
                    t
            },

4258
        ty_struct(did, ref r) =>
4259
            match (*r).self_r {
B
Brian Anderson 已提交
4260
              Some(_) =>
4261
                // Ditto.
4262 4263 4264
                mk_struct(cx, did, substs {self_r: Some(ty::re_static),
                                           self_ty: None,
                                           tps: /*bad*/copy (*r).tps}),
B
Brian Anderson 已提交
4265
              None =>
4266 4267 4268 4269 4270
                t
            },

        _ =>
            t
4271 4272
    };

4273
    let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
B
Brian Anderson 已提交
4274 4275
    let t_norm = mk_t(cx, sty);
    cx.normalized_cache.insert(t, t_norm);
B
Brian Anderson 已提交
4276
    return t_norm;
4277 4278
}

4279
// Returns the repeat count for a repeating vector expression.
4280 4281 4282 4283
pub fn eval_repeat_count(tcx: ctxt,
                         count_expr: @ast::expr,
                         span: span)
                      -> uint {
4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298
    match const_eval::eval_const_expr(tcx, count_expr) {
        const_eval::const_int(count) => return count as uint,
        const_eval::const_uint(count) => return count as uint,
        const_eval::const_float(count) => {
            tcx.sess.span_err(span,
                              ~"expected signed or unsigned integer for \
                                repeat count but found float");
            return count as uint;
        }
        const_eval::const_str(_) => {
            tcx.sess.span_err(span,
                              ~"expected signed or unsigned integer for \
                                repeat count but found string");
            return 0;
        }
4299 4300 4301 4302 4303 4304 4305
        const_eval::const_bool(_) => {
            tcx.sess.span_err(span,
                              ~"expected signed or unsigned integer for \
                                repeat count but found boolean");
            return 0;
        }

4306 4307 4308
    }
}

4309
// Determine what purity to check a nested function under
4310 4311 4312 4313
pub pure fn determine_inherited_purity(parent_purity: ast::purity,
                                       child_purity: ast::purity,
                                       child_proto: ast::Proto)
                                    -> ast::purity {
4314 4315 4316
    // 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
4317 4318 4319 4320
    match child_proto {
        ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity,
        _ => child_purity
    }
4321 4322
}

4323 4324
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
4325 4326 4327
// Here, the supertraits are the transitive closure of the supertrait
// relation on the supertraits from each bounded trait's constraint
// list.
4328 4329 4330
pub fn iter_bound_traits_and_supertraits(tcx: ctxt,
                                         bounds: param_bounds,
                                         f: &fn(t) -> bool) {
4331 4332
    let mut fin = false;

4333 4334 4335 4336 4337
    for bounds.each |bound| {

        let bound_trait_ty = match *bound {
            ty::bound_trait(bound_t) => bound_t,

B
Brian Anderson 已提交
4338
            ty::bound_copy | ty::bound_owned |
B
Brian Anderson 已提交
4339
            ty::bound_const | ty::bound_durable => {
4340 4341 4342 4343
                loop; // skip non-trait bounds
            }
        };

4344 4345
        let mut supertrait_map = HashMap();
        let mut seen_def_ids = ~[];
4346
        let mut i = 0;
4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379
        let trait_ty_id = ty_to_def_id(bound_trait_ty).expect(
            ~"iter_trait_ty_supertraits got a non-trait type");
        let mut trait_ty = bound_trait_ty;

        debug!("iter_bound_traits_and_supertraits: trait_ty = %s",
               ty_to_str(tcx, trait_ty));

        // Add the given trait ty to the hash map
        supertrait_map.insert(trait_ty_id, trait_ty);
        seen_def_ids.push(trait_ty_id);

        if f(trait_ty) {
            // Add all the supertraits to the hash map,
            // executing <f> on each of them
            while i < supertrait_map.size() && !fin {
                let init_trait_id = seen_def_ids[i];
                i += 1;
                 // Add supertraits to supertrait_map
                let supertraits = trait_supertraits(tcx, init_trait_id);
                for supertraits.each |supertrait| {
                    let super_t = supertrait.tpt.ty;
                    let d_id = ty_to_def_id(super_t).expect("supertrait \
                        should be a trait ty");
                    if !supertrait_map.contains_key(d_id) {
                        supertrait_map.insert(d_id, super_t);
                        trait_ty = super_t;
                        seen_def_ids.push(d_id);
                    }
                    debug!("A super_t = %s", ty_to_str(tcx, trait_ty));
                    if !f(trait_ty) {
                        fin = true;
                    }
                }
4380
            }
4381 4382
        };
        fin = false;
4383 4384 4385
    }
}

4386 4387
pub fn count_traits_and_supertraits(tcx: ctxt,
                                    boundses: &[param_bounds]) -> uint {
4388 4389 4390 4391 4392 4393 4394 4395 4396
    let mut total = 0;
    for boundses.each |bounds| {
        for iter_bound_traits_and_supertraits(tcx, *bounds) |_trait_ty| {
            total += 1;
        }
    }
    return total;
}

4397
// Given a trait and a type, returns the impl of that type
4398
pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412
    match tcx.trait_impls.find(trait_id) {
        Some(ty_to_impl) => match ty_to_impl.find(self_ty) {
            Some(the_impl) => the_impl.did,
            None => // try autoderef!
                match deref(tcx, self_ty, false) {
                    Some(some_ty) => get_impl_id(tcx, trait_id, some_ty.ty),
                    None => tcx.sess.bug(~"get_impl_id: no impl of trait for \
                                           this type")
            }
        },
        None => tcx.sess.bug(~"get_impl_id: trait isn't in trait_impls")
    }
}

4413
impl mt : cmp::Eq {
4414 4415 4416 4417
    pure fn eq(&self, other: &mt) -> bool {
        (*self).ty == (*other).ty && (*self).mutbl == (*other).mutbl
    }
    pure fn ne(&self, other: &mt) -> bool { !(*self).eq(other) }
4418
}
4419

4420
impl vstore : cmp::Eq {
4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449
    pure fn eq(&self, other: &vstore) -> bool {
        match (*self) {
            vstore_fixed(e0a) => {
                match (*other) {
                    vstore_fixed(e0b) => e0a == e0b,
                    _ => false
                }
            }
            vstore_uniq => {
                match (*other) {
                    vstore_uniq => true,
                    _ => false
                }
            }
            vstore_box => {
                match (*other) {
                    vstore_box => true,
                    _ => false
                }
            }
            vstore_slice(e0a) => {
                match (*other) {
                    vstore_slice(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
    pure fn ne(&self, other: &vstore) -> bool { !(*self).eq(other) }
4450
}
4451

4452
impl Region : cmp::Eq {
4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487
    pure fn eq(&self, other: &Region) -> bool {
        match (*self) {
            re_bound(e0a) => {
                match (*other) {
                    re_bound(e0b) => e0a == e0b,
                    _ => false
                }
            }
            re_free(e0a, e1a) => {
                match (*other) {
                    re_free(e0b, e1b) => e0a == e0b && e1a == e1b,
                    _ => false
                }
            }
            re_scope(e0a) => {
                match (*other) {
                    re_scope(e0b) => e0a == e0b,
                    _ => false
                }
            }
            re_static => {
                match (*other) {
                    re_static => true,
                    _ => false
                }
            }
            re_infer(e0a) => {
                match (*other) {
                    re_infer(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
    pure fn ne(&self, other: &Region) -> bool { !(*self).eq(other) }
4488
}
4489

4490
impl bound_region : cmp::Eq {
4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516
    pure fn eq(&self, other: &bound_region) -> bool {
        match (*self) {
            br_self => {
                match (*other) {
                    br_self => true,
                    _ => false
                }
            }
            br_anon(e0a) => {
                match (*other) {
                    br_anon(e0b) => e0a == e0b,
                    _ => false
                }
            }
            br_named(e0a) => {
                match (*other) {
                    br_named(e0b) => e0a == e0b,
                    _ => false
                }
            }
            br_cap_avoid(e0a, e1a) => {
                match (*other) {
                    br_cap_avoid(e0b, e1b) => e0a == e0b && e1a == e1b,
                    _ => false
                }
            }
4517 4518 4519 4520 4521 4522
            br_fresh(e0a) => {
                match (*other) {
                    br_fresh(e0b) => e0a == e0b,
                    _ => false
                }
            }
4523 4524 4525
        }
    }
    pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) }
4526
}
4527

4528
impl sty : cmp::Eq {
4529
    pure fn eq(&self, other: &sty) -> bool {
4530
        match (/*bad*/copy *self) {
4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572
            ty_nil => {
                match (*other) {
                    ty_nil => true,
                    _ => false
                }
            }
            ty_bot => {
                match (*other) {
                    ty_bot => true,
                    _ => false
                }
            }
            ty_bool => {
                match (*other) {
                    ty_bool => true,
                    _ => false
                }
            }
            ty_int(e0a) => {
                match (*other) {
                    ty_int(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_uint(e0a) => {
                match (*other) {
                    ty_uint(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_float(e0a) => {
                match (*other) {
                    ty_float(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_estr(e0a) => {
                match (*other) {
                    ty_estr(e0b) => e0a == e0b,
                    _ => false
                }
            }
4573
            ty_enum(e0a, ref e1a) => {
4574
                match (*other) {
4575
                    ty_enum(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609
                    _ => false
                }
            }
            ty_box(e0a) => {
                match (*other) {
                    ty_box(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_uniq(e0a) => {
                match (*other) {
                    ty_uniq(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_evec(e0a, e1a) => {
                match (*other) {
                    ty_evec(e0b, e1b) => e0a == e0b && e1a == e1b,
                    _ => false
                }
            }
            ty_ptr(e0a) => {
                match (*other) {
                    ty_ptr(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_rptr(e0a, e1a) => {
                match (*other) {
                    ty_rptr(e0b, e1b) => e0a == e0b && e1a == e1b,
                    _ => false
                }
            }
            ty_rec(e0a) => {
4610
                match (/*bad*/copy *other) {
4611 4612 4613 4614
                    ty_rec(e0b) => e0a == e0b,
                    _ => false
                }
            }
4615
            ty_fn(ref e0a) => {
4616
                match (*other) {
4617
                    ty_fn(ref e0b) => (*e0a) == (*e0b),
4618 4619 4620
                    _ => false
                }
            }
4621
            ty_trait(e0a, ref e1a, e2a) => {
4622
                match (*other) {
4623 4624
                    ty_trait(e0b, ref e1b, e2b) =>
                        e0a == e0b && (*e1a) == (*e1b) && e2a == e2b,
4625 4626 4627
                    _ => false
                }
            }
4628
            ty_struct(e0a, ref e1a) => {
4629
                match (*other) {
4630
                    ty_struct(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4631 4632 4633 4634
                    _ => false
                }
            }
            ty_tup(e0a) => {
4635
                match (/*bad*/copy *other) {
4636 4637 4638 4639
                    ty_tup(e0b) => e0a == e0b,
                    _ => false
                }
            }
4640
            ty_infer(ref e0a) => {
4641
                match (*other) {
4642
                    ty_infer(ref e0b) => *e0a == *e0b,
4643 4644 4645
                    _ => false
                }
            }
4646 4647 4648 4649 4650 4651
            ty_err => {
                match (*other) {
                    ty_err => true,
                    _ => false
                }
            }
4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690
            ty_param(e0a) => {
                match (*other) {
                    ty_param(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_self => {
                match (*other) {
                    ty_self => true,
                    _ => false
                }
            }
            ty_type => {
                match (*other) {
                    ty_type => true,
                    _ => false
                }
            }
            ty_opaque_box => {
                match (*other) {
                    ty_opaque_box => true,
                    _ => false
                }
            }
            ty_opaque_closure_ptr(e0a) => {
                match (*other) {
                    ty_opaque_closure_ptr(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_unboxed_vec(e0a) => {
                match (*other) {
                    ty_unboxed_vec(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
    pure fn ne(&self, other: &sty) -> bool { !(*self).eq(other) }
4691
}
4692

4693
impl param_bound : cmp::Eq {
4694 4695 4696 4697 4698 4699 4700 4701
    pure fn eq(&self, other: &param_bound) -> bool {
        match (*self) {
            bound_copy => {
                match (*other) {
                    bound_copy => true,
                    _ => false
                }
            }
B
Brian Anderson 已提交
4702
            bound_durable => {
4703
                match (*other) {
B
Brian Anderson 已提交
4704
                    bound_durable => true,
4705 4706 4707
                    _ => false
                }
            }
B
Brian Anderson 已提交
4708
            bound_owned => {
4709
                match (*other) {
B
Brian Anderson 已提交
4710
                    bound_owned => true,
4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727
                    _ => false
                }
            }
            bound_const => {
                match (*other) {
                    bound_const => true,
                    _ => false
                }
            }
            bound_trait(e0a) => {
                match (*other) {
                    bound_trait(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
B
Brian Anderson 已提交
4728
    pure fn ne(&self, other: &param_bound) -> bool { !self.eq(other) }
4729
}
4730

4731
impl Kind : cmp::Eq {
4732 4733
    pure fn eq(&self, other: &Kind) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &Kind) -> bool { *(*self) != *(*other) }
4734
}
4735

4736

4737 4738 4739 4740 4741 4742 4743
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: