ty.rs 142.5 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
use core::dvec::DVec;
P
Patrick Walton 已提交
14 15
use std::{map, smallintmap};
use result::Result;
B
Brian Anderson 已提交
16
use std::map::HashMap;
P
Patrick Walton 已提交
17
use driver::session;
18
use session::Session;
P
Patrick Walton 已提交
19 20
use syntax::{ast, ast_map};
use syntax::ast_util;
21
use syntax::ast_util::{is_local, local_def};
P
Patrick Walton 已提交
22 23
use syntax::codemap::span;
use metadata::csearch;
24
use util::ppaux::{region_to_str, explain_region, vstore_to_str,
25
                  note_and_explain_region, bound_region_to_str};
P
Patrick Walton 已提交
26 27 28 29 30
use middle::lint;
use middle::lint::{get_lint_level, allow};
use syntax::ast::*;
use syntax::print::pprust::*;
use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
31
use middle::resolve::{Impl, MethodInfo};
32

33
export ProvidedMethodSource;
34 35
export ProvidedMethodInfo;
export ProvidedMethodsMap;
36
export InstantiatedTraitRef;
37
export TyVid, IntVid, FloatVid, FnVid, RegionVid, vid;
N
Niko Matsakis 已提交
38
export br_hashmap;
39
export is_instantiable;
40 41
export node_id_to_type;
export node_id_to_type_params;
42 43 44
export arg;
export args_eq;
export block_ty;
45
export struct_fields, struct_mutable_fields;
46
export ctxt;
47 48
export deref, deref_sty;
export index, index_sty;
49 50 51
export def_has_ty_params;
export expr_has_ty_params;
export expr_ty;
52
export expr_ty_params_and_ty;
53 54
export expr_is_lval, expr_kind;
export ExprKind, LvalueExpr, RvalueDatumExpr, RvalueDpsExpr, RvalueStmtExpr;
T
Tim Chevalier 已提交
55
export field_ty;
56
export fold_ty, fold_sty_to_ty, fold_region, fold_regions;
57
export apply_op_on_t_to_ty_fn;
58
export fold_regions_and_ty, walk_regions_and_ty;
59
export field;
60
export field_idx, field_idx_strict;
61
export get_field;
T
Tim Chevalier 已提交
62
export get_fields;
63
export get_element_type;
64
export has_dtor;
65
export is_binopable;
66
export is_pred_ty;
67
export lookup_struct_field, lookup_struct_fields;
T
Tim Chevalier 已提交
68
export lookup_field_type;
69
export lookup_item_type;
70
export lookup_public_fields;
71 72
export method;
export method_idx;
73
export mk_struct, mk_err;
74
export mk_ctxt;
75
export mk_with_id, type_def_id;
76 77 78 79
export mt;
export node_type_table;
export pat_ty;
export sequence_element_type;
80
export stmt_node_id;
81
export sty;
82
export subst, subst_tps, substs_is_noop, substs_to_str, substs;
83
export subst_substs;
84
export t;
85
export new_ty_hash;
86
export enum_variants, substd_enum_variants, enum_is_univariant;
87
export trait_methods, store_trait_methods, impl_traits;
88
export enum_variant_with_id;
89
export ty_dtor;
90
export DtorKind, NoDtor, LegacyDtor, TraitDtor;
91
export ty_param_bounds_and_ty;
92
export ty_param_substs_and_ty;
93 94 95 96 97 98
export ty_bool, mk_bool, type_is_bool;
export ty_bot, mk_bot, type_is_bot;
export ty_box, mk_box, mk_imm_box, type_is_box, type_is_boxed;
export ty_opaque_closure_ptr, mk_opaque_closure_ptr;
export ty_opaque_box, mk_opaque_box;
export ty_float, mk_float, mk_mach_float, type_is_fp;
99
export ty_fn, FnTy, FnTyBase, FnMeta, FnSig, mk_fn;
100
export ty_fn_proto, ty_fn_purity, ty_fn_ret, ty_fn_ret_style, tys_in_fn_ty;
101
export ty_int, mk_int, mk_mach_int, mk_char;
102
export mk_i8, mk_u8, mk_i16, mk_u16, mk_i32, mk_u32, mk_i64, mk_u64;
103
export mk_f32, mk_f64;
104
export ty_err;
M
Michael Sullivan 已提交
105 106
export ty_estr, mk_estr, type_is_str;
export ty_evec, mk_evec, type_is_vec;
107
export ty_unboxed_vec, mk_unboxed_vec, mk_mut_unboxed_vec;
108
export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice;
109
export serialize_vstore, deserialize_vstore;
110
export ty_nil, mk_nil, type_is_nil;
111
export ty_trait, mk_trait;
112
export ty_param, mk_param, ty_params_to_tys;
113
export ty_ptr, mk_ptr, mk_mut_ptr, mk_imm_ptr, mk_nil_ptr, type_is_unsafe_ptr;
114
export ty_rptr, mk_rptr, mk_mut_rptr, mk_imm_rptr;
115 116 117 118 119 120
export ty_rec, mk_rec;
export ty_enum, mk_enum, type_is_enum;
export ty_tup, mk_tup;
export ty_type, mk_type;
export ty_uint, mk_uint, mk_mach_uint;
export ty_uniq, mk_uniq, mk_imm_uniq, type_is_unique_box;
121 122
export ty_infer, mk_infer, type_is_ty_var, mk_var, mk_int_var, mk_float_var;
export InferTy, TyVar, IntVar, FloatVar;
123
export ValueMode, ReadValue, CopyValue, MoveValue;
124
export ty_self, mk_self, type_has_self;
125
export ty_struct;
126
export Region, bound_region, encl_region;
127 128
export re_bound, re_free, re_scope, re_static, re_infer;
export ReVar, ReSkolemized;
129
export br_self, br_anon, br_named, br_cap_avoid;
130
export get, type_has_params, type_needs_infer, type_has_regions;
131 132
export type_is_region_ptr;
export type_id;
133
export tbox_has_flag;
134
export ty_var_id;
135
export ty_to_def_id;
136
export ty_fn_args;
137
export ty_region;
138
export Kind, kind_implicitly_copyable, kind_send_copy, kind_copyable;
139
export kind_noncopyable, kind_const;
140
export kind_can_be_copied, kind_can_be_sent, kind_can_be_implicitly_copied;
141
export type_implicitly_moves;
142
export kind_is_safe_for_default_mode;
B
Brian Anderson 已提交
143
export kind_is_durable;
144
export meta_kind, kind_lteq, type_kind;
145
export operators;
146
export type_err, terr_vstore_kind;
147
export terr_mismatch, terr_onceness_mismatch;
148
export type_err_to_str, note_and_explain_type_err;
149
export expected_found;
150
export type_needs_drop;
151
export type_is_empty;
152
export type_is_integral;
153
export type_is_numeric;
P
Patrick Walton 已提交
154
export type_is_pod;
155
export type_is_scalar;
156
export type_is_immediate;
157
export type_is_borrowed;
158 159 160
export type_is_sequence;
export type_is_signed;
export type_is_structural;
161
export type_is_copyable;
162
export type_is_slice;
163
export type_is_unique;
164
export type_is_c_like_enum;
165
export type_structurally_contains;
166
export type_structurally_contains_uniques;
167
export type_autoderef, deref, deref_sty;
168
export type_param;
169
export type_needs_unwind_cleanup;
170
export canon_mode;
171 172 173 174
export resolved_mode;
export arg_mode;
export unify_mode;
export set_default_mode;
175
export VariantInfo, VariantInfo_;
176
export walk_ty, maybe_walk_ty;
177
export occurs_check;
178
export param_ty;
B
Brian Anderson 已提交
179
export param_bound, param_bounds, bound_copy, bound_durable;
180
export param_bounds_to_str, param_bound_to_str;
181
export bound_send, bound_trait;
182
export param_bounds_to_kind;
183
export default_arg_mode_for_ty;
184
export item_path;
185
export item_path_str;
186
export ast_ty_to_ty_cache_entry;
187
export atttce_unresolved, atttce_resolved;
188
export mach_sty;
189
export ty_sort_str;
190
export normalize_ty;
N
Niko Matsakis 已提交
191
export to_str;
192
export bound_const;
193 194
export terr_no_integral_type, terr_no_floating_point_type;
export terr_ty_param_size, terr_self_substs;
195 196
export terr_in_field, terr_record_fields, terr_vstores_differ, terr_arg_count;
export terr_sorts, terr_vec, terr_str, terr_record_size, terr_tuple_size;
197 198
export terr_regions_does_not_outlive, terr_mutability, terr_purity_mismatch;
export terr_regions_not_same, terr_regions_no_overlap;
199 200
export terr_regions_insufficiently_polymorphic;
export terr_regions_overly_polymorphic;
201
export terr_proto_mismatch;
202
export terr_ret_style_mismatch;
203
export terr_fn, terr_trait;
204
export purity_to_str;
205
export onceness_to_str;
206
export param_tys_in_type;
207
export eval_repeat_count;
208
export ast_proto_to_proto;
209
export method_call_bounds;
210
export hash_region;
211 212
export region_variance, rv_covariant, rv_invariant, rv_contravariant;
export opt_region_variance;
213
export determine_inherited_purity;
214
export provided_trait_methods;
215
export trait_supertraits;
216 217
export AutoAdjustment;
export AutoRef;
218
export AutoRefKind, AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn;
219 220
export iter_bound_traits_and_supertraits;
export count_traits_and_supertraits;
221

222
// Data types
223

224 225
// 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.
T
Tim Chevalier 已提交
226
type arg = {mode: ast::mode, ty: t};
227

M
Marijn Haverbeke 已提交
228
type field = {ident: ast::ident, mt: mt};
229

230
type param_bounds = @~[param_bound];
231

232
type method = {ident: ast::ident,
233
               tps: @~[param_bounds],
234
               fty: FnTy,
235
               self_ty: ast::self_ty_,
236 237
               vis: ast::visibility,
               def_id: ast::def_id};
238

239
type mt = {ty: t, mutbl: ast::mutability};
240

241 242
#[auto_serialize]
#[auto_deserialize]
243 244 245 246
enum vstore {
    vstore_fixed(uint),
    vstore_uniq,
    vstore_box,
247
    vstore_slice(Region)
248 249
}

T
Tim Chevalier 已提交
250
type field_ty = {
T
Tim Chevalier 已提交
251
  ident: ident,
T
Tim Chevalier 已提交
252
  id: def_id,
253
  vis: ast::visibility,
254
  mutability: ast::struct_mutability
T
Tim Chevalier 已提交
255 256
};

257 258 259 260 261 262 263 264 265
/// How an lvalue is to be used.
#[auto_serialize]
#[auto_deserialize]
pub enum ValueMode {
    ReadValue,  // Non-destructively read the value; do not copy or move.
    CopyValue,  // Copy the value.
    MoveValue,  // Move the value.
}

266 267
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
268
type creader_cache_key = {cnum: int, pos: uint, len: uint};
B
Brian Anderson 已提交
269
type creader_cache = HashMap<creader_cache_key, t>;
270

271
impl creader_cache_key : cmp::Eq {
272 273 274 275 276 277 278 279
    pure fn eq(&self, other: &creader_cache_key) -> bool {
        (*self).cnum == (*other).cnum &&
            (*self).pos == (*other).pos &&
            (*self).len == (*other).len
    }
    pure fn ne(&self, other: &creader_cache_key) -> bool {
        !((*self) == (*other))
    }
280
}
281

282 283 284 285 286
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);
    }
}
287

288
type intern_key = {sty: sty, o_def_id: Option<ast::def_id>};
289

290
impl intern_key : cmp::Eq {
291 292 293 294
    pure fn eq(&self, other: &intern_key) -> bool {
        (*self).sty == (*other).sty && (*self).o_def_id == (*other).o_def_id
    }
    pure fn ne(&self, other: &intern_key) -> bool { !(*self).eq(other) }
295
}
296

297 298 299 300 301
impl intern_key : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_2(&self.sty, &self.o_def_id, lsb0, f);
    }
}
302

303 304
enum ast_ty_to_ty_cache_entry {
    atttce_unresolved,  /* not resolved yet */
305
    atttce_resolved(t)  /* resolved to a type, irrespective of region */
306 307
}

B
Brian Anderson 已提交
308
type opt_region_variance = Option<region_variance>;
309

310 311
#[auto_serialize]
#[auto_deserialize]
312 313
enum region_variance { rv_covariant, rv_invariant, rv_contravariant }

314
impl region_variance : cmp::Eq {
315 316 317 318 319 320 321 322 323 324 325
    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) }
326
}
327

328 329
#[auto_serialize]
#[auto_deserialize]
330
pub type AutoAdjustment = {
331 332 333 334
    autoderefs: uint,
    autoref: Option<AutoRef>
};

335 336
#[auto_serialize]
#[auto_deserialize]
337
pub type AutoRef = {
338
    kind: AutoRefKind,
339
    region: Region,
340 341 342
    mutbl: ast::mutability
};

343 344
#[auto_serialize]
#[auto_deserialize]
345
enum AutoRefKind {
346 347 348
    /// Convert from T to &T
    AutoPtr,

349
    /// Convert from @[]/~[] to &[] (or str)
350
    AutoBorrowVec,
351

352 353 354
    /// Convert from @[]/~[] to &&[] (or str)
    AutoBorrowVecRef,

355 356
    /// Convert from @fn()/~fn() to &fn()
    AutoBorrowFn,
357 358
}

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
// 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.
type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;

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

374 375 376 377 378
struct ProvidedMethodSource {
    method_id: ast::def_id,
    impl_id: ast::def_id
}

379 380 381 382 383
struct InstantiatedTraitRef {
    def_id: ast::def_id,
    tpt: ty_param_substs_and_ty
}

384
type ctxt =
385
    @{diag: syntax::diagnostic::span_handler,
B
Brian Anderson 已提交
386
      interner: HashMap<intern_key, t_box>,
G
Graydon Hoare 已提交
387
      mut next_id: uint,
388
      vecs_implicitly_copyable: bool,
389
      legacy_modes: bool,
390 391
      cstore: metadata::cstore::CStore,
      sess: session::Session,
G
Graydon Hoare 已提交
392
      def_map: resolve::DefMap,
393

394
      region_map: middle::region::region_map,
395
      region_paramd_items: middle::region::region_paramd_items,
396 397 398

      // Stores the types for various nodes in the AST.  Note that this table
      // is not guaranteed to be populated until after typeck.  See
L
Lindsey Kuper 已提交
399
      // typeck::check::fn_ctxt for details.
M
Marijn Haverbeke 已提交
400
      node_types: node_type_table,
401 402 403 404 405

      // 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.
B
Brian Anderson 已提交
406
      node_type_substs: HashMap<node_id, ~[t]>,
407

M
Marijn Haverbeke 已提交
408
      items: ast_map::map,
B
Brian Anderson 已提交
409
      intrinsic_defs: HashMap<ast::ident, (ast::def_id, t)>,
M
Marijn Haverbeke 已提交
410 411 412
      freevars: freevars::freevar_map,
      tcache: type_cache,
      rcache: creader_cache,
413
      ccache: constness_cache,
B
Brian Anderson 已提交
414 415 416
      short_names_cache: HashMap<t, @~str>,
      needs_drop_cache: HashMap<t, bool>,
      needs_unwind_cleanup_cache: HashMap<t, bool>,
417 418
      kind_cache: HashMap<t, Kind>,
      ast_ty_to_ty_cache: HashMap<@ast::Ty, ast_ty_to_ty_cache_entry>,
419
      enum_var_cache: HashMap<def_id, @~[VariantInfo]>,
B
Brian Anderson 已提交
420 421 422
      trait_method_cache: HashMap<def_id, @~[method]>,
      ty_param_bounds: HashMap<ast::node_id, param_bounds>,
      inferred_modes: HashMap<ast::node_id, ast::mode>,
423
      adjustments: HashMap<ast::node_id, @AutoAdjustment>,
424
      normalized_cache: HashMap<t, t>,
425
      lang_items: middle::lang_items::LanguageItems,
426
      legacy_boxed_traits: HashMap<node_id, ()>,
B
Brian Anderson 已提交
427 428 429
      // 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.
430
      provided_methods: ProvidedMethodsMap,
431
      provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
432
      supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
433 434 435 436 437 438 439 440

      // 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.
441 442 443 444
      destructors: HashMap<ast::def_id, ()>,

      // Records the value mode (read, copy, or move) for every value.
      value_modes: HashMap<ast::node_id, ValueMode>,
445
      };
446

447 448 449 450 451 452 453 454 455 456 457
enum tbox_flag {
    has_params = 1,
    has_self = 2,
    needs_infer = 4,
    has_regions = 8,

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

458
type t_box = @{sty: sty,
459
               id: uint,
460
               flags: uint,
B
Brian Anderson 已提交
461
               o_def_id: Option<ast::def_id>};
462

463 464 465 466 467 468 469
// 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 {}
type t = *t_opaque;
470

471
pure fn get(t: t) -> t_box unsafe {
472
    let t2 = cast::reinterpret_cast::<t, t_box>(&t);
473
    let t3 = t2;
474
    cast::forget(move t2);
475 476 477
    t3
}

478
pure fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
479 480
    (tb.flags & (flag as uint)) != 0u
}
481 482 483 484
pure fn type_has_params(t: t) -> bool { tbox_has_flag(get(t), has_params) }
pure fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
pure fn type_needs_infer(t: t) -> bool { tbox_has_flag(get(t), needs_infer) }
pure fn type_has_regions(t: t) -> bool { tbox_has_flag(get(t), has_regions) }
B
Brian Anderson 已提交
485
pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
486
pure fn type_id(t: t) -> uint { get(t).id }
487

488 489 490 491 492
/**
 * Meta information about a closure.
 *
 * - `purity` is the function's effect (pure, impure, unsafe).
 * - `proto` is the protocol (fn@, fn~, etc).
493 494
 * - `onceness` indicates whether the function can be called one time or many
 *   times.
495
 * - `region` is the region bound on the function's upvars (often &static).
496 497 498
 * - `bounds` is the parameter bounds on the function's upvars.
 * - `ret_style` indicates whether the function returns a value or fails. */
struct FnMeta {
499
    purity: ast::purity,
500
    proto: ast::Proto,
501
    onceness: ast::Onceness,
502
    region: Region,
503 504
    bounds: @~[param_bound],
    ret_style: ret_style
505 506 507 508 509 510 511 512 513
}

/**
 * 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. */
struct FnSig {
514 515
    inputs: ~[arg],
    output: t
516 517 518 519 520 521 522 523
}

/**
 * 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. */
struct FnTyBase<M: cmp::Eq> {
524 525
    meta: M,
    sig: FnSig
526 527 528
}

type FnTy = FnTyBase<FnMeta>;
529

530 531
type param_ty = {idx: uint, def_id: def_id};

532
impl param_ty : cmp::Eq {
533 534 535 536
    pure fn eq(&self, other: &param_ty) -> bool {
        (*self).idx == (*other).idx && (*self).def_id == (*other).def_id
    }
    pure fn ne(&self, other: &param_ty) -> bool { !(*self).eq(other) }
537
}
538

539 540 541 542 543
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)
    }
}
544 545


546
/// Representation of regions:
547 548
#[auto_serialize]
#[auto_deserialize]
549
enum Region {
550 551 552 553 554 555 556 557 558
    /// 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 已提交
559
    re_bound(bound_region),
560 561 562 563

    /// 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 已提交
564
    re_free(node_id, bound_region),
565 566

    /// A concrete region naming some expression within the current function.
N
Niko Matsakis 已提交
567
    re_scope(node_id),
568 569 570 571 572

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

    /// A region variable.  Should not exist after typeck.
573
    re_infer(InferRegion)
N
Niko Matsakis 已提交
574 575
}

576 577
#[auto_serialize]
#[auto_deserialize]
N
Niko Matsakis 已提交
578
enum bound_region {
579
    /// The self region for structs, impls (&T in a type defn or &self/T)
580 581
    br_self,

582 583
    /// An anonymous region parameter for a given fn (&T)
    br_anon(uint),
584 585 586 587

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

588 589 590 591 592 593 594 595 596
    /**
     * 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. */
597
    br_cap_avoid(ast::node_id, @bound_region),
598 599
}

600
type opt_region = Option<Region>;
601

602 603 604 605 606 607 608 609 610
/**
 * 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
611
 *   types (enums, structs) declared as having a region parameter.  `self_r`
612 613 614 615 616 617 618
 *   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. */
619 620
type substs = {
    self_r: opt_region,
B
Brian Anderson 已提交
621
    self_ty: Option<ty::t>,
622
    tps: ~[t]
623 624
};

625
// NB: If you change this, you'll probably want to change the corresponding
626
// AST structure in libsyntax/ast.rs as well.
P
Patrick Walton 已提交
627
enum sty {
P
Patrick Walton 已提交
628 629 630 631 632 633
    ty_nil,
    ty_bot,
    ty_bool,
    ty_int(ast::int_ty),
    ty_uint(ast::uint_ty),
    ty_float(ast::float_ty),
634
    ty_estr(vstore),
635
    ty_enum(def_id, substs),
P
Patrick Walton 已提交
636 637
    ty_box(mt),
    ty_uniq(mt),
638
    ty_evec(mt, vstore),
P
Patrick Walton 已提交
639
    ty_ptr(mt),
640
    ty_rptr(Region, mt),
641
    ty_rec(~[field]),
642
    ty_fn(FnTy),
643
    ty_trait(def_id, substs, vstore),
644
    ty_struct(def_id, substs),
645
    ty_tup(~[t]),
P
Patrick Walton 已提交
646

647
    ty_param(param_ty), // type parameter
648
    ty_self, // special, implicit `self` type parameter
P
Patrick Walton 已提交
649

650
    ty_infer(InferTy), // soething used only during inference/typeck
651 652 653
    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)
654

M
Michael Sullivan 已提交
655
    // "Fake" types, used for trans purposes
P
Patrick Walton 已提交
656
    ty_type, // type_desc*
657
    ty_opaque_box, // used by monomorphizer to represent any @ box
658
    ty_opaque_closure_ptr(ast::Proto), // ptr to env for fn, fn@, fn~
M
Michael Sullivan 已提交
659
    ty_unboxed_vec(mt),
660 661
}

662
enum terr_vstore_kind {
663
    terr_vec, terr_str, terr_fn, terr_trait
664 665
}

666
struct expected_found<T> {
667 668
    expected: T,
    found: T
669 670
}

671
// Data structures used in type unification
P
Patrick Walton 已提交
672
enum type_err {
P
Patrick Walton 已提交
673
    terr_mismatch,
674 675
    terr_ret_style_mismatch(expected_found<ast::ret_style>),
    terr_purity_mismatch(expected_found<purity>),
676
    terr_onceness_mismatch(expected_found<Onceness>),
677
    terr_mutability,
678
    terr_proto_mismatch(expected_found<ast::Proto>),
P
Patrick Walton 已提交
679
    terr_box_mutability,
M
Marijn Haverbeke 已提交
680
    terr_ptr_mutability,
681
    terr_ref_mutability,
P
Patrick Walton 已提交
682
    terr_vec_mutability,
683 684 685
    terr_tuple_size(expected_found<uint>),
    terr_ty_param_size(expected_found<uint>),
    terr_record_size(expected_found<uint>),
P
Patrick Walton 已提交
686
    terr_record_mutability,
687
    terr_record_fields(expected_found<ident>),
P
Patrick Walton 已提交
688
    terr_arg_count,
689
    terr_mode_mismatch(expected_found<mode>),
690 691 692
    terr_regions_does_not_outlive(Region, Region),
    terr_regions_not_same(Region, Region),
    terr_regions_no_overlap(Region, Region),
693 694
    terr_regions_insufficiently_polymorphic(bound_region, Region),
    terr_regions_overly_polymorphic(bound_region, Region),
695
    terr_vstores_differ(terr_vstore_kind, expected_found<vstore>),
B
Brian Anderson 已提交
696
    terr_in_field(@type_err, ast::ident),
697
    terr_sorts(expected_found<t>),
698 699
    terr_self_substs,
    terr_no_integral_type,
700
    terr_no_floating_point_type,
701 702
}

P
Patrick Walton 已提交
703
enum param_bound {
P
Patrick Walton 已提交
704
    bound_copy,
B
Brian Anderson 已提交
705
    bound_durable,
P
Patrick Walton 已提交
706
    bound_send,
707
    bound_const,
708
    bound_trait(t),
709 710
}

711 712
enum TyVid = uint;
enum IntVid = uint;
713
enum FloatVid = uint;
714
enum FnVid = uint;
715 716
#[auto_serialize]
#[auto_deserialize]
717
enum RegionVid = uint;
N
Niko Matsakis 已提交
718

719
enum InferTy {
720
    TyVar(TyVid),
721 722
    IntVar(IntVid),
    FloatVar(FloatVid)
723 724
}

725 726 727 728 729 730 731 732 733
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),
          FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f)
        }
    }
}
734

735 736 737 738 739 740 741
#[auto_serialize]
#[auto_deserialize]
enum InferRegion {
    ReVar(RegionVid),
    ReSkolemized(uint, bound_region)
}

742 743 744 745 746 747 748 749
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)
        }
    }
}
750 751

impl InferRegion : cmp::Eq {
752 753 754 755 756 757 758 759 760 761 762 763 764 765
    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))
    }
766 767
}

768 769 770 771
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 已提交
772
          bound_durable => 1u8.iter_bytes(lsb0, f),
773 774 775 776 777 778 779
          bound_send => 2u8.iter_bytes(lsb0, f),
          bound_const => 3u8.iter_bytes(lsb0, f),
          bound_trait(ref t) =>
          to_bytes::iter_bytes_2(&4u8, t, lsb0, f)
        }
    }
}
780

781
trait vid {
782 783
    pure fn to_uint() -> uint;
    pure fn to_str() -> ~str;
N
Niko Matsakis 已提交
784 785
}

786
impl TyVid: vid {
787
    pure fn to_uint() -> uint { *self }
P
Paul Stansifer 已提交
788
    pure fn to_str() -> ~str { fmt!("<V%u>", self.to_uint()) }
N
Niko Matsakis 已提交
789 790
}

791
impl IntVid: vid {
792
    pure fn to_uint() -> uint { *self }
P
Paul Stansifer 已提交
793
    pure fn to_str() -> ~str { fmt!("<VI%u>", self.to_uint()) }
794 795
}

796 797 798 799 800
impl FloatVid: vid {
    pure fn to_uint() -> uint { *self }
    pure fn to_str() -> ~str { fmt!("<VF%u>", self.to_uint()) }
}

801 802 803 804 805 806
impl FnVid: vid {
    pure fn to_uint() -> uint { *self }
    pure fn to_str() -> ~str { fmt!("<F%u>", self.to_uint()) }
}

impl RegionVid: vid {
807
    pure fn to_uint() -> uint { *self }
P
Paul Stansifer 已提交
808
    pure fn to_str() -> ~str { fmt!("%?", self) }
N
Niko Matsakis 已提交
809 810
}

811 812 813 814
impl InferTy {
    pure fn to_hash() -> uint {
        match self {
            TyVar(v) => v.to_uint() << 1,
815
            IntVar(v) => (v.to_uint() << 1) + 1,
816
            FloatVar(v) => (v.to_uint() << 1) + 2
817 818 819 820 821 822
        }
    }

    pure fn to_str() -> ~str {
        match self {
            TyVar(v) => v.to_str(),
823
            IntVar(v) => v.to_str(),
824
            FloatVar(v) => v.to_str()
825 826 827 828
        }
    }
}

829
trait purity_to_str {
830
    pure fn to_str() -> ~str;
831 832
}

B
Brian Anderson 已提交
833
impl purity: purity_to_str {
834
    pure fn to_str() -> ~str {
N
Niko Matsakis 已提交
835 836 837 838
        purity_to_str(self)
    }
}

839 840 841 842 843
impl RegionVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
844

845 846 847 848 849
impl TyVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
850

851 852 853 854 855
impl IntVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
856

857 858 859 860 861
impl FloatVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
862

863 864 865 866 867
impl FnVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
868

869
fn param_bounds_to_kind(bounds: param_bounds) -> Kind {
870
    let mut kind = kind_noncopyable();
871
    for vec::each(*bounds) |bound| {
872
        match *bound {
B
Brian Anderson 已提交
873
          bound_copy => {
874
            kind = raise_kind(kind, kind_implicitly_copyable());
875
          }
B
Brian Anderson 已提交
876 877
          bound_durable => {
            kind = raise_kind(kind, kind_durable());
878
          }
B
Brian Anderson 已提交
879
          bound_send => {
B
Brian Anderson 已提交
880
            kind = raise_kind(kind, kind_send_only() | kind_durable());
881
          }
B
Brian Anderson 已提交
882
          bound_const => {
883 884
            kind = raise_kind(kind, kind_const());
          }
B
Brian Anderson 已提交
885
          bound_trait(_) => ()
886 887 888 889 890
        }
    }
    kind
}

891 892 893 894 895 896 897 898 899 900
/// 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
901
type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
B
Brian Anderson 已提交
902
                               region_param: Option<region_variance>,
903
                               ty: t};
904

905 906
type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t};

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

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

B
Brian Anderson 已提交
911
type node_type_table = @smallintmap::SmallIntMap<t>;
912

913
fn mk_rcache() -> creader_cache {
M
Marijn Haverbeke 已提交
914
    type val = {cnum: int, pos: uint, len: uint};
B
Brian Anderson 已提交
915
    return map::HashMap();
916
}
917

B
Brian Anderson 已提交
918 919
fn new_ty_hash<V: Copy>() -> map::HashMap<t, V> {
    map::HashMap()
920
}
921

922
fn mk_ctxt(s: session::Session,
G
Graydon Hoare 已提交
923
           dm: resolve::DefMap,
924
           amap: ast_map::map,
P
Patrick Walton 已提交
925
           freevars: freevars::freevar_map,
926
           region_map: middle::region::region_map,
927
           region_paramd_items: middle::region::region_paramd_items,
928 929 930 931 932
           +lang_items: middle::lang_items::LanguageItems,
           crate: @ast::crate) -> ctxt {
    let mut legacy_modes = false;
    for crate.node.attrs.each |attribute| {
        match attribute.node.value.node {
933
            ast::meta_word(ref w) if (*w) == ~"legacy_modes" => {
934 935 936 937 938 939 940
                legacy_modes = true;
                break;
            }
            _ => {}
        }
    }

B
Brian Anderson 已提交
941
    let interner = map::HashMap();
942
    let vecs_implicitly_copyable =
943 944
        get_lint_level(s.lint_settings.default_settings,
                       lint::vecs_implicitly_copyable) == allow;
945 946
    @{diag: s.diagnostic(),
      interner: interner,
G
Graydon Hoare 已提交
947
      mut next_id: 0u,
948
      vecs_implicitly_copyable: vecs_implicitly_copyable,
949
      legacy_modes: legacy_modes,
950
      cstore: s.cstore,
951 952
      sess: s,
      def_map: dm,
P
Patrick Walton 已提交
953
      region_map: region_map,
954
      region_paramd_items: region_paramd_items,
955
      node_types: @smallintmap::mk(),
956
      node_type_substs: map::HashMap(),
957
      items: amap,
958
      intrinsic_defs: map::HashMap(),
959
      freevars: freevars,
960
      tcache: HashMap(),
961
      rcache: mk_rcache(),
962
      ccache: HashMap(),
963 964
      short_names_cache: new_ty_hash(),
      needs_drop_cache: new_ty_hash(),
965
      needs_unwind_cleanup_cache: new_ty_hash(),
966
      kind_cache: new_ty_hash(),
967 968 969 970 971 972
      ast_ty_to_ty_cache: HashMap(),
      enum_var_cache: HashMap(),
      trait_method_cache: HashMap(),
      ty_param_bounds: HashMap(),
      inferred_modes: HashMap(),
      adjustments: HashMap(),
973
      normalized_cache: new_ty_hash(),
974
      lang_items: move lang_items,
975
      legacy_boxed_traits: HashMap(),
976
      provided_methods: HashMap(),
977
      provided_method_sources: HashMap(),
978
      supertraits: HashMap(),
979
      destructor_for_type: HashMap(),
980 981
      destructors: HashMap(),
      value_modes: HashMap()}
982
}
983 984


985
// Type constructors
B
Brian Anderson 已提交
986
fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) }
987 988 989

// 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 已提交
990
fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
991
    let key = {sty: st, o_def_id: o_def_id};
992
    match cx.interner.find(key) {
993
      Some(t) => unsafe { return cast::reinterpret_cast(&t); },
B
Brian Anderson 已提交
994
      _ => ()
995
    }
996
    let mut flags = 0u;
997
    fn rflags(r: Region) -> uint {
998
        (has_regions as uint) | {
999
            match r {
1000
              ty::re_infer(_) => needs_infer as uint,
B
Brian Anderson 已提交
1001
              _ => 0u
1002
            }
N
Niko Matsakis 已提交
1003 1004
        }
    }
N
Niko Matsakis 已提交
1005
    fn sflags(substs: &substs) -> uint {
1006
        let mut f = 0u;
1007
        for substs.tps.each |tt| { f |= get(*tt).flags; }
B
Brian Anderson 已提交
1008
        substs.self_r.iter(|r| f |= rflags(*r));
B
Brian Anderson 已提交
1009
        return f;
N
Niko Matsakis 已提交
1010
    }
1011
    match st {
B
Brian Anderson 已提交
1012
      ty_estr(vstore_slice(r)) => {
1013
        flags |= rflags(r);
1014
      }
B
Brian Anderson 已提交
1015
      ty_evec(mt, vstore_slice(r)) => {
1016 1017
        flags |= rflags(r);
        flags |= get(mt.ty).flags;
1018
      }
1019
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
M
Michael Sullivan 已提交
1020
      ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
1021
      ty_opaque_box | ty_err => (),
B
Brian Anderson 已提交
1022
      ty_param(_) => flags |= has_params as uint,
1023
      ty_infer(_) => flags |= needs_infer as uint,
B
Brian Anderson 已提交
1024
      ty_self => flags |= has_self as uint,
1025
      ty_enum(_, ref substs) | ty_struct(_, ref substs)
1026
      | ty_trait(_, ref substs, _) => {
1027
        flags |= sflags(substs);
1028
      }
M
Michael Sullivan 已提交
1029
      ty_box(m) | ty_uniq(m) | ty_evec(m, _) |
B
Brian Anderson 已提交
1030
      ty_ptr(m) | ty_unboxed_vec(m) => {
1031
        flags |= get(m.ty).flags;
1032
      }
B
Brian Anderson 已提交
1033
      ty_rptr(r, m) => {
1034 1035
        flags |= rflags(r);
        flags |= get(m.ty).flags;
M
Marijn Haverbeke 已提交
1036
      }
1037
      ty_rec(flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
1038
      ty_tup(ts) => for ts.each |tt| { flags |= get(*tt).flags; },
N
Niko Matsakis 已提交
1039
      ty_fn(ref f) => {
1040
        flags |= rflags(f.meta.region);
1041 1042
        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
        flags |= get(f.sig.output).flags;
M
Marijn Haverbeke 已提交
1043
      }
1044
    }
1045
    let t = @{sty: st, id: cx.next_id, flags: flags, o_def_id: o_def_id};
1046 1047
    cx.interner.insert(key, t);
    cx.next_id += 1u;
1048
    unsafe { cast::reinterpret_cast(&t) }
1049 1050
}

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

1053 1054
fn mk_err(cx: ctxt) -> t { mk_t(cx, ty_err) }

1055
fn mk_bot(cx: ctxt) -> t { mk_t(cx, ty_bot) }
1056

1057
fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) }
1058

1059
fn mk_int(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i)) }
1060

1061 1062 1063 1064 1065 1066 1067 1068
fn mk_i8(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i8)) }

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

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

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

1069
fn mk_float(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f)) }
1070

1071
fn mk_uint(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u)) }
1072

1073 1074
fn mk_u8(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u8)) }

1075 1076 1077 1078 1079 1080
fn mk_u16(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u16)) }

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

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

1081 1082 1083 1084
fn mk_f32(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f32)) }

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

1085
fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { mk_t(cx, ty_int(tm)) }
1086

1087
fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { mk_t(cx, ty_uint(tm)) }
1088

1089
fn mk_mach_float(cx: ctxt, tm: ast::float_ty) -> t { mk_t(cx, ty_float(tm)) }
1090

1091
fn mk_char(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_char)) }
1092

1093 1094 1095 1096
fn mk_estr(cx: ctxt, t: vstore) -> t {
    mk_t(cx, ty_estr(t))
}

N
Niko Matsakis 已提交
1097 1098
fn mk_enum(cx: ctxt, did: ast::def_id, +substs: substs) -> t {
    // take a copy of substs so that we own the vectors inside
1099
    mk_t(cx, ty_enum(did, substs))
1100
}
1101

1102
fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) }
1103

1104 1105
fn mk_imm_box(cx: ctxt, ty: t) -> t { mk_box(cx, {ty: ty,
                                                  mutbl: ast::m_imm}) }
1106

1107
fn mk_uniq(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_uniq(tm)) }
1108

1109 1110
fn mk_imm_uniq(cx: ctxt, ty: t) -> t { mk_uniq(cx, {ty: ty,
                                                    mutbl: ast::m_imm}) }
1111

1112
fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
1113

1114
fn mk_rptr(cx: ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
1115

1116
fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1117 1118
    mk_rptr(cx, r, {ty: ty, mutbl: ast::m_mutbl})
}
1119
fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1120 1121 1122
    mk_rptr(cx, r, {ty: ty, mutbl: ast::m_imm})
}

1123 1124
fn mk_mut_ptr(cx: ctxt, ty: t) -> t { mk_ptr(cx, {ty: ty,
                                                  mutbl: ast::m_mutbl}) }
1125

1126 1127 1128 1129
fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
    mk_ptr(cx, {ty: ty, mutbl: ast::m_imm})
}

1130 1131 1132 1133
fn mk_nil_ptr(cx: ctxt) -> t {
    mk_ptr(cx, {ty: mk_nil(cx), mutbl: ast::m_imm})
}

1134 1135 1136 1137
fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
    mk_t(cx, ty_evec(tm, t))
}

M
Michael Sullivan 已提交
1138 1139 1140
fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
    mk_t(cx, ty_unboxed_vec(tm))
}
1141 1142 1143
fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
    mk_t(cx, ty_unboxed_vec({ty: ty, mutbl: ast::m_imm}))
}
M
Michael Sullivan 已提交
1144

1145
fn mk_rec(cx: ctxt, fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) }
1146

1147
fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
1148

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

1152 1153
fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
         -> t {
N
Niko Matsakis 已提交
1154
    // take a copy of substs so that we own the vectors inside
1155
    mk_t(cx, ty_trait(did, substs, vstore))
1156 1157
}

1158
fn mk_struct(cx: ctxt, struct_id: ast::def_id, +substs: substs) -> t {
N
Niko Matsakis 已提交
1159
    // take a copy of substs so that we own the vectors inside
1160
    mk_t(cx, ty_struct(struct_id, substs))
T
Tim Chevalier 已提交
1161 1162
}

1163
fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
1164

1165 1166 1167
fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }

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

1169 1170
fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }

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

1173 1174 1175
fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
    mk_t(cx, ty_param({idx: n, def_id: k}))
}
1176

1177
fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
1178

1179 1180
fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t {
    mk_t(cx, ty_opaque_closure_ptr(proto))
1181 1182
}

1183 1184
fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }

1185
fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t {
1186
    mk_t_with_id(cx, get(base).sty, Some(def_id))
1187 1188 1189
}

// Converts s to its machine type equivalent
1190
pure fn mach_sty(cfg: @session::config, t: t) -> sty {
1191
    match get(t).sty {
B
Brian Anderson 已提交
1192 1193 1194
      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),
1195
      ref s => (*s)
1196 1197 1198
    }
}

1199
fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
1200 1201 1202 1203
        // 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) {
1204 1205 1206 1207
            ast::ProtoBorrowed => {
                return ast::by_ref;
            }
            _ => {}
1208 1209 1210
        }
    }
    return if tcx.legacy_modes {
1211 1212 1213 1214 1215 1216 1217 1218 1219
        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
        }
1220 1221
    } else {
        ast::by_copy
1222 1223 1224 1225 1226 1227 1228
    };

    fn type_is_fn(ty: t) -> bool {
        match get(ty).sty {
            ty_fn(*) => true,
            _ => false
        }
1229
    }
1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241

    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
        }
    }
1242 1243
}

1244 1245
// Returns the narrowest lifetime enclosing the evaluation of the expression
// with id `id`.
1246
fn encl_region(cx: ctxt, id: ast::node_id) -> ty::Region {
1247
    match cx.region_map.find(id) {
B
Brian Anderson 已提交
1248 1249
      Some(encl_scope) => ty::re_scope(encl_scope),
      None => ty::re_static
1250 1251 1252
    }
}

1253
fn walk_ty(ty: t, f: fn(t)) {
B
Brian Anderson 已提交
1254
    maybe_walk_ty(ty, |t| { f(t); true });
1255 1256 1257
}

fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
B
Brian Anderson 已提交
1258
    if !f(ty) { return; }
1259
    match get(ty).sty {
1260
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
M
Michael Sullivan 已提交
1261
      ty_estr(_) | ty_type | ty_opaque_box | ty_self |
1262
      ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1263
      }
M
Michael Sullivan 已提交
1264
      ty_box(tm) | ty_evec(tm, _) | ty_unboxed_vec(tm) |
B
Brian Anderson 已提交
1265
      ty_ptr(tm) | ty_rptr(_, tm) => {
1266
        maybe_walk_ty(tm.ty, f);
1267
      }
1268
      ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1269 1270
      ty_trait(_, ref substs, _) => {
        for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); }
1271
      }
B
Brian Anderson 已提交
1272
      ty_rec(fields) => {
B
Brian Anderson 已提交
1273
        for fields.each |fl| { maybe_walk_ty(fl.mt.ty, f); }
M
Marijn Haverbeke 已提交
1274
      }
1275
      ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
N
Niko Matsakis 已提交
1276
      ty_fn(ref ft) => {
1277 1278
        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
        maybe_walk_ty(ft.sig.output, f);
M
Marijn Haverbeke 已提交
1279
      }
B
Brian Anderson 已提交
1280
      ty_uniq(tm) => { maybe_walk_ty(tm.ty, f); }
1281 1282 1283
    }
}

N
Niko Matsakis 已提交
1284
fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: fn(t) -> t) -> t {
N
Niko Matsakis 已提交
1285
    mk_t(tcx, fold_sty(sty, foldop))
1286
}
1287

N
Niko Matsakis 已提交
1288 1289
fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
    fn fold_substs(substs: &substs, fldop: fn(t) -> t) -> substs {
1290
        {self_r: substs.self_r,
1291
         self_ty: substs.self_ty.map(|t| fldop(*t)),
1292
         tps: substs.tps.map(|t| fldop(*t))}
1293 1294
    }

N
Niko Matsakis 已提交
1295
    match *sty {
1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
        ty_box(tm) => {
            ty_box({ty: fldop(tm.ty), mutbl: tm.mutbl})
        }
        ty_uniq(tm) => {
            ty_uniq({ty: fldop(tm.ty), mutbl: tm.mutbl})
        }
        ty_ptr(tm) => {
            ty_ptr({ty: fldop(tm.ty), mutbl: tm.mutbl})
        }
        ty_unboxed_vec(tm) => {
            ty_unboxed_vec({ty: fldop(tm.ty), mutbl: tm.mutbl})
        }
        ty_evec(tm, vst) => {
            ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
        }
        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);
                let new_mt = {ty: new_ty, mutbl: fl.mt.mutbl};
                {ident: fl.ident, mt: new_mt}
            };
            ty_rec(new_fields)
        }
        ty_tup(ts) => {
1326
            let new_ts = vec::map(ts, |tt| fldop(*tt));
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
            ty_tup(new_ts)
        }
        ty_fn(ref f) => {
            let new_args = f.sig.inputs.map(|a| {
                let new_ty = fldop(a.ty);
                {mode: a.mode, ty: new_ty}
            });
            let new_output = fldop(f.sig.output);
            ty_fn(FnTyBase {
                meta: f.meta,
                sig: FnSig {inputs: new_args, output: new_output}
            })
        }
        ty_rptr(r, tm) => {
            ty_rptr(r, {ty: fldop(tm.ty), mutbl: tm.mutbl})
        }
1343 1344
        ty_struct(did, ref substs) => {
            ty_struct(did, fold_substs(substs, fldop))
1345 1346
        }
        ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1347
        ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1348 1349 1350
        ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
            *sty
        }
N
Niko Matsakis 已提交
1351 1352
    }
}
1353

N
Niko Matsakis 已提交
1354 1355
// Folds types from the bottom up.
fn fold_ty(cx: ctxt, t0: t, fldop: fn(t) -> t) -> t {
1356
    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
N
Niko Matsakis 已提交
1357 1358
    fldop(mk_t(cx, sty))
}
1359

1360 1361 1362
fn walk_regions_and_ty(
    cx: ctxt,
    ty: t,
1363
    walkr: fn(r: Region),
1364 1365 1366 1367 1368
    walkt: fn(t: t) -> bool) {

    if (walkt(ty)) {
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1369 1370 1371
            |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 });
1372 1373 1374
    }
}

1375 1376 1377
fn fold_regions_and_ty(
    cx: ctxt,
    ty: t,
1378
    fldr: fn(r: Region) -> Region,
1379 1380 1381 1382
    fldfnt: fn(t: t) -> t,
    fldt: fn(t: t) -> t) -> t {

    fn fold_substs(
N
Niko Matsakis 已提交
1383
        substs: &substs,
1384
        fldr: fn(r: Region) -> Region,
1385 1386
        fldt: fn(t: t) -> t) -> substs {

1387 1388
        {self_r: substs.self_r.map(|r| fldr(*r)),
         self_ty: substs.self_ty.map(|t| fldt(*t)),
1389
         tps: substs.tps.map(|t| fldt(*t))}
1390 1391 1392
    }

    let tb = ty::get(ty);
1393
    match tb.sty {
B
Brian Anderson 已提交
1394
      ty::ty_rptr(r, mt) => {
1395 1396 1397 1398
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
        ty::mk_rptr(cx, m_r, {ty: m_t, mutbl: mt.mutbl})
      }
B
Brian Anderson 已提交
1399
      ty_estr(vstore_slice(r)) => {
1400 1401 1402
        let m_r = fldr(r);
        ty::mk_estr(cx, vstore_slice(m_r))
      }
B
Brian Anderson 已提交
1403
      ty_evec(mt, vstore_slice(r)) => {
1404 1405 1406 1407
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
        ty::mk_evec(cx, {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
      }
N
Niko Matsakis 已提交
1408
      ty_enum(def_id, ref substs) => {
1409 1410
        ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
      }
1411 1412
      ty_struct(def_id, ref substs) => {
        ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1413
      }
1414 1415
      ty_trait(def_id, ref substs, vst) => {
        ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
1416
      }
1417
      ty_fn(ref f) => {
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
          let new_region = fldr(f.meta.region);
          let new_args = vec::map(f.sig.inputs, |a| {
              let new_ty = fldfnt(a.ty);
              {mode: a.mode, ty: new_ty}
          });
          let new_output = fldfnt(f.sig.output);
          ty::mk_fn(cx, FnTyBase {
              meta: FnMeta {region: new_region,
                            ..f.meta},
              sig: FnSig {inputs: new_args,
                          output: new_output}
          })
1430
      }
N
Niko Matsakis 已提交
1431
      ref sty => {
B
Brian Anderson 已提交
1432
        fold_sty_to_ty(cx, sty, |t| fldt(t))
1433 1434 1435 1436
      }
    }
}

1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
/* 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. */
fn apply_op_on_t_to_ty_fn(
    cx: ctxt,
    f: &FnTy,
    t_op: fn(t) -> t) -> FnTy
{
    let t0 = ty::mk_fn(cx, *f);
    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");
        }
    }
}

1461 1462 1463 1464 1465
// n.b. this function is intended to eventually replace fold_region() below,
// that is why its name is so similar.
fn fold_regions(
    cx: ctxt,
    ty: t,
1466
    fldr: fn(r: Region, in_fn: bool) -> Region) -> t {
1467 1468

    fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1469
               fldr: fn(Region, bool) -> Region) -> t {
B
Brian Anderson 已提交
1470
        if !type_has_regions(ty) { return ty; }
1471 1472
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1473 1474 1475
            |r| fldr(r, in_fn),
            |t| do_fold(cx, t, true, fldr),
            |t| do_fold(cx, t, in_fn, fldr))
1476 1477 1478 1479
    }
    do_fold(cx, ty, false, fldr)
}

1480
fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t {
N
Niko Matsakis 已提交
1481
    fn do_fold(cx: ctxt, t0: t, under_r: bool,
1482
               fldop: fn(Region, bool) -> Region) -> t {
N
Niko Matsakis 已提交
1483
        let tb = get(t0);
B
Brian Anderson 已提交
1484
        if !tbox_has_flag(tb, has_regions) { return t0; }
1485
        match tb.sty {
B
Brian Anderson 已提交
1486
          ty_rptr(r, {ty: t1, mutbl: m}) => {
N
Niko Matsakis 已提交
1487 1488 1489
            let m_r = fldop(r, under_r);
            let m_t1 = do_fold(cx, t1, true, fldop);
            ty::mk_rptr(cx, m_r, {ty: m_t1, mutbl: m})
1490
          }
B
Brian Anderson 已提交
1491
          ty_estr(vstore_slice(r)) => {
1492 1493 1494
            let m_r = fldop(r, under_r);
            ty::mk_estr(cx, vstore_slice(m_r))
          }
B
Brian Anderson 已提交
1495
          ty_evec({ty: t1, mutbl: m}, vstore_slice(r)) => {
1496 1497 1498 1499
            let m_r = fldop(r, under_r);
            let m_t1 = do_fold(cx, t1, true, fldop);
            ty::mk_evec(cx, {ty: m_t1, mutbl: m}, vstore_slice(m_r))
          }
B
Brian Anderson 已提交
1500
          ty_fn(_) => {
N
Niko Matsakis 已提交
1501 1502
            // do not recurse into functions, which introduce fresh bindings
            t0
1503
          }
N
Niko Matsakis 已提交
1504
          ref sty => {
B
Brian Anderson 已提交
1505
            do fold_sty_to_ty(cx, sty) |t| {
N
Niko Matsakis 已提交
1506
                do_fold(cx, t, under_r, fldop)
1507
            }
1508
          }
N
Niko Matsakis 已提交
1509
      }
1510
    }
1511

N
Niko Matsakis 已提交
1512
    do_fold(cx, t0, false, fldop)
1513 1514
}

1515
// Substitute *only* type parameters.  Used in trans where regions are erased.
1516 1517
fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
    if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1518
    let tb = ty::get(typ);
1519
    if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1520
    match tb.sty {
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
        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))
        }
1533 1534 1535
    }
}

N
Niko Matsakis 已提交
1536
fn substs_is_noop(substs: &substs) -> bool {
1537 1538 1539
    substs.tps.len() == 0u &&
        substs.self_r.is_none() &&
        substs.self_ty.is_none()
1540 1541
}

N
Niko Matsakis 已提交
1542
fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
P
Paul Stansifer 已提交
1543
    fmt!("substs(self_r=%s, self_ty=%s, tps=%?)",
1544 1545
         substs.self_r.map_default(~"none", |r| region_to_str(cx, *r)),
         substs.self_ty.map_default(~"none", |t| ty_to_str(cx, *t)),
1546
         tys_to_str(cx, substs.tps))
1547 1548
}

1549 1550 1551
fn param_bound_to_str(cx: ctxt, pb: &param_bound) -> ~str {
    match *pb {
        bound_copy => ~"copy",
B
Brian Anderson 已提交
1552
        bound_durable => ~"durable",
1553 1554 1555 1556 1557 1558 1559
        bound_send => ~"send",
        bound_const => ~"const",
        bound_trait(t) => ty_to_str(cx, t)
    }
}

fn param_bounds_to_str(cx: ctxt, pbs: param_bounds) -> ~str {
1560
    fmt!("%?", pbs.map(|pb| param_bound_to_str(cx, pb)))
1561 1562
}

1563
fn subst(cx: ctxt,
N
Niko Matsakis 已提交
1564
         substs: &substs,
1565 1566
         typ: t) -> t {

P
Paul Stansifer 已提交
1567
    debug!("subst(substs=%s, typ=%s)",
1568
           substs_to_str(cx, substs),
P
Paul Stansifer 已提交
1569
           ty_to_str(cx, typ));
N
Niko Matsakis 已提交
1570

B
Brian Anderson 已提交
1571
    if substs_is_noop(substs) { return typ; }
1572
    let r = do_subst(cx, substs, typ);
P
Paul Stansifer 已提交
1573
    debug!("  r = %s", ty_to_str(cx, r));
B
Brian Anderson 已提交
1574
    return r;
1575 1576

    fn do_subst(cx: ctxt,
N
Niko Matsakis 已提交
1577
                substs: &substs,
1578 1579
                typ: t) -> t {
        let tb = get(typ);
B
Brian Anderson 已提交
1580
        if !tbox_has_flag(tb, needs_subst) { return typ; }
1581
        match tb.sty {
B
Brian Anderson 已提交
1582 1583 1584
          ty_param(p) => substs.tps[p.idx],
          ty_self => substs.self_ty.get(),
          _ => {
1585 1586
            fold_regions_and_ty(
                cx, typ,
1587
                |r| match r {
1588
                    re_bound(br_self) => substs.self_r.expect(
1589
                        fmt!("ty::subst: \
1590 1591
                      Reference to self region when given substs with no \
                      self region, ty = %s", ty_to_str(cx, typ))),
B
Brian Anderson 已提交
1592
                    _ => r
1593
                },
B
Brian Anderson 已提交
1594 1595
                |t| do_subst(cx, substs, t),
                |t| do_subst(cx, substs, t))
1596 1597
          }
        }
N
Niko Matsakis 已提交
1598 1599
    }
}
1600

1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
// Performs substitutions on a set of substitutions (result = super(sub)) to
// yield a new set of substitutions. This is used in trait inheritance.
fn subst_substs(cx: ctxt, super: &substs, sub: &substs) -> substs {
    {
        self_r: super.self_r,
        self_ty: super.self_ty.map(|typ| subst(cx, sub, *typ)),
        tps: super.tps.map(|typ| subst(cx, sub, *typ))
    }
}

1611
// Type utilities
1612

1613
fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
1614

1615
fn type_is_bot(ty: t) -> bool { get(ty).sty == ty_bot }
1616

1617
fn type_is_ty_var(ty: t) -> bool {
1618
    match get(ty).sty {
1619
      ty_infer(TyVar(_)) => true,
B
Brian Anderson 已提交
1620
      _ => false
1621 1622 1623
    }
}

1624
fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
1625

1626
fn type_is_structural(ty: t) -> bool {
1627
    match get(ty).sty {
1628
      ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_fn(_) |
1629 1630 1631
      ty_trait(*) |
      ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
B
Brian Anderson 已提交
1632 1633
      => true,
      _ => false
1634 1635 1636
    }
}

1637
fn type_is_copyable(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
1638
    return kind_can_be_copied(type_kind(cx, ty));
1639 1640
}

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

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

1655
fn sequence_element_type(cx: ctxt, ty: t) -> t {
1656
    match get(ty).sty {
B
Brian Anderson 已提交
1657 1658 1659 1660
      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"),
1661 1662 1663
    }
}

1664
fn get_element_type(ty: t, i: uint) -> t {
1665
    match get(ty).sty {
B
Brian Anderson 已提交
1666 1667 1668
      ty_rec(flds) => return flds[i].mt.ty,
      ty_tup(ts) => return ts[i],
      _ => fail ~"get_element_type called on invalid type"
1669 1670 1671
    }
}

1672
pure fn type_is_box(ty: t) -> bool {
1673
    match get(ty).sty {
B
Brian Anderson 已提交
1674 1675
      ty_box(_) => return true,
      _ => return false
1676
    }
M
Marijn Haverbeke 已提交
1677 1678
}

1679
pure fn type_is_boxed(ty: t) -> bool {
1680
    match get(ty).sty {
1681
      ty_box(_) | ty_opaque_box |
B
Brian Anderson 已提交
1682 1683
      ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
      _ => false
1684 1685 1686
    }
}

1687
pure fn type_is_region_ptr(ty: t) -> bool {
1688
    match get(ty).sty {
B
Brian Anderson 已提交
1689 1690
      ty_rptr(_, _) => true,
      _ => false
1691 1692 1693
    }
}

1694
pure fn type_is_slice(ty: t) -> bool {
1695
    match get(ty).sty {
B
Brian Anderson 已提交
1696 1697
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
      _ => return false
1698 1699 1700
    }
}

1701
pure fn type_is_unique_box(ty: t) -> bool {
1702
    match get(ty).sty {
B
Brian Anderson 已提交
1703 1704
      ty_uniq(_) => return true,
      _ => return false
1705
    }
M
Marijn Haverbeke 已提交
1706
}
1707

1708
pure fn type_is_unsafe_ptr(ty: t) -> bool {
1709
    match get(ty).sty {
B
Brian Anderson 已提交
1710 1711
      ty_ptr(_) => return true,
      _ => return false
1712 1713 1714
    }
}

1715
pure fn type_is_vec(ty: t) -> bool {
1716
    return match get(ty).sty {
B
Brian Anderson 已提交
1717 1718 1719
          ty_evec(_, _) | ty_unboxed_vec(_) => true,
          ty_estr(_) => true,
          _ => false
B
Brian Anderson 已提交
1720
        };
M
Marijn Haverbeke 已提交
1721 1722
}

1723
pure fn type_is_unique(ty: t) -> bool {
1724
    match get(ty).sty {
B
Brian Anderson 已提交
1725 1726 1727 1728
      ty_uniq(_) => return true,
      ty_evec(_, vstore_uniq) => true,
      ty_estr(vstore_uniq) => true,
      _ => return false
B
Brian Anderson 已提交
1729
    }
1730 1731
}

1732 1733 1734 1735 1736
/*
 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.)
*/
1737
pure fn type_is_scalar(ty: t) -> bool {
1738
    match get(ty).sty {
1739
      ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1740 1741
      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
      ty_ptr(_) => true,
B
Brian Anderson 已提交
1742
      _ => false
M
Marijn Haverbeke 已提交
1743
    }
1744 1745
}

1746
fn type_is_immediate(ty: t) -> bool {
B
Brian Anderson 已提交
1747
    return type_is_scalar(ty) || type_is_boxed(ty) ||
1748
        type_is_unique(ty) || type_is_region_ptr(ty);
1749 1750
}

1751
fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1752
    match cx.needs_drop_cache.find(ty) {
B
Brian Anderson 已提交
1753 1754
      Some(result) => return result,
      None => {/* fall through */ }
M
Marijn Haverbeke 已提交
1755 1756
    }

1757
    let mut accum = false;
1758
    let result = match get(ty).sty {
M
Marijn Haverbeke 已提交
1759
      // scalar types
1760
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1761
      ty_type | ty_ptr(_) | ty_rptr(_, _) |
1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773
      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,

1774 1775 1776 1777
      ty_trait(_, _, vstore_box) |
      ty_trait(_, _, vstore_uniq) => true,
      ty_trait(_, _, vstore_fixed(_)) |
      ty_trait(_, _, vstore_slice(_)) => false,
1778

1779
      ty_param(*) | ty_infer(*) | ty_err => true,
1780

B
Brian Anderson 已提交
1781 1782 1783
      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 已提交
1784 1785 1786
        for flds.each |f| {
            if type_needs_drop(cx, f.mt.ty) { accum = true; }
        }
1787
        accum
M
Marijn Haverbeke 已提交
1788
      }
1789 1790
      ty_struct(did, ref substs) => {
         // Any struct with a dtor needs a drop
1791
         ty_dtor(cx, did).is_present() || {
1792
             for vec::each(ty::struct_fields(cx, did, substs)) |f| {
1793 1794 1795
                 if type_needs_drop(cx, f.mt.ty) { accum = true; }
             }
             accum
1796
         }
1797
      }
B
Brian Anderson 已提交
1798
      ty_tup(elts) => {
1799
          for elts.each |m| { if type_needs_drop(cx, *m) { accum = true; } }
1800
        accum
1801
      }
N
Niko Matsakis 已提交
1802
      ty_enum(did, ref substs) => {
1803
        let variants = enum_variants(cx, did);
1804
          for vec::each(*variants) |variant| {
B
Brian Anderson 已提交
1805
              for variant.args.each |aty| {
M
Marijn Haverbeke 已提交
1806
                // Perform any type parameter substitutions.
1807
                let arg_ty = subst(cx, substs, *aty);
1808
                if type_needs_drop(cx, arg_ty) { accum = true; }
1809
            }
1810
            if accum { break; }
1811
        }
1812
        accum
M
Marijn Haverbeke 已提交
1813
      }
N
Niko Matsakis 已提交
1814
      ty_fn(ref fty) => {
1815
        match fty.meta.proto {
1816 1817
          ast::ProtoBare | ast::ProtoBorrowed => false,
          ast::ProtoBox | ast::ProtoUniq => true,
1818 1819
        }
      }
1820
    };
1821

1822
    cx.needs_drop_cache.insert(ty, result);
B
Brian Anderson 已提交
1823
    return result;
1824 1825
}

1826 1827 1828 1829 1830
// 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.
fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1831
    match cx.needs_unwind_cleanup_cache.find(ty) {
B
Brian Anderson 已提交
1832 1833
      Some(result) => return result,
      None => ()
1834 1835
    }

1836 1837 1838 1839
    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 已提交
1840
    return needs_unwind_cleanup;
1841 1842 1843
}

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

1847
    // Prevent infinite recursion
1848
    match tycache.find(ty) {
B
Brian Anderson 已提交
1849 1850
      Some(_) => return false,
      None => { tycache.insert(ty, ()); }
1851
    }
1852

1853
    let mut encountered_box = encountered_box;
1854
    let mut needs_unwind_cleanup = false;
B
Brian Anderson 已提交
1855
    do maybe_walk_ty(ty) |ty| {
1856
        let old_encountered_box = encountered_box;
1857
        let result = match get(ty).sty {
B
Brian Anderson 已提交
1858
          ty_box(_) | ty_opaque_box => {
1859 1860 1861
            encountered_box = true;
            true
          }
1862 1863
          ty_nil | ty_bot | ty_bool |
          ty_int(_) | ty_uint(_) | ty_float(_) |
B
Brian Anderson 已提交
1864
          ty_rec(_) | ty_tup(_) | ty_ptr(_) => {
1865 1866
            true
          }
N
Niko Matsakis 已提交
1867
          ty_enum(did, ref substs) => {
1868
            for vec::each(*enum_variants(cx, did)) |v| {
B
Brian Anderson 已提交
1869
                for v.args.each |aty| {
1870
                    let t = subst(cx, substs, *aty);
1871 1872 1873
                    needs_unwind_cleanup |=
                        type_needs_unwind_cleanup_(cx, t, tycache,
                                                   encountered_box);
1874 1875 1876 1877
                }
            }
            !needs_unwind_cleanup
          }
M
Michael Sullivan 已提交
1878
          ty_uniq(_) |
1879 1880 1881 1882
          ty_estr(vstore_uniq) |
          ty_estr(vstore_box) |
          ty_evec(_, vstore_uniq) |
          ty_evec(_, vstore_box)
B
Brian Anderson 已提交
1883
          => {
1884 1885 1886 1887 1888 1889 1890 1891 1892
            // 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 已提交
1893
          _ => {
1894 1895 1896
            needs_unwind_cleanup = true;
            false
          }
1897 1898 1899 1900
        };

        encountered_box = old_encountered_box;
        result
1901 1902
    }

B
Brian Anderson 已提交
1903
    return needs_unwind_cleanup;
1904 1905
}

1906
enum Kind { kind_(u32) }
1907

1908
/// can be copied (implicitly or explicitly)
1909
const KIND_MASK_COPY         : u32 = 0b000000000000000000000000001_u32;
1910

B
Brian Anderson 已提交
1911
/// can be sent: no shared box, borrowed ptr (must imply DURABLE)
1912
const KIND_MASK_SEND         : u32 = 0b000000000000000000000000010_u32;
1913

B
Brian Anderson 已提交
1914 1915
/// is durable (no borrowed ptrs)
const KIND_MASK_DURABLE      : u32 = 0b000000000000000000000000100_u32;
1916 1917

/// is deeply immutable
1918
const KIND_MASK_CONST        : u32 = 0b000000000000000000000001000_u32;
1919 1920

/// can be implicitly copied (must imply COPY)
1921 1922 1923 1924
const KIND_MASK_IMPLICIT     : u32 = 0b000000000000000000000010000_u32;

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

1926
fn kind_noncopyable() -> Kind {
1927 1928 1929
    kind_(0u32)
}

1930
fn kind_copyable() -> Kind {
1931 1932 1933
    kind_(KIND_MASK_COPY)
}

1934
fn kind_implicitly_copyable() -> Kind {
1935 1936 1937
    kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY)
}

1938
fn kind_safe_for_default_mode() -> Kind {
1939 1940 1941 1942
    // similar to implicit copy, but always includes vectors and strings
    kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY)
}

1943
fn kind_implicitly_sendable() -> Kind {
1944 1945 1946
    kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_SEND)
}

1947
fn kind_safe_for_default_mode_send() -> Kind {
1948 1949 1950 1951 1952 1953
    // similar to implicit copy, but always includes vectors and strings
    kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT |
          KIND_MASK_COPY | KIND_MASK_SEND)
}


1954
fn kind_send_copy() -> Kind {
1955 1956
    kind_(KIND_MASK_COPY | KIND_MASK_SEND)
}
1957

1958
fn kind_send_only() -> Kind {
1959 1960 1961
    kind_(KIND_MASK_SEND)
}

1962
fn kind_const() -> Kind {
1963 1964 1965
    kind_(KIND_MASK_CONST)
}

B
Brian Anderson 已提交
1966 1967
fn kind_durable() -> Kind {
    kind_(KIND_MASK_DURABLE)
1968 1969
}

1970
fn kind_top() -> Kind {
1971 1972 1973
    kind_(0xffffffffu32)
}

1974
fn remove_const(k: Kind) -> Kind {
1975
    k - kind_const()
1976 1977
}

1978
fn remove_implicit(k: Kind) -> Kind {
1979
    k - kind_(KIND_MASK_IMPLICIT | KIND_MASK_DEFAULT_MODE)
1980 1981
}

1982
fn remove_send(k: Kind) -> Kind {
1983 1984 1985
    k - kind_(KIND_MASK_SEND)
}

B
Brian Anderson 已提交
1986 1987
fn remove_durable_send(k: Kind) -> Kind {
    k - kind_(KIND_MASK_DURABLE) - kind_(KIND_MASK_SEND)
1988 1989
}

1990
fn remove_copyable(k: Kind) -> Kind {
1991
    k - kind_(KIND_MASK_COPY | KIND_MASK_DEFAULT_MODE)
1992 1993
}

1994
impl Kind : ops::BitAnd<Kind,Kind> {
1995
    pure fn bitand(&self, other: &Kind) -> Kind {
1996
        unsafe {
1997
            lower_kind(*self, *other)
1998 1999 2000
        }
    }
}
2001

2002
impl Kind : ops::BitOr<Kind,Kind> {
2003
    pure fn bitor(&self, other: &Kind) -> Kind {
2004
        unsafe {
2005
            raise_kind(*self, *other)
2006 2007 2008
        }
    }
}
2009

2010
impl Kind : ops::Sub<Kind,Kind> {
2011
    pure fn sub(&self, other: &Kind) -> Kind {
2012
        unsafe {
2013
            kind_(**self & !**other)
2014 2015 2016
        }
    }
}
2017

2018
// Using these query functions is preferable to direct comparison or matching
2019 2020
// against the kind constants, as we may modify the kind hierarchy in the
// future.
2021
pure fn kind_can_be_implicitly_copied(k: Kind) -> bool {
2022
    *k & KIND_MASK_IMPLICIT == KIND_MASK_IMPLICIT
2023 2024
}

2025
pure fn kind_is_safe_for_default_mode(k: Kind) -> bool {
2026 2027 2028
    *k & KIND_MASK_DEFAULT_MODE == KIND_MASK_DEFAULT_MODE
}

2029
pure fn kind_can_be_copied(k: Kind) -> bool {
2030
    *k & KIND_MASK_COPY == KIND_MASK_COPY
2031 2032
}

2033
pure fn kind_can_be_sent(k: Kind) -> bool {
2034 2035 2036
    *k & KIND_MASK_SEND == KIND_MASK_SEND
}

B
Brian Anderson 已提交
2037 2038
pure fn kind_is_durable(k: Kind) -> bool {
    *k & KIND_MASK_DURABLE == KIND_MASK_DURABLE
2039 2040
}

2041
fn meta_kind(p: FnMeta) -> Kind {
2042
    match p.proto { // XXX consider the kind bounds!
2043
        ast::ProtoBare => {
B
Brian Anderson 已提交
2044
            kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2045 2046 2047 2048 2049
        }
        ast::ProtoBorrowed => {
            kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE)
        }
        ast::ProtoBox => {
B
Brian Anderson 已提交
2050
            kind_safe_for_default_mode() | kind_durable()
2051 2052
        }
        ast::ProtoUniq => {
B
Brian Anderson 已提交
2053
            kind_send_copy() | kind_durable()
2054
        }
2055 2056 2057
    }
}

2058
fn kind_lteq(a: Kind, b: Kind) -> bool {
2059
    *a & *b == *a
M
Marijn Haverbeke 已提交
2060 2061
}

2062
fn lower_kind(a: Kind, b: Kind) -> Kind {
2063 2064 2065
    kind_(*a & *b)
}

2066
fn raise_kind(a: Kind, b: Kind) -> Kind {
2067
    kind_(*a | *b)
M
Marijn Haverbeke 已提交
2068 2069
}

2070 2071
#[test]
fn test_kinds() {
2072 2073
    // The kind "lattice" is defined by the subset operation on the
    // set of permitted operations.
2074 2075
    assert kind_lteq(kind_send_copy(), kind_send_copy());
    assert kind_lteq(kind_copyable(), kind_send_copy());
2076
    assert kind_lteq(kind_copyable(), kind_copyable());
2077
    assert kind_lteq(kind_noncopyable(), kind_send_copy());
2078 2079
    assert kind_lteq(kind_noncopyable(), kind_copyable());
    assert kind_lteq(kind_noncopyable(), kind_noncopyable());
2080 2081
    assert kind_lteq(kind_copyable(), kind_implicitly_copyable());
    assert kind_lteq(kind_copyable(), kind_implicitly_sendable());
2082 2083
    assert kind_lteq(kind_send_copy(), kind_implicitly_sendable());
    assert !kind_lteq(kind_send_copy(), kind_implicitly_copyable());
2084 2085 2086 2087 2088 2089
    assert !kind_lteq(kind_copyable(), kind_send_only());
}

// 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
2090
// implicitly copied and to compute whether things have const kind.
2091
fn mutability_kind(m: mutability) -> Kind {
2092
    match (m) {
B
Brian Anderson 已提交
2093 2094 2095
      m_mutbl => remove_const(remove_implicit(kind_top())),
      m_const => remove_implicit(kind_top()),
      m_imm => kind_top()
2096 2097 2098
    }
}

2099
fn mutable_type_kind(cx: ctxt, ty: mt) -> Kind {
2100
    lower_kind(mutability_kind(ty.mutbl), type_kind(cx, ty.ty))
2101 2102
}

2103
fn type_kind(cx: ctxt, ty: t) -> Kind {
2104
    match cx.kind_cache.find(ty) {
B
Brian Anderson 已提交
2105 2106
      Some(result) => return result,
      None => {/* fall through */ }
2107 2108 2109
    }

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

2112
    let mut result = match get(ty).sty {
2113
      // Scalar and unique types are sendable, constant, and owned
2114
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
B
Brian Anderson 已提交
2115
      ty_ptr(_) => {
B
Brian Anderson 已提交
2116
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2117 2118
      }

2119
      // Implicit copyability of strs is configurable
B
Brian Anderson 已提交
2120
      ty_estr(vstore_uniq) => {
2121
        if cx.vecs_implicitly_copyable {
B
Brian Anderson 已提交
2122
            kind_implicitly_sendable() | kind_const() | kind_durable()
2123
        } else {
B
Brian Anderson 已提交
2124
            kind_send_copy() | kind_const() | kind_durable()
2125
        }
2126
      }
2127 2128

      // functions depend on the protocol
2129
      ty_fn(ref f) => meta_kind(f.meta),
2130 2131 2132

      // Those with refcounts raise noncopyable to copyable,
      // lower sendable to copyable. Therefore just set result to copyable.
B
Brian Anderson 已提交
2133
      ty_box(tm) => {
2134
        remove_send(mutable_type_kind(cx, tm) | kind_safe_for_default_mode())
2135
      }
2136

2137
      // Trait instances are (for now) like shared boxes, basically
B
Brian Anderson 已提交
2138
      ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_durable(),
2139

2140 2141 2142 2143 2144
      // 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),

      // General region pointers are copyable but NOT owned nor sendable
B
Brian Anderson 已提交
2145
      ty_rptr(_, _) => kind_safe_for_default_mode(),
2146

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

2151
      // Implicit copyability of vecs is configurable
B
Brian Anderson 已提交
2152
      ty_evec(tm, vstore_uniq) => {
2153
          if cx.vecs_implicitly_copyable {
2154
              mutable_type_kind(cx, tm)
2155 2156 2157
          } else {
              remove_implicit(mutable_type_kind(cx, tm))
          }
2158
      }
2159

2160 2161 2162
      // 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 已提交
2163
      ty_evec(tm, vstore_box) => {
2164
        remove_send(kind_safe_for_default_mode() | mutable_type_kind(cx, tm))
2165
      }
2166 2167 2168
      ty_evec(tm, vstore_slice(re_static)) => {
        kind_safe_for_default_mode() | mutable_type_kind(cx, tm)
      }
B
Brian Anderson 已提交
2169
      ty_evec(tm, vstore_slice(_)) => {
B
Brian Anderson 已提交
2170 2171
        remove_durable_send(kind_safe_for_default_mode() |
                           mutable_type_kind(cx, tm))
2172
      }
B
Brian Anderson 已提交
2173
      ty_evec(tm, vstore_fixed(_)) => {
2174
        mutable_type_kind(cx, tm)
2175
      }
2176 2177

      // All estrs are copyable; uniques and interiors are sendable.
B
Brian Anderson 已提交
2178
      ty_estr(vstore_box) => {
B
Brian Anderson 已提交
2179
        kind_safe_for_default_mode() | kind_const() | kind_durable()
2180
      }
2181 2182 2183
      ty_estr(vstore_slice(re_static)) => {
        kind_safe_for_default_mode() | kind_send_copy() | kind_const()
      }
B
Brian Anderson 已提交
2184
      ty_estr(vstore_slice(_)) => {
2185
        kind_safe_for_default_mode() | kind_const()
2186
      }
B
Brian Anderson 已提交
2187
      ty_estr(vstore_fixed(_)) => {
B
Brian Anderson 已提交
2188
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2189
      }
2190

2191
      // Records lower to the lowest of their members.
B
Brian Anderson 已提交
2192
      ty_rec(flds) => {
2193
        let mut lowest = kind_top();
B
Brian Anderson 已提交
2194
        for flds.each |f| {
2195
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
2196
        }
M
Marijn Haverbeke 已提交
2197
        lowest
2198
      }
2199

2200 2201
      ty_struct(did, ref substs) => {
        // Structs are sendable if all their fields are sendable,
2202
        // likewise for copyable...
2203 2204
        // also factor out this code, copied from the records case
        let mut lowest = kind_top();
2205
        let flds = struct_fields(cx, did, substs);
B
Brian Anderson 已提交
2206
        for flds.each |f| {
2207 2208
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
        }
2209
        // ...but structs with dtors are never copyable (they can be
2210 2211
        // sendable)
        if ty::has_dtor(cx, did) {
2212
           lowest = remove_copyable(lowest);
2213
        }
2214
        lowest
2215
      }
2216

2217
      // Tuples lower to the lowest of their members.
B
Brian Anderson 已提交
2218
      ty_tup(tys) => {
2219
        let mut lowest = kind_top();
2220
        for tys.each |ty| { lowest = lower_kind(lowest, type_kind(cx, *ty)); }
M
Marijn Haverbeke 已提交
2221
        lowest
2222
      }
2223

2224
      // Enums lower to the lowest of their variants.
N
Niko Matsakis 已提交
2225
      ty_enum(did, ref substs) => {
2226
        let mut lowest = kind_top();
2227 2228
        let variants = enum_variants(cx, did);
        if vec::len(*variants) == 0u {
B
Brian Anderson 已提交
2229
            lowest = kind_send_only() | kind_durable();
2230
        } else {
2231
            for vec::each(*variants) |variant| {
B
Brian Anderson 已提交
2232
                for variant.args.each |aty| {
2233
                    // Perform any type parameter substitutions.
2234
                    let arg_ty = subst(cx, substs, *aty);
2235
                    lowest = lower_kind(lowest, type_kind(cx, arg_ty));
2236
                    if lowest == kind_noncopyable() { break; }
2237
                }
2238 2239
            }
        }
M
Marijn Haverbeke 已提交
2240
        lowest
2241
      }
2242

B
Brian Anderson 已提交
2243
      ty_param(p) => {
2244
        param_bounds_to_kind(cx.ty_param_bounds.get(p.def_id.node))
2245
      }
2246

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

2251
      ty_infer(_) => {
2252
        cx.sess.bug(~"Asked to compute kind of a type variable");
2253
      }
B
Brian Anderson 已提交
2254
      ty_type | ty_opaque_closure_ptr(_)
2255
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2256
        cx.sess.bug(~"Asked to compute kind of fictitious type");
2257
      }
M
Marijn Haverbeke 已提交
2258
    };
2259

2260 2261 2262
    // arbitrary threshold to prevent by-value copying of big records
    if kind_is_safe_for_default_mode(result) {
        if type_size(cx, ty) > 4 {
2263
            result = result - kind_(KIND_MASK_DEFAULT_MODE);
2264 2265 2266
        }
    }

2267
    cx.kind_cache.insert(ty, result);
B
Brian Anderson 已提交
2268
    return result;
2269 2270
}

2271 2272 2273 2274 2275
fn type_implicitly_moves(cx: ctxt, ty: t) -> bool {
    let kind = type_kind(cx, ty);
    !(kind_can_be_copied(kind) && kind_can_be_implicitly_copied(kind))
}

2276 2277 2278
/// 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 {
2279
    match get(ty).sty {
2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301
      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 已提交
2302
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2303 2304
      }

2305 2306
      ty_struct(did, ref substs) => {
        let flds = struct_fields(cx, did, substs);
T
Tim Chevalier 已提交
2307
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2308 2309
      }

B
Brian Anderson 已提交
2310
      ty_tup(tys) => {
T
Tim Chevalier 已提交
2311
        tys.foldl(0, |s, t| *s + type_size(cx, *t))
2312 2313
      }

N
Niko Matsakis 已提交
2314
      ty_enum(did, ref substs) => {
2315 2316 2317
        let variants = substd_enum_variants(cx, did, substs);
        variants.foldl( // find max size of any variant
            0,
T
Tim Chevalier 已提交
2318
            |m, v| uint::max(*m,
2319
                             // find size of this variant:
T
Tim Chevalier 已提交
2320
                             v.args.foldl(0, |s, a| *s + type_size(cx, *a))))
2321 2322
      }

B
Brian Anderson 已提交
2323
      ty_param(_) | ty_self => {
2324 2325 2326
        1
      }

2327
      ty_infer(_) => {
2328 2329
        cx.sess.bug(~"Asked to compute kind of a type variable");
      }
B
Brian Anderson 已提交
2330
      ty_type | ty_opaque_closure_ptr(_)
2331
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2332 2333 2334 2335 2336
        cx.sess.bug(~"Asked to compute kind of fictitious type");
      }
    }
}

2337
// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2338 2339
fn is_instantiable(cx: ctxt, r_ty: t) -> bool {

2340
    fn type_requires(cx: ctxt, seen: @mut ~[def_id],
2341
                     r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2342
        debug!("type_requires(%s, %s)?",
2343
               ty_to_str(cx, r_ty),
P
Paul Stansifer 已提交
2344
               ty_to_str(cx, ty));
2345 2346

        let r = {
2347
            get(r_ty).sty == get(ty).sty ||
2348 2349 2350
                subtypes_require(cx, seen, r_ty, ty)
        };

P
Paul Stansifer 已提交
2351
        debug!("type_requires(%s, %s)? %b",
2352 2353
               ty_to_str(cx, r_ty),
               ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2354
               r);
B
Brian Anderson 已提交
2355
        return r;
2356 2357
    }

2358
    fn subtypes_require(cx: ctxt, seen: @mut ~[def_id],
2359
                        r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2360
        debug!("subtypes_require(%s, %s)?",
2361
               ty_to_str(cx, r_ty),
P
Paul Stansifer 已提交
2362
               ty_to_str(cx, ty));
2363

2364
        let r = match get(ty).sty {
2365 2366 2367 2368 2369 2370
          ty_nil |
          ty_bot |
          ty_bool |
          ty_int(_) |
          ty_uint(_) |
          ty_float(_) |
2371
          ty_estr(_) |
2372
          ty_fn(_) |
2373
          ty_infer(_) |
2374
          ty_err |
2375
          ty_param(_) |
2376
          ty_self |
2377 2378 2379
          ty_type |
          ty_opaque_box |
          ty_opaque_closure_ptr(_) |
2380
          ty_evec(_, _) |
B
Brian Anderson 已提交
2381
          ty_unboxed_vec(_) => {
2382 2383 2384 2385
            false
          }
          ty_box(mt) |
          ty_uniq(mt) |
B
Brian Anderson 已提交
2386
          ty_rptr(_, mt) => {
B
Brian Anderson 已提交
2387
            return type_requires(cx, seen, r_ty, mt.ty);
2388 2389
          }

2390
          ty_ptr(*) => {
2391 2392 2393
            false           // unsafe ptrs can always be NULL
          }

B
Brian Anderson 已提交
2394
          ty_rec(fields) => {
B
Brian Anderson 已提交
2395
            do vec::any(fields) |field| {
2396 2397 2398 2399
                type_requires(cx, seen, r_ty, field.mt.ty)
            }
          }

2400
          ty_trait(_, _, _) => {
2401 2402 2403
            false
          }

2404
          ty_struct(ref did, _) if vec::contains(*seen, did) => {
2405 2406 2407
            false
          }

2408
          ty_struct(did, ref substs) => {
2409
              seen.push(did);
2410
              let r = vec::any(struct_fields(cx, did, substs),
2411
                               |f| type_requires(cx, seen, r_ty, f.mt.ty));
N
Niko Matsakis 已提交
2412
              seen.pop();
2413 2414 2415
            r
          }

B
Brian Anderson 已提交
2416
          ty_tup(ts) => {
N
Niko Matsakis 已提交
2417
            vec::any(ts, |t| type_requires(cx, seen, r_ty, *t))
2418 2419
          }

N
Niko Matsakis 已提交
2420
          ty_enum(ref did, _) if vec::contains(*seen, did) => {
2421 2422 2423
            false
          }

2424 2425 2426 2427 2428
            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 已提交
2429
                        let sty = subst(cx, substs, *aty);
2430 2431 2432
                        type_requires(cx, seen, r_ty, sty)
                    })
                });
N
Niko Matsakis 已提交
2433
                seen.pop();
2434 2435
                r
            }
2436 2437
        };

P
Paul Stansifer 已提交
2438
        debug!("subtypes_require(%s, %s)? %b",
2439 2440
               ty_to_str(cx, r_ty),
               ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2441
               r);
2442

B
Brian Anderson 已提交
2443
        return r;
2444 2445
    }

2446
    let seen = @mut ~[];
2447 2448 2449
    !subtypes_require(cx, seen, r_ty, r_ty)
}

N
Niko Matsakis 已提交
2450
fn type_structurally_contains(cx: ctxt, ty: t, test: fn(x: &sty) -> bool) ->
B
Brian Anderson 已提交
2451
   bool {
2452
    let sty = &get(ty).sty;
P
Paul Stansifer 已提交
2453
    debug!("type_structurally_contains: %s", ty_to_str(cx, ty));
B
Brian Anderson 已提交
2454
    if test(sty) { return true; }
N
Niko Matsakis 已提交
2455 2456
    match *sty {
      ty_enum(did, ref substs) => {
2457
        for vec::each(*enum_variants(cx, did)) |variant| {
B
Brian Anderson 已提交
2458
            for variant.args.each |aty| {
2459
                let sty = subst(cx, substs, *aty);
B
Brian Anderson 已提交
2460
                if type_structurally_contains(cx, sty, test) { return true; }
2461
            }
2462
        }
B
Brian Anderson 已提交
2463
        return false;
M
Marijn Haverbeke 已提交
2464
      }
B
Brian Anderson 已提交
2465
      ty_rec(fields) => {
B
Brian Anderson 已提交
2466
        for fields.each |field| {
B
Brian Anderson 已提交
2467 2468 2469
            if type_structurally_contains(cx, field.mt.ty, test) {
                return true;
            }
2470
        }
B
Brian Anderson 已提交
2471
        return false;
M
Marijn Haverbeke 已提交
2472
      }
2473 2474
      ty_struct(did, ref substs) => {
        for lookup_struct_fields(cx, did).each |field| {
2475
            let ft = lookup_field_type(cx, did, field.id, substs);
B
Brian Anderson 已提交
2476
            if type_structurally_contains(cx, ft, test) { return true; }
2477
        }
B
Brian Anderson 已提交
2478
        return false;
2479 2480
      }

B
Brian Anderson 已提交
2481
      ty_tup(ts) => {
B
Brian Anderson 已提交
2482
        for ts.each |tt| {
2483
            if type_structurally_contains(cx, *tt, test) { return true; }
2484
        }
B
Brian Anderson 已提交
2485
        return false;
2486
      }
B
Brian Anderson 已提交
2487
      ty_evec(mt, vstore_fixed(_)) => {
B
Brian Anderson 已提交
2488
        return type_structurally_contains(cx, mt.ty, test);
2489
      }
B
Brian Anderson 已提交
2490
      _ => return false
M
Marijn Haverbeke 已提交
2491 2492 2493
    }
}

2494
fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
2495
    return type_structurally_contains(cx, ty, |sty| {
N
Niko Matsakis 已提交
2496
        match *sty {
2497 2498
          ty_uniq(_) |
          ty_evec(_, vstore_uniq) |
B
Brian Anderson 已提交
2499 2500
          ty_estr(vstore_uniq) => true,
          _ => false,
2501
        }
2502
    });
2503 2504
}

2505
fn type_is_integral(ty: t) -> bool {
2506
    match get(ty).sty {
2507
      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) | ty_bool => true,
B
Brian Anderson 已提交
2508
      _ => false
M
Marijn Haverbeke 已提交
2509 2510 2511
    }
}

2512
fn type_is_fp(ty: t) -> bool {
2513
    match get(ty).sty {
2514
      ty_infer(FloatVar(_)) | ty_float(_) => true,
B
Brian Anderson 已提交
2515
      _ => false
M
Marijn Haverbeke 已提交
2516 2517 2518
    }
}

2519
fn type_is_numeric(ty: t) -> bool {
B
Brian Anderson 已提交
2520
    return type_is_integral(ty) || type_is_fp(ty);
2521 2522
}

2523
fn type_is_signed(ty: t) -> bool {
2524
    match get(ty).sty {
B
Brian Anderson 已提交
2525 2526
      ty_int(_) => true,
      _ => false
M
Marijn Haverbeke 已提交
2527 2528 2529
    }
}

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

            // Perform any type parameter substitutions.
2550
            let tup_ty = subst(cx, substs, tup_ty);
B
Brian Anderson 已提交
2551
            if !type_is_pod(cx, tup_ty) { result = false; }
2552
        }
B
Brian Anderson 已提交
2553
      }
B
Brian Anderson 已提交
2554
      ty_rec(flds) => {
B
Brian Anderson 已提交
2555
        for flds.each |f| {
B
Brian Anderson 已提交
2556
            if !type_is_pod(cx, f.mt.ty) { result = false; }
P
Patrick Walton 已提交
2557
        }
B
Brian Anderson 已提交
2558
      }
B
Brian Anderson 已提交
2559
      ty_tup(elts) => {
2560
        for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
B
Brian Anderson 已提交
2561
      }
B
Brian Anderson 已提交
2562 2563
      ty_estr(vstore_fixed(_)) => result = true,
      ty_evec(mt, vstore_fixed(_)) | ty_unboxed_vec(mt) => {
2564 2565
        result = type_is_pod(cx, mt.ty);
      }
B
Brian Anderson 已提交
2566 2567
      ty_param(_) => result = false,
      ty_opaque_closure_ptr(_) => result = true,
2568 2569
      ty_struct(did, ref substs) => {
        result = vec::any(lookup_struct_fields(cx, did), |f| {
2570 2571 2572
            let fty = ty::lookup_item_type(cx, f.id);
            let sty = subst(cx, substs, fty.ty);
            type_is_pod(cx, sty)
2573
        });
2574
      }
2575

B
Brian Anderson 已提交
2576
      ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2577 2578 2579
        result = false;
      }

2580
      ty_infer(*) | ty_self(*) | ty_err => {
2581
        cx.sess.bug(~"non concrete type in type_is_pod");
2582
      }
P
Patrick Walton 已提交
2583 2584
    }

B
Brian Anderson 已提交
2585
    return result;
P
Patrick Walton 已提交
2586 2587
}

2588
fn type_is_enum(ty: t) -> bool {
2589
    match get(ty).sty {
B
Brian Anderson 已提交
2590 2591
      ty_enum(_, _) => return true,
      _ => return false
2592 2593 2594
    }
}

P
Patrick Walton 已提交
2595
// Whether a type is enum like, that is a enum type with only nullary
2596
// constructors
2597
fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2598
    match get(ty).sty {
2599
      ty_enum(did, _) => {
2600
        let variants = enum_variants(cx, did);
B
Brian Anderson 已提交
2601
        let some_n_ary = vec::any(*variants, |v| vec::len(v.args) > 0u);
B
Brian Anderson 已提交
2602
        return !some_n_ary;
2603
      }
B
Brian Anderson 已提交
2604
      _ => return false
2605 2606 2607
    }
}

B
Brian Anderson 已提交
2608
fn type_param(ty: t) -> Option<uint> {
2609
    match get(ty).sty {
B
Brian Anderson 已提交
2610
      ty_param(p) => return Some(p.idx),
B
Brian Anderson 已提交
2611
      _ => {/* fall through */ }
2612
    }
B
Brian Anderson 已提交
2613
    return None;
2614 2615
}

2616 2617
// Returns the type and mutability of *t.
//
2618 2619 2620 2621
// The parameter `explicit` indicates if this is an *explicit* dereference.
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
    deref_sty(cx, &get(t).sty, explicit)
2622
}
2623 2624

fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
N
Niko Matsakis 已提交
2625
    match *sty {
B
Brian Anderson 已提交
2626
      ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
B
Brian Anderson 已提交
2627
        Some(mt)
2628 2629
      }

2630
      ty_ptr(mt) if explicit => {
B
Brian Anderson 已提交
2631
        Some(mt)
2632 2633
      }

N
Niko Matsakis 已提交
2634
      ty_enum(did, ref substs) => {
2635 2636 2637
        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]);
B
Brian Anderson 已提交
2638
            Some({ty: v_t, mutbl: ast::m_imm})
2639
        } else {
B
Brian Anderson 已提交
2640
            None
2641 2642 2643
        }
      }

2644 2645
      ty_struct(did, ref substs) => {
        let fields = struct_fields(cx, did, substs);
2646 2647 2648 2649 2650 2651 2652 2653
        if fields.len() == 1 && fields[0].ident ==
                syntax::parse::token::special_idents::unnamed_field {
            Some({ty: fields[0].mt.ty, mutbl: ast::m_imm})
        } else {
            None
        }
      }

B
Brian Anderson 已提交
2654
      _ => None
2655 2656 2657
    }
}

2658
fn type_autoderef(cx: ctxt, t: t) -> t {
2659
    let mut t = t;
2660
    loop {
2661
        match deref(cx, t, false) {
B
Brian Anderson 已提交
2662 2663
          None => return t,
          Some(mt) => t = mt.ty
2664 2665
        }
    }
2666 2667 2668
}

// Returns the type and mutability of t[i]
B
Brian Anderson 已提交
2669
fn index(cx: ctxt, t: t) -> Option<mt> {
2670
    index_sty(cx, &get(t).sty)
2671 2672
}

B
Brian Anderson 已提交
2673
fn index_sty(cx: ctxt, sty: &sty) -> Option<mt> {
N
Niko Matsakis 已提交
2674
    match *sty {
B
Brian Anderson 已提交
2675 2676 2677
      ty_evec(mt, _) => Some(mt),
      ty_estr(_) => Some({ty: mk_u8(cx), mutbl: ast::m_imm}),
      _ => None
2678
    }
2679 2680
}

2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696
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) =>
          to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f)
        }
    }
}
2697

2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711
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),
2712

2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731
          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),
        }
    }
}
2732

2733 2734 2735 2736 2737 2738 2739
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)
    }
}
2740

2741 2742 2743 2744 2745 2746
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)
    }
}
2747

2748 2749 2750 2751 2752 2753
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)
    }
}
2754

2755 2756 2757 2758 2759 2760
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)
    }
}
2761

2762 2763 2764 2765 2766 2767 2768 2769 2770 2771
impl FnMeta : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_5(&self.purity,
                               &self.proto,
                               &self.region,
                               &self.bounds,
                               &self.ret_style,
                               lsb0, f);
    }
}
2772

2773 2774 2775 2776 2777 2778 2779
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);
    }
}
2780

2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806
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),
2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817

          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) =>
2818 2819 2820
          to_bytes::iter_bytes_3(&12u8,
                                 &ft.meta,
                                 &ft.sig,
2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847
                                 lsb0, f),

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

2848
          ty_struct(ref did, ref substs) =>
2849 2850 2851 2852
          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),
2853 2854

          ty_err => 25u8.iter_bytes(lsb0, f)
2855 2856 2857 2858
        }
    }
}

B
Brian Anderson 已提交
2859 2860
fn br_hashmap<V:Copy>() -> HashMap<bound_region, V> {
    map::HashMap()
N
Niko Matsakis 已提交
2861 2862
}

2863
fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
P
Paul Stansifer 已提交
2864
    //io::println(fmt!("%?/%?", id, cx.node_types.size()));
2865
    match smallintmap::find(*cx.node_types, id as uint) {
B
Brian Anderson 已提交
2866 2867
       Some(t) => t,
       None => cx.sess.bug(
2868
           fmt!("node_id_to_type: no type for node `%s`",
P
Paul Stansifer 已提交
2869
                ast_map::node_id_to_str(cx.items, id,
P
Paul Stansifer 已提交
2870
                                        cx.sess.parse_sess.interner)))
T
Tim Chevalier 已提交
2871
    }
2872 2873
}

2874
fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2875
    match cx.node_type_substs.find(id) {
B
Brian Anderson 已提交
2876 2877
      None => return ~[],
      Some(ts) => return ts
2878 2879 2880
    }
}

2881
fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
B
Brian Anderson 已提交
2882
    return cx.node_type_substs.contains_key(id);
2883 2884
}

2885
// Type accessors for substructures of types
2886
fn ty_fn_args(fty: t) -> ~[arg] {
2887
    match get(fty).sty {
2888
      ty_fn(ref f) => f.sig.inputs,
B
Brian Anderson 已提交
2889
      _ => fail ~"ty_fn_args() called on non-fn type"
2890 2891 2892
    }
}

2893
fn ty_fn_proto(fty: t) -> Proto {
2894
    match get(fty).sty {
2895
      ty_fn(ref f) => f.meta.proto,
B
Brian Anderson 已提交
2896
      _ => fail ~"ty_fn_proto() called on non-fn type"
M
Marijn Haverbeke 已提交
2897
    }
G
Graydon Hoare 已提交
2898 2899
}

2900
fn ty_fn_purity(fty: t) -> ast::purity {
2901
    match get(fty).sty {
2902
      ty_fn(ref f) => f.meta.purity,
2903 2904 2905 2906
      _ => fail ~"ty_fn_purity() called on non-fn type"
    }
}

2907
pure fn ty_fn_ret(fty: t) -> t {
2908
    match get(fty).sty {
2909
      ty_fn(ref f) => f.sig.output,
B
Brian Anderson 已提交
2910
      _ => fail ~"ty_fn_ret() called on non-fn type"
2911
    }
G
Graydon Hoare 已提交
2912 2913
}

2914
fn ty_fn_ret_style(fty: t) -> ast::ret_style {
2915
    match get(fty).sty {
2916
      ty_fn(ref f) => f.meta.ret_style,
B
Brian Anderson 已提交
2917
      _ => fail ~"ty_fn_ret_style() called on non-fn type"
2918 2919 2920
    }
}

2921
fn is_fn_ty(fty: t) -> bool {
2922
    match get(fty).sty {
2923 2924 2925 2926 2927
      ty_fn(_) => true,
      _ => false
    }
}

2928
fn ty_region(ty: t) -> Region {
2929
    match get(ty).sty {
2930
      ty_rptr(r, _) => r,
2931
      ref s => fail fmt!("ty_region() invoked on non-rptr: %?", (*s))
2932
    }
G
Graydon Hoare 已提交
2933 2934
}

2935
// Returns a vec of all the input and output types of fty.
2936 2937
fn tys_in_fn_ty(fty: &FnTy) -> ~[t] {
    vec::append_one(fty.sig.inputs.map(|a| a.ty), fty.sig.output)
2938 2939
}

2940 2941
// Just checks whether it's a fn that returns bool,
// not its purity.
2942 2943
fn is_pred_ty(fty: t) -> bool {
    is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
2944 2945
}

2946
// Type accessors for AST nodes
N
Niko Matsakis 已提交
2947
fn block_ty(cx: ctxt, b: &ast::blk) -> t {
B
Brian Anderson 已提交
2948
    return node_id_to_type(cx, b.node.id);
2949
}
2950 2951


2952 2953
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
2954
fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
B
Brian Anderson 已提交
2955
    return node_id_to_type(cx, pat.id);
2956 2957
}

2958

2959 2960 2961 2962
// Returns the type of an expression as a monotype.
//
// NB: This type doesn't provide type parameter substitutions; e.g. if you
// ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
2963
// instead of "fn(t) -> T with T = int". If this isn't what you want, see
2964
// expr_ty_params_and_ty() below.
2965
fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
B
Brian Anderson 已提交
2966
    return node_id_to_type(cx, expr.id);
2967 2968
}

2969
fn expr_ty_params_and_ty(cx: ctxt,
2970
                         expr: @ast::expr) -> {params: ~[t], ty: t} {
B
Brian Anderson 已提交
2971
    return {params: node_id_to_type_params(cx, expr.id),
M
Marijn Haverbeke 已提交
2972
         ty: node_id_to_type(cx, expr.id)};
2973 2974
}

2975
fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
B
Brian Anderson 已提交
2976
    return node_id_has_type_params(cx, expr.id);
2977 2978
}

2979 2980
fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
                      id: ast::node_id)
B
Brian Anderson 已提交
2981
    -> Option<@~[param_bounds]> {
2982 2983 2984
    do method_map.find(id).map |method| {
        match method.origin {
          typeck::method_static(did) => {
2985 2986
            // n.b.: When we encode impl methods, the bounds
            // that we encode include both the impl bounds
2987 2988 2989 2990 2991
            // and then the method bounds themselves...
            ty::lookup_item_type(tcx, did).bounds
          }
          typeck::method_param({trait_id:trt_id,
                                method_num:n_mth, _}) |
2992 2993
          typeck::method_trait(trt_id, n_mth, _) |
          typeck::method_self(trt_id, n_mth) => {
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005
            // ...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;
            let mth = ty::trait_methods(tcx, trt_id)[n_mth];
            @(vec::append(*trt_bounds, *mth.tps))
          }
        }
    }
}

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 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053
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));
        }
    }
}

fn expr_is_lval(tcx: ctxt,
                method_map: typeck::method_map,
                e: @ast::expr) -> bool {
    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.
enum ExprKind {
    LvalueExpr,
    RvalueDpsExpr,
    RvalueDatumExpr,
    RvalueStmtExpr
}

fn expr_kind(tcx: ctxt,
             method_map: typeck::method_map,
             expr: @ast::expr) -> ExprKind {
    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(*) |
3054
                ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080

                // 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(*) |
3081
        ast::expr_method_call(*) |
3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095
        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_unary_move(*) |
        ast::expr_repeat(*) |
        ast::expr_lit(@{node: lit_str(_), _}) |
3096
        ast::expr_vstore(_, ast::expr_vstore_slice) |
3097
        ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3098
        ast::expr_vstore(_, ast::expr_vstore_fixed(_)) |
3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146
        ast::expr_vec(*) => {
            RvalueDpsExpr
        }

        ast::expr_cast(*) => {
            match smallintmap::find(*tcx.node_types, expr.id as uint) {
                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(*) |
3147
        ast::expr_vstore(_, ast::expr_vstore_box) |
3148
        ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3149
        ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3150 3151 3152
            RvalueDatumExpr
        }

3153 3154
        ast::expr_paren(e) => expr_kind(tcx, method_map, e),

3155 3156 3157 3158 3159
        ast::expr_mac(*) => {
            tcx.sess.span_bug(
                expr.span,
                ~"macro expression remains after expansion");
        }
M
Marijn Haverbeke 已提交
3160 3161 3162
    }
}

3163
fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3164
    match s.node {
B
Brian Anderson 已提交
3165
      ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
B
Brian Anderson 已提交
3166
        return id;
3167
      }
3168
      ast::stmt_mac(*) => fail ~"unexpanded macro in trans"
3169 3170 3171
    }
}

3172
fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3173
    let mut i = 0u;
B
Brian Anderson 已提交
3174 3175
    for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
    return None;
3176 3177
}

3178 3179 3180 3181 3182 3183 3184 3185 3186
fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field]) -> uint {
    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))));
}

3187 3188
fn get_field(tcx: ctxt, rec_ty: t, id: ast::ident) -> field {
    match vec::find(get_fields(rec_ty), |f| f.ident == id) {
B
Brian Anderson 已提交
3189
      Some(f) => f,
3190
      // Do we only call this when we know the field is legit?
3191
      None => fail (fmt!("get_field: ty doesn't have a field %s",
3192
                         tcx.sess.str_of(id)))
T
Tim Chevalier 已提交
3193 3194 3195
    }
}

3196
fn get_fields(rec_ty:t) -> ~[field] {
3197
    match get(rec_ty).sty {
3198 3199 3200
      ty_rec(fields) => fields,
      // Can we check at the caller?
      _ => fail ~"get_fields: not a record type"
3201 3202 3203
    }
}

B
Brian Anderson 已提交
3204
fn method_idx(id: ast::ident, meths: &[method]) -> Option<uint> {
3205
    let mut i = 0u;
B
Brian Anderson 已提交
3206 3207
    for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; }
    return None;
3208 3209
}

3210 3211 3212 3213 3214 3215
/// 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.
fn param_tys_in_type(ty: t) -> ~[param_ty] {
    let mut rslt = ~[];
    do walk_ty(ty) |ty| {
3216
        match get(ty).sty {
B
Brian Anderson 已提交
3217
          ty_param(p) => {
3218
            rslt.push(p);
3219
          }
B
Brian Anderson 已提交
3220
          _ => ()
3221 3222 3223 3224 3225
        }
    }
    rslt
}

3226
fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3227 3228 3229

    // Returns a vec of all the type variables occurring in `ty`. It may
    // contain duplicates.  (Integral type vars aren't counted.)
3230
    fn vars_in_type(ty: t) -> ~[TyVid] {
3231
        let mut rslt = ~[];
B
Brian Anderson 已提交
3232
        do walk_ty(ty) |ty| {
3233
            match get(ty).sty {
3234
              ty_infer(TyVar(v)) => rslt.push(v),
B
Brian Anderson 已提交
3235 3236
              _ => ()
            }
3237 3238 3239 3240
        }
        rslt
    }

3241
    // Fast path
B
Brian Anderson 已提交
3242
    if !type_needs_infer(rt) { return; }
B
Brian Anderson 已提交
3243

T
Tim Chevalier 已提交
3244
    // Occurs check!
N
Niko Matsakis 已提交
3245
    if vec::contains(vars_in_type(rt), &vid) {
T
Tim Chevalier 已提交
3246 3247 3248
            // 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.
3249
            tcx.sess.span_fatal
3250
                (sp, ~"type inference failed because I \
3251
                     could not find a type\n that's both of the form "
3252
                 + ty_to_str(tcx, mk_var(tcx, vid)) +
3253 3254
                 ~" and of the form " + ty_to_str(tcx, rt) +
                 ~" - such a type would have to be infinitely large.");
3255
    }
T
Tim Chevalier 已提交
3256
}
3257

3258 3259
// Maintains a little union-set tree for inferred modes.  `canon()` returns
// the current head value for `m0`.
B
Brian Anderson 已提交
3260
fn canon<T:Copy cmp::Eq>(tbl: HashMap<ast::node_id, ast::inferable<T>>,
3261
                         +m0: ast::inferable<T>) -> ast::inferable<T> {
3262 3263
    match m0 {
      ast::infer(id) => match tbl.find(id) {
B
Brian Anderson 已提交
3264
        None => m0,
3265 3266
        Some(ref m1) => {
            let cm1 = canon(tbl, (*m1));
3267
            // path compression:
3268
            if cm1 != (*m1) { tbl.insert(id, cm1); }
3269 3270
            cm1
        }
3271
      },
B
Brian Anderson 已提交
3272
      _ => m0
3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284
    }
}

// Maintains a little union-set tree for inferred modes.  `resolve_mode()`
// returns the current head value for `m0`.
fn canon_mode(cx: ctxt, m0: ast::mode) -> ast::mode {
    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.
fn resolved_mode(cx: ctxt, m: ast::mode) -> ast::rmode {
3285
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3286
      ast::infer(_) => {
P
Paul Stansifer 已提交
3287
        cx.sess.bug(fmt!("mode %? was never resolved", m));
3288
      }
B
Brian Anderson 已提交
3289
      ast::expl(m0) => m0
3290 3291 3292
    }
}

3293
fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { resolved_mode(cx, a.mode) }
3294 3295

// Unifies `m1` and `m2`.  Returns unified value or failure code.
3296
fn unify_mode(cx: ctxt, modes: expected_found<ast::mode>)
3297
    -> Result<ast::mode, type_err> {
3298 3299 3300

    let m1 = modes.expected;
    let m2 = modes.found;
3301
    match (canon_mode(cx, m1), canon_mode(cx, m2)) {
B
Brian Anderson 已提交
3302
      (m1, m2) if (m1 == m2) => {
3303
        result::Ok(m1)
3304
      }
E
Erick Tryzelaar 已提交
3305
      (ast::infer(_), ast::infer(id2)) => {
3306
        cx.inferred_modes.insert(id2, m1);
3307
        result::Ok(m1)
3308
      }
B
Brian Anderson 已提交
3309
      (ast::infer(id), m) | (m, ast::infer(id)) => {
3310
        cx.inferred_modes.insert(id, m);
3311
        result::Ok(m1)
3312
      }
E
Erick Tryzelaar 已提交
3313
      (_, _) => {
3314
        result::Err(terr_mode_mismatch(modes))
3315 3316 3317 3318 3319 3320 3321
      }
    }
}

// If `m` was never unified, unifies it with `m_def`.  Returns the final value
// for `m`.
fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) {
3322
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3323
      ast::infer(id) => {
3324 3325
        cx.inferred_modes.insert(id, ast::expl(m_def));
      }
B
Brian Anderson 已提交
3326
      ast::expl(_) => ()
3327 3328 3329
    }
}

3330
fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3331
    match get(t).sty {
N
Niko Matsakis 已提交
3332
      ty_nil | ty_bot | ty_bool | ty_int(_) |
M
Michael Sullivan 已提交
3333
      ty_uint(_) | ty_float(_) | ty_estr(_) |
B
Brian Anderson 已提交
3334
      ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
N
Niko Matsakis 已提交
3335 3336 3337
        ty_to_str(cx, t)
      }

P
Paul Stansifer 已提交
3338
      ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3339 3340 3341 3342 3343 3344 3345 3346
      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 已提交
3347
      ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3348
      ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3349
      ty_tup(_) => ~"tuple",
3350 3351
      ty_infer(TyVar(_)) => ~"inferred type",
      ty_infer(IntVar(_)) => ~"integral variable",
3352
      ty_infer(FloatVar(_)) => ~"floating-point variable",
B
Brian Anderson 已提交
3353
      ty_param(_) => ~"type parameter",
3354 3355
      ty_self => ~"self",
      ty_err => ~"type error"
N
Niko Matsakis 已提交
3356 3357 3358
    }
}

N
Niko Matsakis 已提交
3359
fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3360 3361 3362 3363 3364 3365 3366 3367 3368
    /*!
     *
     * 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. */

3369
    fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3370 3371 3372
        match k {
            terr_vec => ~"[]",
            terr_str => ~"str",
3373 3374
            terr_fn => ~"fn",
            terr_trait => ~"trait"
3375
        }
3376 3377
    }

N
Niko Matsakis 已提交
3378
    match *err {
3379 3380 3381 3382 3383 3384 3385
        terr_mismatch => ~"types differ",
        terr_ret_style_mismatch(values) => {
            fn to_str(s: ast::ret_style) -> ~str {
                match s {
                    ast::noreturn => ~"non-returning",
                    ast::return_val => ~"return-by-value"
                }
3386
            }
3387 3388 3389 3390 3391 3392 3393 3394 3395
            fmt!("expected %s function, found %s function",
                 to_str(values.expected),
                 to_str(values.expected))
        }
        terr_purity_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
                 purity_to_str(values.expected),
                 purity_to_str(values.found))
        }
3396 3397 3398 3399 3400
        terr_onceness_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
                 onceness_to_str(values.expected),
                 onceness_to_str(values.found))
        }
3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458
        terr_proto_mismatch(values) => {
            fmt!("expected %s closure, found %s closure",
                 proto_ty_to_str(cx, values.expected),
                 proto_ty_to_str(cx, values.found))
        }
        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",
                 mode_to_str(values.expected), mode_to_str(values.found))
        }
        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))
        }
3459
        terr_vstores_differ(k, ref values) => {
3460 3461
            fmt!("%s storage differs: expected %s but found %s",
                 terr_vstore_kind_to_str(k),
3462 3463
                 vstore_to_str(cx, (*values).expected),
                 vstore_to_str(cx, (*values).found))
3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479
        }
        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
        }
        terr_no_integral_type => {
            ~"couldn't determine an appropriate integral type for integer \
              literal"
3480
        }
3481 3482 3483 3484
        terr_no_floating_point_type => {
            ~"couldn't determine an appropriate floating point type for \
              floating point literal"
        }
3485 3486 3487
    }
}

3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504
fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
    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, ~"");
        }
3505 3506 3507 3508 3509 3510 3511 3512 3513 3514
        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, ~"");
        }
3515 3516 3517 3518
        _ => {}
    }
}

3519
fn def_has_ty_params(def: ast::def) -> bool {
3520
    match def {
3521
      ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
B
Brian Anderson 已提交
3522 3523
        => true,
      _ => false
3524 3525 3526
    }
}

3527 3528
fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
    cx.trait_method_cache.insert(ast_util::local_def(id), ms);
3529 3530
}

3531
fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3532 3533
    if is_local(id) {
        match cx.items.find(id.node) {
P
Patrick Walton 已提交
3534 3535 3536 3537
            Some(ast_map::node_item(@{
                        node: item_trait(_, _, ref ms),
                        _
                    }, _)) =>
3538
                match ast_util::split_trait_methods((*ms)) {
3539
                   (_, p) => p.map(|method| method.ident)
3540
                },
3541
            _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3542 3543
                                  id))
        }
3544
    } else {
3545
        csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3546 3547 3548
    }
}

3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564
fn trait_supertraits(cx: ctxt, id: ast::def_id) -> @~[InstantiatedTraitRef] {
    // 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 {
3565
            ty_trait(def_id, ref substs, _) => {
3566 3567
                result.push(InstantiatedTraitRef {
                    def_id: def_id,
3568
                    tpt: { substs: (*substs), ty: *trait_type }
3569 3570 3571 3572 3573 3574 3575 3576 3577
                });
            }
            _ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
        }
    }

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

3579
fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
3580
    match cx.trait_method_cache.find(id) {
3581
      // Local traits are supposed to have been added explicitly.
B
Brian Anderson 已提交
3582
      Some(ms) => ms,
3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594
      _ => {
        // 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
      }
3595 3596
    }
}
3597

3598 3599 3600
/*
  Could this return a list of (def_id, substs) pairs?
 */
3601 3602 3603 3604
fn impl_traits(cx: ctxt, id: ast::def_id, vstore: vstore) -> ~[t] {
    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 已提交
3605 3606 3607
            ty::ty_trait(did, ref substs, _) => {
                mk_trait(cx, did, (*substs), vstore)
            }
3608 3609 3610 3611
            _ => cx.sess.bug(~"impl_traits: not a trait")
        }
    }

3612
    if id.crate == ast::local_crate {
P
Paul Stansifer 已提交
3613
        debug!("(impl_traits) searching for trait impl %?", id);
3614
        match cx.items.find(id.node) {
B
Brian Anderson 已提交
3615
           Some(ast_map::node_item(@{
3616
                        node: ast::item_impl(_, opt_trait, _, _),
3617
                        _},
B
Brian Anderson 已提交
3618
                    _)) => {
3619

B
Brian Anderson 已提交
3620
               do option::map_default(&opt_trait, ~[]) |trait_ref| {
3621 3622 3623
                       ~[vstoreify(cx,
                                   node_id_to_type(cx, trait_ref.ref_id),
                                   vstore)]
3624
                   }
3625
           }
B
Brian Anderson 已提交
3626
           _ => ~[]
3627
        }
3628
    } else {
3629 3630
        vec::map(csearch::get_impl_traits(cx, id),
                 |x| vstoreify(cx, *x, vstore))
3631 3632 3633
    }
}

B
Brian Anderson 已提交
3634
fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3635
    match get(ty).sty {
3636
      ty_trait(id, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
B
Brian Anderson 已提交
3637
      _ => None
3638 3639 3640
    }
}

3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652
/// 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 {
3653
                ast::item_struct(struct_def, _) => {
3654 3655 3656 3657 3658 3659 3660 3661 3662 3663
                    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")
    }
}

3664
// Enum information
3665 3666 3667 3668 3669 3670 3671 3672 3673 3674
struct VariantInfo_ {
    args: ~[t],
    ctor_ty: t,
    name: ast::ident,
    id: ast::def_id,
    disr_val: int,
    vis: visibility
}

type VariantInfo = @VariantInfo_;
M
Marijn Haverbeke 已提交
3675

3676 3677
fn substd_enum_variants(cx: ctxt,
                        id: ast::def_id,
3678
                        substs: &substs) -> ~[VariantInfo] {
B
Brian Anderson 已提交
3679 3680
    do vec::map(*enum_variants(cx, id)) |variant_info| {
        let substd_args = vec::map(variant_info.args,
3681
                                   |aty| subst(cx, substs, *aty));
3682

3683
        let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3684

3685 3686
        @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
                      ..**variant_info}
3687 3688 3689
    }
}

3690
fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
P
Paul Stansifer 已提交
3691
    ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3692 3693
}

3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711
enum DtorKind {
    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()
    }
}

3712
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
3713
   Otherwise return none. */
3714 3715
fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
    match cx.destructor_for_type.find(struct_id) {
3716
        Some(method_def_id) => return TraitDtor(method_def_id),
3717 3718 3719
        None => {}  // Continue.
    }

3720 3721
    if is_local(struct_id) {
       match cx.items.find(struct_id.node) {
B
Brian Anderson 已提交
3722
           Some(ast_map::node_item(@{
3723
               node: ast::item_struct(@{ dtor: Some(ref dtor), _ }, _),
3724 3725
               _
           }, _)) =>
3726
               LegacyDtor(local_def((*dtor).node.id)),
3727
           _ =>
3728
               NoDtor
3729 3730 3731
       }
    }
    else {
3732
      match csearch::struct_dtor(cx.sess.cstore, struct_id) {
3733 3734 3735
        None => NoDtor,
        Some(did) => LegacyDtor(did),
      }
3736 3737 3738
    }
}

3739 3740
fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
    ty_dtor(cx, struct_id).is_present()
3741 3742
}

3743 3744 3745 3746 3747
fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
    if id.crate != ast::local_crate {
        csearch::get_item_path(cx, id)
    } else {
        let node = cx.items.get(id.node);
3748
        match node {
B
Brian Anderson 已提交
3749
          ast_map::node_item(item, path) => {
3750
            let item_elt = match item.node {
B
Brian Anderson 已提交
3751
              item_mod(_) | item_foreign_mod(_) => {
3752 3753
                ast_map::path_mod(item.ident)
              }
B
Brian Anderson 已提交
3754
              _ => {
3755 3756 3757
                ast_map::path_name(item.ident)
              }
            };
3758
            vec::append_one(*path, item_elt)
3759 3760
          }

B
Brian Anderson 已提交
3761
          ast_map::node_foreign_item(nitem, _, path) => {
3762
            vec::append_one(*path, ast_map::path_name(nitem.ident))
3763 3764
          }

B
Brian Anderson 已提交
3765
          ast_map::node_method(method, _, path) => {
3766
            vec::append_one(*path, ast_map::path_name(method.ident))
3767
          }
B
Brian Anderson 已提交
3768
          ast_map::node_trait_method(trait_method, _, path) => {
3769 3770 3771
            let method = ast_util::trait_method_to_ty_method(*trait_method);
            vec::append_one(*path, ast_map::path_name(method.ident))
          }
3772

3773
          ast_map::node_variant(ref variant, _, path) => {
3774
            vec::append_one(vec::init(*path),
3775
                            ast_map::path_name((*variant).node.name))
3776 3777
          }

B
Brian Anderson 已提交
3778
          ast_map::node_dtor(_, _, _, path) => {
P
Paul Stansifer 已提交
3779 3780
            vec::append_one(*path, ast_map::path_name(
                syntax::parse::token::special_idents::literally_dtor))
T
Tim Chevalier 已提交
3781 3782
          }

3783 3784 3785 3786
          ast_map::node_struct_ctor(_, item, path) => {
            vec::append_one(*path, ast_map::path_name(item.ident))
          }

3787 3788 3789
          ast_map::node_stmt(*) | ast_map::node_expr(*) |
          ast_map::node_arg(*) | ast_map::node_local(*) |
          ast_map::node_export(*) | ast_map::node_block(*) => {
P
Paul Stansifer 已提交
3790
            cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3791 3792 3793 3794 3795
          }
        }
    }
}

3796
fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3797
    enum_variants(cx, id).len() == 1
3798 3799
}

3800
fn type_is_empty(cx: ctxt, t: t) -> bool {
3801
    match ty::get(t).sty {
B
Brian Anderson 已提交
3802 3803
       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
       _ => false
3804 3805 3806
     }
}

3807
fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3808
    match cx.enum_var_cache.find(id) {
B
Brian Anderson 已提交
3809
      Some(variants) => return variants,
B
Brian Anderson 已提交
3810
      _ => { /* fallthrough */ }
3811
    }
3812

3813
    let result = if ast::local_crate != id.crate {
3814
        @csearch::get_enum_variants(cx, id)
3815
    } else {
3816 3817 3818 3819 3820
        /*
          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
         */
3821
        match cx.items.get(id.node) {
P
Patrick Walton 已提交
3822 3823 3824 3825
          ast_map::node_item(@{
                    node: ast::item_enum(ref enum_definition, _),
                    _
                }, _) => {
3826
            let variants = (*enum_definition).variants;
3827
            let mut disr_val = -1;
B
Brian Anderson 已提交
3828
            @vec::map(variants, |variant| {
3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839
                match variant.node.kind {
                    ast::tuple_variant_kind(args) => {
                        let ctor_ty = node_id_to_type(cx, variant.node.id);
                        let arg_tys = {
                            if vec::len(args) > 0u {
                                ty_fn_args(ctor_ty).map(|a| a.ty)
                            } else {
                                ~[]
                            }
                        };
                        match variant.node.disr_expr {
B
Brian Anderson 已提交
3840
                          Some (ex) => {
3841 3842 3843 3844 3845 3846 3847 3848
                            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
                        }
3849
                        @VariantInfo_{args: arg_tys,
3850 3851 3852
                          ctor_ty: ctor_ty,
                          name: variant.node.name,
                          id: ast_util::local_def(variant.node.id),
3853 3854
                          disr_val: disr_val,
                          vis: variant.node.vis
3855
                         }
3856
                    }
3857
                    ast::struct_variant_kind(_) => {
3858
                        fail ~"struct variant kinds unimpl in enum_variants"
3859 3860 3861 3862
                    }
                    ast::enum_variant_kind(_) => {
                        fail ~"enum variant kinds unimpl in enum_variants"
                    }
3863
                }
3864
            })
M
Marijn Haverbeke 已提交
3865
          }
B
Brian Anderson 已提交
3866
          _ => cx.sess.bug(~"tag_variants: id not bound to an enum")
3867
        }
3868
    };
3869
    cx.enum_var_cache.insert(id, result);
3870
    result
3871 3872
}

3873

P
Patrick Walton 已提交
3874
// Returns information about the enum variant with the given ID:
3875
fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id,
3876
                        variant_id: ast::def_id) -> VariantInfo {
3877
    let variants = enum_variants(cx, enum_id);
3878 3879
    let mut i = 0;
    while i < variants.len() {
B
Brian Anderson 已提交
3880
        let variant = variants[i];
3881
        if variant.id == variant_id { return variant; }
3882
        i += 1;
3883
    }
3884
    cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
3885 3886
}

3887

3888 3889
// 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.
3890
fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
3891
    match cx.tcache.find(did) {
3892
      Some(tpt) => {
3893 3894
        // The item is in this crate. The caller should have added it to the
        // type cache already
3895 3896 3897
        return tpt;
      }
      None => {
3898
        assert did.crate != ast::local_crate;
M
Marijn Haverbeke 已提交
3899 3900
        let tyt = csearch::get_type(cx, did);
        cx.tcache.insert(did, tyt);
B
Brian Anderson 已提交
3901
        return tyt;
M
Marijn Haverbeke 已提交
3902
      }
3903
    }
T
Tim Chevalier 已提交
3904 3905
}

T
Tim Chevalier 已提交
3906
// Look up a field ID, whether or not it's local
3907 3908
// Takes a list of type substs in case the struct is generic
fn lookup_field_type(tcx: ctxt, struct_id: def_id, id: def_id,
N
Niko Matsakis 已提交
3909
                     substs: &substs) -> ty::t {
3910

3911
    let t = if id.crate == ast::local_crate {
T
Tim Chevalier 已提交
3912 3913 3914
        node_id_to_type(tcx, id.node)
    }
    else {
3915
        match tcx.tcache.find(id) {
B
Brian Anderson 已提交
3916 3917
           Some(tpt) => tpt.ty,
           None => {
3918
               let tpt = csearch::get_field_type(tcx, struct_id, id);
T
Tim Chevalier 已提交
3919
               tcx.tcache.insert(id, tpt);
3920
               tpt.ty
T
Tim Chevalier 已提交
3921 3922
           }
        }
3923
    };
3924
    subst(tcx, substs, t)
T
Tim Chevalier 已提交
3925 3926
}

3927 3928 3929
// Look up the list of field names and IDs for a given struct
// Fails if the id is not bound to a struct.
fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
3930
  if did.crate == ast::local_crate {
3931
    match cx.items.find(did.node) {
B
Brian Anderson 已提交
3932
       Some(ast_map::node_item(i,_)) => {
3933
         match i.node {
3934 3935
            ast::item_struct(struct_def, _) => {
               struct_field_tys(struct_def.fields)
3936
            }
3937
            _ => cx.sess.bug(~"struct ID bound to non-struct")
T
Tim Chevalier 已提交
3938
         }
T
Tim Chevalier 已提交
3939
       }
3940 3941
       Some(ast_map::node_variant(ref variant, _, _)) => {
          match (*variant).node.kind {
3942
            ast::struct_variant_kind(struct_def) => {
3943
              struct_field_tys(struct_def.fields)
3944 3945 3946 3947 3948 3949 3950
            }
            _ => {
              cx.sess.bug(~"struct ID bound to enum variant that isn't \
                            struct-like")
            }
          }
       }
B
Brian Anderson 已提交
3951
       _ => {
P
Paul Stansifer 已提交
3952
           cx.sess.bug(
3953
               fmt!("struct ID not bound to an item: %s",
P
Paul Stansifer 已提交
3954
                    ast_map::node_id_to_str(cx.items, did.node,
P
Paul Stansifer 已提交
3955
                                            cx.sess.parse_sess.interner)));
3956
       }
T
Tim Chevalier 已提交
3957
    }
T
Tim Chevalier 已提交
3958
        }
3959
  else {
3960
        return csearch::get_struct_fields(cx, did);
T
Tim Chevalier 已提交
3961 3962 3963
    }
}

3964
fn lookup_struct_field(cx: ctxt, parent: ast::def_id, field_id: ast::def_id)
3965
    -> field_ty {
3966
    match vec::find(lookup_struct_fields(cx, parent),
B
Brian Anderson 已提交
3967
                 |f| f.id.node == field_id.node) {
B
Brian Anderson 已提交
3968
        Some(t) => t,
3969
        None => cx.sess.bug(~"struct ID not found in parent's fields")
3970 3971 3972
    }
}

3973
pure fn is_public(f: field_ty) -> bool {
3974 3975 3976 3977 3978
    // XXX: This is wrong.
    match f.vis {
        public | inherited => true,
        private => false
    }
3979 3980
}

3981
fn struct_field_tys(fields: ~[@struct_field]) -> ~[field_ty] {
3982
    let mut rslt = ~[];
3983 3984 3985
    for fields.each |field| {
        match field.node.kind {
            named_field(ident, mutability, visibility) => {
3986 3987 3988 3989
                rslt.push({ident: ident,
                           id: ast_util::local_def(field.node.id),
                           vis: visibility,
                           mutability: mutability});
3990
            }
3991 3992 3993 3994 3995
            unnamed_field => {
                rslt.push({ident:
                    syntax::parse::token::special_idents::unnamed_field,
                           id: ast_util::local_def(field.node.id),
                           vis: ast::public,
3996
                           mutability: ast::struct_immutable});
3997
            }
T
Tim Chevalier 已提交
3998 3999 4000
       }
    }
    rslt
T
Tim Chevalier 已提交
4001 4002
}

4003 4004
// Return a list of fields corresponding to the struct's items
// (as if the struct was a record). trans uses this
4005
// Takes a list of substs with which to instantiate field types
4006 4007 4008
// 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.
4009
fn struct_mutable_fields(cx:ctxt,
N
Niko Matsakis 已提交
4010 4011
                                 did: ast::def_id,
                                 substs: &substs) -> ~[field] {
4012
    struct_item_fields(cx, did, substs, |_mt| m_mutbl)
4013 4014
}

4015
// Same as struct_mutable_fields, but doesn't change
4016
// mutability.
4017
fn struct_fields(cx:ctxt,
N
Niko Matsakis 已提交
4018 4019
                         did: ast::def_id,
                         substs: &substs) -> ~[field] {
4020 4021 4022
    struct_item_fields(cx, did, substs, |mt| match mt {
      struct_mutable => m_mutbl,
        struct_immutable => m_imm })
4023 4024 4025
}


4026
fn struct_item_fields(cx:ctxt,
N
Niko Matsakis 已提交
4027 4028
                     did: ast::def_id,
                     substs: &substs,
4029
                     frob_mutability: fn(struct_mutability) -> mutability)
4030 4031
    -> ~[field] {
    let mut rslt = ~[];
4032
    for lookup_struct_fields(cx, did).each |f| {
G
Graydon Hoare 已提交
4033
       // consider all instance vars mut, because the
T
Tim Chevalier 已提交
4034
       // constructor may mutate all vars
4035
       rslt.push({ident: f.ident, mt:
4036
               {ty: lookup_field_type(cx, did, f.id, substs),
4037
                    mutbl: frob_mutability(f.mutability)}});
T
Tim Chevalier 已提交
4038 4039 4040 4041
    }
    rslt
}

4042
fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
M
Marijn Haverbeke 已提交
4043 4044 4045 4046
    const tycat_other: int = 0;
    const tycat_bool: int = 1;
    const tycat_int: int = 2;
    const tycat_float: int = 3;
M
Michael Sullivan 已提交
4047 4048
    const tycat_struct: int = 4;
    const tycat_bot: int = 5;
M
Marijn Haverbeke 已提交
4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059

    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 {
4060
        match op {
B
Brian Anderson 已提交
4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078
          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 已提交
4079 4080 4081
        }
    }

4082
    fn tycat(ty: t) -> int {
4083
        match get(ty).sty {
B
Brian Anderson 已提交
4084
          ty_bool => tycat_bool,
4085
          ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4086
          ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
B
Brian Anderson 已提交
4087 4088 4089
          ty_rec(_) | ty_tup(_) | ty_enum(_, _) => tycat_struct,
          ty_bot => tycat_bot,
          _ => tycat_other
M
Marijn Haverbeke 已提交
4090 4091 4092 4093 4094
        }
    }

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

4096
    let tbl = ~[
4097 4098 4099
    /*.          add,     shift,   bit
      .             sub,     rel,     logic
      .                mult,    eq,         */
4100
    /*other*/   ~[f, f, f, f, f, f, f, f],
4101 4102 4103
    /*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],
4104 4105
    /*bot*/     ~[f, f, f, f, f, f, f, f],
    /*struct*/  ~[t, t, t, t, f, f, t, t]];
B
Brian Anderson 已提交
4106

B
Brian Anderson 已提交
4107
    return tbl[tycat(ty)][opcat(op)];
4108 4109
}

4110
fn ty_params_to_tys(tcx: ty::ctxt, tps: ~[ast::ty_param]) -> ~[t] {
B
Brian Anderson 已提交
4111
    vec::from_fn(tps.len(), |i| {
4112 4113 4114
                ty::mk_param(tcx, i, ast_util::local_def(tps[i].id))
        })
}
4115

4116
/// Returns an equivalent type with all the typedefs and self regions removed.
4117
fn normalize_ty(cx: ctxt, t: t) -> t {
4118 4119 4120 4121 4122 4123 4124 4125 4126 4127
    fn normalize_mt(cx: ctxt, mt: mt) -> mt {
        { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
    }
    fn normalize_vstore(vstore: vstore) -> vstore {
        match vstore {
            vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
            vstore_slice(_) => vstore_slice(re_static)
        }
    }

4128
    match cx.normalized_cache.find(t) {
B
Brian Anderson 已提交
4129 4130
      Some(t) => return t,
      None => ()
B
Brian Anderson 已提交
4131 4132
    }

4133
    let t = match get(t).sty {
4134 4135 4136 4137
        ty_evec(mt, vstore) =>
            // This type has a vstore. Get rid of it
            mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),

4138 4139 4140 4141
        ty_estr(vstore) =>
            // This type has a vstore. Get rid of it
            mk_estr(cx, normalize_vstore(vstore)),

E
Erick Tryzelaar 已提交
4142
        ty_rptr(_, mt) =>
4143
            // This type has a region. Get rid of it
4144 4145
            mk_rptr(cx, re_static, normalize_mt(cx, mt)),

4146 4147
        ty_fn(ref fn_ty) => {
            mk_fn(cx, FnTyBase {
4148 4149 4150 4151
                meta: FnMeta {
                    region: ty::re_static,
                    ..fn_ty.meta
                },
4152 4153 4154
                sig: fn_ty.sig
            })
        }
4155

4156 4157
        ty_enum(did, ref r) =>
            match (*r).self_r {
B
Brian Anderson 已提交
4158
                Some(_) =>
4159
                    // Use re_static since trans doesn't care about regions
E
Eric Holk 已提交
4160
                    mk_enum(cx, did,
4161 4162
                     {self_r: Some(ty::re_static),
                      self_ty: None,
4163
                      tps: (*r).tps}),
B
Brian Anderson 已提交
4164
                None =>
4165 4166 4167
                    t
            },

4168
        ty_struct(did, ref r) =>
4169
            match (*r).self_r {
B
Brian Anderson 已提交
4170
              Some(_) =>
4171
                // Ditto.
4172 4173 4174
                mk_struct(cx, did, {self_r: Some(ty::re_static),
                                    self_ty: None,
                                    tps: (*r).tps}),
B
Brian Anderson 已提交
4175
              None =>
4176 4177 4178 4179 4180
                t
            },

        _ =>
            t
4181 4182
    };

4183
    let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
B
Brian Anderson 已提交
4184 4185
    let t_norm = mk_t(cx, sty);
    cx.normalized_cache.insert(t, t_norm);
B
Brian Anderson 已提交
4186
    return t_norm;
4187 4188
}

4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205
// Returns the repeat count for a repeating vector expression.
fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr, span: span) -> uint {
    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;
        }
4206 4207 4208 4209 4210 4211 4212
        const_eval::const_bool(_) => {
            tcx.sess.span_err(span,
                              ~"expected signed or unsigned integer for \
                                repeat count but found boolean");
            return 0;
        }

4213 4214 4215
    }
}

4216 4217 4218
// Determine what purity to check a nested function under
pure fn determine_inherited_purity(parent_purity: ast::purity,
                                   child_purity: ast::purity,
4219
                                   child_proto: ast::Proto) -> ast::purity {
4220 4221 4222
    // 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
4223 4224 4225 4226
    match child_proto {
        ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity,
        _ => child_purity
    }
4227 4228
}

4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239
// Iterate over a type parameter's bounded traits and any supertraits
// of those traits, ignoring kinds.
fn iter_bound_traits_and_supertraits(tcx: ctxt,
                                     bounds: param_bounds,
                                     f: &fn(t) -> bool) {
    for bounds.each |bound| {

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

            ty::bound_copy | ty::bound_send |
B
Brian Anderson 已提交
4240
            ty::bound_const | ty::bound_durable => {
4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286
                loop; // skip non-trait bounds
            }
        };

        let mut worklist = ~[];

        let init_trait_ty = bound_trait_ty;

        worklist.push(init_trait_ty);

        let mut i = 0;
        while i < worklist.len() {
            let init_trait_ty = worklist[i];
            i += 1;

            let init_trait_id = match ty_to_def_id(init_trait_ty) {
                Some(id) => id,
                None => tcx.sess.bug(
                    ~"trait type should have def_id")
            };

            // Add supertraits to worklist
            let supertraits = trait_supertraits(tcx,
                                                init_trait_id);
            for supertraits.each |supertrait| {
                worklist.push(supertrait.tpt.ty);
            }

            if !f(init_trait_ty) {
                return;
            }
        }
    }
}

fn count_traits_and_supertraits(tcx: ctxt,
                                boundses: &[param_bounds]) -> uint {
    let mut total = 0;
    for boundses.each |bounds| {
        for iter_bound_traits_and_supertraits(tcx, *bounds) |_trait_ty| {
            total += 1;
        }
    }
    return total;
}

4287
impl mt : cmp::Eq {
4288 4289 4290 4291
    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) }
4292
}
4293

4294
impl arg : cmp::Eq {
4295 4296 4297 4298
    pure fn eq(&self, other: &arg) -> bool {
        (*self).mode == (*other).mode && (*self).ty == (*other).ty
    }
    pure fn ne(&self, other: &arg) -> bool { !(*self).eq(other) }
4299
}
4300

4301
impl field : cmp::Eq {
4302 4303 4304 4305
    pure fn eq(&self, other: &field) -> bool {
        (*self).ident == (*other).ident && (*self).mt == (*other).mt
    }
    pure fn ne(&self, other: &field) -> bool { !(*self).eq(other) }
4306
}
4307

4308
impl vstore : cmp::Eq {
4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337
    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) }
4338
}
4339

4340
impl FnMeta : cmp::Eq {
4341 4342 4343 4344 4345 4346 4347
    pure fn eq(&self, other: &FnMeta) -> bool {
        (*self).purity == (*other).purity &&
        (*self).proto == (*other).proto &&
        (*self).bounds == (*other).bounds &&
        (*self).ret_style == (*other).ret_style
    }
    pure fn ne(&self, other: &FnMeta) -> bool { !(*self).eq(other) }
4348
}
4349

4350
impl FnSig : cmp::Eq {
4351 4352 4353 4354 4355
    pure fn eq(&self, other: &FnSig) -> bool {
        (*self).inputs == (*other).inputs &&
        (*self).output == (*other).output
    }
    pure fn ne(&self, other: &FnSig) -> bool { !(*self).eq(other) }
4356
}
4357

4358
impl<M: cmp::Eq> FnTyBase<M> : cmp::Eq {
4359 4360 4361 4362
    pure fn eq(&self, other: &FnTyBase<M>) -> bool {
        (*self).meta == (*other).meta && (*self).sig == (*other).sig
    }
    pure fn ne(&self, other: &FnTyBase<M>) -> bool { !(*self).eq(other) }
4363
}
4364

4365
impl TyVid : cmp::Eq {
4366 4367
    pure fn eq(&self, other: &TyVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &TyVid) -> bool { *(*self) != *(*other) }
4368
}
4369

4370
impl IntVid : cmp::Eq {
4371 4372
    pure fn eq(&self, other: &IntVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &IntVid) -> bool { *(*self) != *(*other) }
4373
}
4374

4375
impl FloatVid : cmp::Eq {
4376 4377
    pure fn eq(&self, other: &FloatVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &FloatVid) -> bool { *(*self) != *(*other) }
4378 4379
}

4380
impl FnVid : cmp::Eq {
4381 4382
    pure fn eq(&self, other: &FnVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &FnVid) -> bool { *(*self) != *(*other) }
4383
}
4384

4385
impl RegionVid : cmp::Eq {
4386 4387
    pure fn eq(&self, other: &RegionVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &RegionVid) -> bool { *(*self) != *(*other) }
4388
}
4389

4390
impl Region : cmp::Eq {
4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425
    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) }
4426
}
4427

4428
impl bound_region : cmp::Eq {
4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457
    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
                }
            }
        }
    }
    pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) }
4458
}
4459

4460
impl substs : cmp::Eq {
4461 4462 4463 4464 4465 4466
    pure fn eq(&self, other: &substs) -> bool {
        (*self).self_r == (*other).self_r &&
        (*self).self_ty == (*other).self_ty &&
        (*self).tps == (*other).tps
    }
    pure fn ne(&self, other: &substs) -> bool { !(*self).eq(other) }
4467
}
4468

4469
impl InferTy : cmp::Eq {
4470 4471 4472 4473
    pure fn eq(&self, other: &InferTy) -> bool {
        (*self).to_hash() == (*other).to_hash()
    }
    pure fn ne(&self, other: &InferTy) -> bool { !(*self).eq(other) }
4474
}
4475

4476
impl sty : cmp::Eq {
4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 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 4517 4518 4519 4520
    pure fn eq(&self, other: &sty) -> bool {
        match (*self) {
            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
                }
            }
4521
            ty_enum(e0a, ref e1a) => {
4522
                match (*other) {
4523
                    ty_enum(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4524 4525 4526 4527 4528 4529 4530 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
                    _ => 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) => {
                match (*other) {
                    ty_rec(e0b) => e0a == e0b,
                    _ => false
                }
            }
4563
            ty_fn(ref e0a) => {
4564
                match (*other) {
4565
                    ty_fn(ref e0b) => (*e0a) == (*e0b),
4566 4567 4568
                    _ => false
                }
            }
4569
            ty_trait(e0a, ref e1a, e2a) => {
4570
                match (*other) {
4571 4572
                    ty_trait(e0b, ref e1b, e2b) =>
                        e0a == e0b && (*e1a) == (*e1b) && e2a == e2b,
4573 4574 4575
                    _ => false
                }
            }
4576
            ty_struct(e0a, ref e1a) => {
4577
                match (*other) {
4578
                    ty_struct(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593
                    _ => false
                }
            }
            ty_tup(e0a) => {
                match (*other) {
                    ty_tup(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_infer(e0a) => {
                match (*other) {
                    ty_infer(e0b) => e0a == e0b,
                    _ => false
                }
            }
4594 4595 4596 4597 4598 4599
            ty_err => {
                match (*other) {
                    ty_err => true,
                    _ => false
                }
            }
4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638
            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) }
4639
}
4640

4641
impl param_bound : cmp::Eq {
4642 4643 4644 4645 4646 4647 4648 4649
    pure fn eq(&self, other: &param_bound) -> bool {
        match (*self) {
            bound_copy => {
                match (*other) {
                    bound_copy => true,
                    _ => false
                }
            }
B
Brian Anderson 已提交
4650
            bound_durable => {
4651
                match (*other) {
B
Brian Anderson 已提交
4652
                    bound_durable => true,
4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675
                    _ => false
                }
            }
            bound_send => {
                match (*other) {
                    bound_send => true,
                    _ => false
                }
            }
            bound_const => {
                match (*other) {
                    bound_const => true,
                    _ => false
                }
            }
            bound_trait(e0a) => {
                match (*other) {
                    bound_trait(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
B
Brian Anderson 已提交
4676
    pure fn ne(&self, other: &param_bound) -> bool { !self.eq(other) }
4677
}
4678

4679
impl Kind : cmp::Eq {
4680 4681
    pure fn eq(&self, other: &Kind) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &Kind) -> bool { *(*self) != *(*other) }
4682
}
4683

4684

4685 4686 4687 4688 4689 4690 4691
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: