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

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

13 14
use core::prelude::*;

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

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

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

244
// Data types
245

246 247
// 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 已提交
248
type arg = {mode: ast::mode, ty: t};
249

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

252
type param_bounds = @~[param_bound];
253

254
type method = {ident: ast::ident,
255
               tps: @~[param_bounds],
256
               fty: FnTy,
257
               self_ty: ast::self_ty_,
258 259
               vis: ast::visibility,
               def_id: ast::def_id};
260

261 262 263 264
struct mt {
    ty: t,
    mutbl: ast::mutability,
}
265

266 267
#[auto_encode]
#[auto_decode]
268 269 270 271
enum vstore {
    vstore_fixed(uint),
    vstore_uniq,
    vstore_box,
272
    vstore_slice(Region)
273 274
}

T
Tim Chevalier 已提交
275
type field_ty = {
T
Tim Chevalier 已提交
276
  ident: ident,
T
Tim Chevalier 已提交
277
  id: def_id,
278
  vis: ast::visibility,
279
  mutability: ast::struct_mutability
T
Tim Chevalier 已提交
280 281
};

282
/// How an lvalue is to be used.
283 284
#[auto_encode]
#[auto_decode]
285 286 287 288 289 290
pub enum ValueMode {
    ReadValue,  // Non-destructively read the value; do not copy or move.
    CopyValue,  // Copy the value.
    MoveValue,  // Move the value.
}

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

296
impl creader_cache_key : cmp::Eq {
297 298 299 300 301 302 303 304
    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))
    }
305
}
306

307 308 309 310 311
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);
    }
}
312

313
type intern_key = {sty: *sty, o_def_id: Option<ast::def_id>};
314

315
impl intern_key : cmp::Eq {
316
    pure fn eq(&self, other: &intern_key) -> bool {
317 318 319
        unsafe {
            *self.sty == *other.sty && self.o_def_id == other.o_def_id
        }
320 321
    }
    pure fn ne(&self, other: &intern_key) -> bool { !(*self).eq(other) }
322
}
323

324 325
impl intern_key : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
326 327 328
        unsafe {
            to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f);
        }
329 330
    }
}
331

332 333
enum ast_ty_to_ty_cache_entry {
    atttce_unresolved,  /* not resolved yet */
334
    atttce_resolved(t)  /* resolved to a type, irrespective of region */
335 336
}

B
Brian Anderson 已提交
337
type opt_region_variance = Option<region_variance>;
338

339 340
#[auto_encode]
#[auto_decode]
341 342
enum region_variance { rv_covariant, rv_invariant, rv_contravariant }

343
impl region_variance : cmp::Eq {
344 345 346 347 348 349 350 351 352 353 354
    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) }
355
}
356

357 358
#[auto_encode]
#[auto_decode]
359
pub type AutoAdjustment = {
360 361 362 363
    autoderefs: uint,
    autoref: Option<AutoRef>
};

364 365
#[auto_encode]
#[auto_decode]
366
pub type AutoRef = {
367
    kind: AutoRefKind,
368
    region: Region,
369 370 371
    mutbl: ast::mutability
};

372 373
#[auto_encode]
#[auto_decode]
374
enum AutoRefKind {
375 376 377
    /// Convert from T to &T
    AutoPtr,

378
    /// Convert from @[]/~[] to &[] (or str)
379
    AutoBorrowVec,
380

381 382 383
    /// Convert from @[]/~[] to &&[] (or str)
    AutoBorrowVecRef,

384 385
    /// Convert from @fn()/~fn() to &fn()
    AutoBorrowFn,
386 387
}

388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
// 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
}

403 404 405 406 407
struct ProvidedMethodSource {
    method_id: ast::def_id,
    impl_id: ast::def_id
}

408 409 410 411 412
struct InstantiatedTraitRef {
    def_id: ast::def_id,
    tpt: ty_param_substs_and_ty
}

413
type ctxt =
414
    @{diag: syntax::diagnostic::span_handler,
B
Brian Anderson 已提交
415
      interner: HashMap<intern_key, t_box>,
G
Graydon Hoare 已提交
416
      mut next_id: uint,
417
      vecs_implicitly_copyable: bool,
418
      legacy_modes: bool,
419 420
      cstore: metadata::cstore::CStore,
      sess: session::Session,
G
Graydon Hoare 已提交
421
      def_map: resolve::DefMap,
422

423
      region_map: middle::region::region_map,
424
      region_paramd_items: middle::region::region_paramd_items,
425 426 427

      // 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 已提交
428
      // typeck::check::fn_ctxt for details.
M
Marijn Haverbeke 已提交
429
      node_types: node_type_table,
430 431 432 433 434

      // 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 已提交
435
      node_type_substs: HashMap<node_id, ~[t]>,
436

M
Marijn Haverbeke 已提交
437
      items: ast_map::map,
B
Brian Anderson 已提交
438
      intrinsic_defs: HashMap<ast::ident, (ast::def_id, t)>,
M
Marijn Haverbeke 已提交
439 440 441
      freevars: freevars::freevar_map,
      tcache: type_cache,
      rcache: creader_cache,
442
      ccache: constness_cache,
B
Brian Anderson 已提交
443 444 445
      short_names_cache: HashMap<t, @~str>,
      needs_drop_cache: HashMap<t, bool>,
      needs_unwind_cleanup_cache: HashMap<t, bool>,
446 447
      kind_cache: HashMap<t, Kind>,
      ast_ty_to_ty_cache: HashMap<@ast::Ty, ast_ty_to_ty_cache_entry>,
448
      enum_var_cache: HashMap<def_id, @~[VariantInfo]>,
B
Brian Anderson 已提交
449 450 451
      trait_method_cache: HashMap<def_id, @~[method]>,
      ty_param_bounds: HashMap<ast::node_id, param_bounds>,
      inferred_modes: HashMap<ast::node_id, ast::mode>,
452
      adjustments: HashMap<ast::node_id, @AutoAdjustment>,
453
      normalized_cache: HashMap<t, t>,
454
      lang_items: middle::lang_items::LanguageItems,
455
      legacy_boxed_traits: HashMap<node_id, ()>,
B
Brian Anderson 已提交
456 457 458
      // 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.
459
      provided_methods: ProvidedMethodsMap,
460
      provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
461
      supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
462 463 464 465 466 467 468 469

      // 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.
470 471 472 473
      destructors: HashMap<ast::def_id, ()>,

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

476 477 478 479 480
enum tbox_flag {
    has_params = 1,
    has_self = 2,
    needs_infer = 4,
    has_regions = 8,
481
    has_ty_err = 16,
482 483 484 485 486 487

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

488
type t_box = @{sty: sty,
489
               id: uint,
490
               flags: uint,
B
Brian Anderson 已提交
491
               o_def_id: Option<ast::def_id>};
492

493 494 495 496 497 498 499
// 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;
500

501
pure fn get(t: t) -> t_box unsafe {
502
    let t2 = cast::reinterpret_cast::<t, t_box>(&t);
503
    let t3 = t2;
504
    cast::forget(move t2);
505 506 507
    t3
}

508
pure fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
509 510
    (tb.flags & (flag as uint)) != 0u
}
511 512 513 514
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) }
515
pure fn type_contains_err(t: t) -> bool { tbox_has_flag(get(t), has_ty_err) }
B
Brian Anderson 已提交
516
pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
517
pure fn type_id(t: t) -> uint { get(t).id }
518

519 520 521 522 523
/**
 * Meta information about a closure.
 *
 * - `purity` is the function's effect (pure, impure, unsafe).
 * - `proto` is the protocol (fn@, fn~, etc).
524 525
 * - `onceness` indicates whether the function can be called one time or many
 *   times.
526
 * - `region` is the region bound on the function's upvars (often &static).
527
 * - `bounds` is the parameter bounds on the function's upvars. */
528
#[deriving_eq]
529
struct FnMeta {
530
    purity: ast::purity,
531
    proto: ast::Proto,
532
    onceness: ast::Onceness,
533
    region: Region,
534
    bounds: @~[param_bound]
535 536 537 538 539 540 541 542
}

/**
 * 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. */
543
#[deriving_eq]
544
struct FnSig {
545 546
    inputs: ~[arg],
    output: t
547 548 549 550 551 552 553
}

/**
 * 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. */
554
#[deriving_eq]
555
struct FnTyBase<M: cmp::Eq> {
556 557 558 559 560 561 562 563
    meta: M,        // Either FnMeta or FnVid
    sig: FnSig      // Types of arguments/return type
}

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

type FnTy = FnTyBase<FnMeta>;
567

568 569
type param_ty = {idx: uint, def_id: def_id};

570
impl param_ty : cmp::Eq {
571 572 573 574
    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) }
575
}
576

577 578 579 580 581
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)
    }
}
582 583


584
/// Representation of regions:
585 586
#[auto_encode]
#[auto_decode]
587
enum Region {
588 589 590 591 592 593 594 595 596
    /// 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 已提交
597
    re_bound(bound_region),
598 599 600 601

    /// 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 已提交
602
    re_free(node_id, bound_region),
603 604

    /// A concrete region naming some expression within the current function.
N
Niko Matsakis 已提交
605
    re_scope(node_id),
606 607 608 609 610

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

    /// A region variable.  Should not exist after typeck.
611
    re_infer(InferRegion)
N
Niko Matsakis 已提交
612 613
}

614 615
#[auto_encode]
#[auto_decode]
N
Niko Matsakis 已提交
616
enum bound_region {
617
    /// The self region for structs, impls (&T in a type defn or &self/T)
618 619
    br_self,

620 621
    /// An anonymous region parameter for a given fn (&T)
    br_anon(uint),
622 623 624 625

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

626 627 628
    /// Fresh bound identifiers created during GLB computations.
    br_fresh(uint),

629 630 631 632 633 634 635 636 637
    /**
     * 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. */
638
    br_cap_avoid(ast::node_id, @bound_region),
639 640
}

641
type opt_region = Option<Region>;
642

643 644 645 646 647 648 649 650 651
/**
 * 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
652
 *   types (enums, structs) declared as having a region parameter.  `self_r`
653 654 655 656 657 658 659
 *   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. */
660 661
type substs = {
    self_r: opt_region,
B
Brian Anderson 已提交
662
    self_ty: Option<ty::t>,
663
    tps: ~[t]
664 665
};

666
// NB: If you change this, you'll probably want to change the corresponding
667
// AST structure in libsyntax/ast.rs as well.
P
Patrick Walton 已提交
668
enum sty {
P
Patrick Walton 已提交
669 670 671 672 673 674
    ty_nil,
    ty_bot,
    ty_bool,
    ty_int(ast::int_ty),
    ty_uint(ast::uint_ty),
    ty_float(ast::float_ty),
675
    ty_estr(vstore),
676
    ty_enum(def_id, substs),
P
Patrick Walton 已提交
677 678
    ty_box(mt),
    ty_uniq(mt),
679
    ty_evec(mt, vstore),
P
Patrick Walton 已提交
680
    ty_ptr(mt),
681
    ty_rptr(Region, mt),
682
    ty_rec(~[field]),
683
    ty_fn(FnTy),
684
    ty_trait(def_id, substs, vstore),
685
    ty_struct(def_id, substs),
686
    ty_tup(~[t]),
P
Patrick Walton 已提交
687

688
    ty_param(param_ty), // type parameter
689
    ty_self, // special, implicit `self` type parameter
P
Patrick Walton 已提交
690

691
    ty_infer(InferTy), // something used only during inference/typeck
692 693 694
    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)
695

M
Michael Sullivan 已提交
696
    // "Fake" types, used for trans purposes
P
Patrick Walton 已提交
697
    ty_type, // type_desc*
698
    ty_opaque_box, // used by monomorphizer to represent any @ box
699
    ty_opaque_closure_ptr(ast::Proto), // ptr to env for fn, fn@, fn~
M
Michael Sullivan 已提交
700
    ty_unboxed_vec(mt),
701 702
}

703
enum terr_vstore_kind {
704
    terr_vec, terr_str, terr_fn, terr_trait
705 706
}

707
struct expected_found<T> {
708 709
    expected: T,
    found: T
710 711
}

712
// Data structures used in type unification
P
Patrick Walton 已提交
713
enum type_err {
P
Patrick Walton 已提交
714
    terr_mismatch,
715
    terr_purity_mismatch(expected_found<purity>),
716
    terr_onceness_mismatch(expected_found<Onceness>),
717
    terr_mutability,
718
    terr_proto_mismatch(expected_found<ast::Proto>),
P
Patrick Walton 已提交
719
    terr_box_mutability,
M
Marijn Haverbeke 已提交
720
    terr_ptr_mutability,
721
    terr_ref_mutability,
P
Patrick Walton 已提交
722
    terr_vec_mutability,
723 724 725
    terr_tuple_size(expected_found<uint>),
    terr_ty_param_size(expected_found<uint>),
    terr_record_size(expected_found<uint>),
P
Patrick Walton 已提交
726
    terr_record_mutability,
727
    terr_record_fields(expected_found<ident>),
P
Patrick Walton 已提交
728
    terr_arg_count,
729
    terr_mode_mismatch(expected_found<mode>),
730 731 732
    terr_regions_does_not_outlive(Region, Region),
    terr_regions_not_same(Region, Region),
    terr_regions_no_overlap(Region, Region),
733 734
    terr_regions_insufficiently_polymorphic(bound_region, Region),
    terr_regions_overly_polymorphic(bound_region, Region),
735
    terr_vstores_differ(terr_vstore_kind, expected_found<vstore>),
B
Brian Anderson 已提交
736
    terr_in_field(@type_err, ast::ident),
737
    terr_sorts(expected_found<t>),
738
    terr_self_substs,
739
    terr_integer_as_char,
740
    terr_no_integral_type,
741
    terr_no_floating_point_type,
742 743
}

P
Patrick Walton 已提交
744
enum param_bound {
P
Patrick Walton 已提交
745
    bound_copy,
B
Brian Anderson 已提交
746
    bound_durable,
B
Brian Anderson 已提交
747
    bound_owned,
748
    bound_const,
749
    bound_trait(t),
750 751
}

752 753
enum TyVid = uint;
enum IntVid = uint;
754
enum FloatVid = uint;
755
enum FnVid = uint;
756 757
#[auto_encode]
#[auto_decode]
758
enum RegionVid = uint;
N
Niko Matsakis 已提交
759

760
#[deriving_eq]
761
enum InferTy {
762
    TyVar(TyVid),
763 764
    IntVar(IntVid),
    FloatVar(FloatVid)
765 766
}

767 768 769 770 771
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),
772
          FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f),
773 774 775
        }
    }
}
776

777 778
#[auto_encode]
#[auto_decode]
779 780 781 782 783
enum InferRegion {
    ReVar(RegionVid),
    ReSkolemized(uint, bound_region)
}

784 785 786 787 788 789 790 791
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)
        }
    }
}
792 793

impl InferRegion : cmp::Eq {
794 795 796 797 798 799 800 801 802 803 804 805 806 807
    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))
    }
808 809
}

810 811 812 813
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 已提交
814
          bound_durable => 1u8.iter_bytes(lsb0, f),
B
Brian Anderson 已提交
815
          bound_owned => 2u8.iter_bytes(lsb0, f),
816 817 818 819 820 821
          bound_const => 3u8.iter_bytes(lsb0, f),
          bound_trait(ref t) =>
          to_bytes::iter_bytes_2(&4u8, t, lsb0, f)
        }
    }
}
822

823
trait Vid {
824
    pure fn to_uint() -> uint;
N
Niko Matsakis 已提交
825 826
}

827
impl TyVid: Vid {
828
    pure fn to_uint() -> uint { *self }
829 830 831
}

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

835
impl IntVid: Vid {
836
    pure fn to_uint() -> uint { *self }
837 838 839
}

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

843
impl FloatVid: Vid {
844
    pure fn to_uint() -> uint { *self }
845 846 847
}

impl FloatVid: ToStr {
848 849 850
    pure fn to_str() -> ~str { fmt!("<VF%u>", self.to_uint()) }
}

851
impl FnVid: Vid {
852
    pure fn to_uint() -> uint { *self }
853 854 855
}

impl FnVid: ToStr {
856 857 858
    pure fn to_str() -> ~str { fmt!("<F%u>", self.to_uint()) }
}

859
impl RegionVid: Vid {
860
    pure fn to_uint() -> uint { *self }
N
Niko Matsakis 已提交
861 862
}

863 864 865
impl RegionVid: ToStr {
    pure fn to_str() -> ~str { fmt!("%?", self) }
}
866

867
impl FnSig : ToStr {
868
    pure fn to_str() -> ~str {
869 870
        // grr, without tcx not much we can do.
        return ~"(...)";
871 872 873
    }
}

874
impl InferTy: ToStr {
875
    pure fn to_str() -> ~str {
876 877 878 879 880
        match self {
            TyVar(ref v) => v.to_str(),
            IntVar(ref v) => v.to_str(),
            FloatVar(ref v) => v.to_str()
        }
N
Niko Matsakis 已提交
881 882 883
    }
}

884 885 886 887 888
impl RegionVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
889

890 891 892 893 894
impl TyVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
895

896 897 898 899 900
impl IntVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
901

902 903 904 905 906
impl FloatVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
907

908 909 910 911 912
impl FnVid : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        (**self).iter_bytes(lsb0, f)
    }
}
913

914
fn param_bounds_to_kind(bounds: param_bounds) -> Kind {
915
    let mut kind = kind_noncopyable();
916
    for vec::each(*bounds) |bound| {
917
        match *bound {
B
Brian Anderson 已提交
918
          bound_copy => {
919
            kind = raise_kind(kind, kind_implicitly_copyable());
920
          }
B
Brian Anderson 已提交
921 922
          bound_durable => {
            kind = raise_kind(kind, kind_durable());
923
          }
B
Brian Anderson 已提交
924 925
          bound_owned => {
            kind = raise_kind(kind, kind_owned_only() | kind_durable());
926
          }
B
Brian Anderson 已提交
927
          bound_const => {
928 929
            kind = raise_kind(kind, kind_const());
          }
B
Brian Anderson 已提交
930
          bound_trait(_) => ()
931 932 933 934 935
        }
    }
    kind
}

936 937 938 939 940 941 942 943 944 945
/// A polytype.
///
/// - `bounds`: The list of bounds for each type parameter.  The length of the
///   list also tells you how many type parameters there are.
///
/// - `rp`: true if the type is region-parameterized.  Types can have at
///   most one region parameter, always called `&self`.
///
/// - `ty`: the base type.  May have reference to the (unsubstituted) bound
///   region `&self` or to (unsubstituted) ty_param types
946
type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
B
Brian Anderson 已提交
947
                               region_param: Option<region_variance>,
948
                               ty: t};
949

950 951
type ty_param_substs_and_ty = {substs: ty::substs, ty: ty::t};

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

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

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

958
fn mk_rcache() -> creader_cache {
M
Marijn Haverbeke 已提交
959
    type val = {cnum: int, pos: uint, len: uint};
B
Brian Anderson 已提交
960
    return map::HashMap();
961
}
962

B
Brian Anderson 已提交
963 964
fn new_ty_hash<V: Copy>() -> map::HashMap<t, V> {
    map::HashMap()
965
}
966

967
fn mk_ctxt(s: session::Session,
G
Graydon Hoare 已提交
968
           dm: resolve::DefMap,
969
           amap: ast_map::map,
P
Patrick Walton 已提交
970
           freevars: freevars::freevar_map,
971
           region_map: middle::region::region_map,
972
           region_paramd_items: middle::region::region_paramd_items,
973 974 975 976 977
           +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 {
978
            ast::meta_word(ref w) if (*w) == ~"legacy_modes" => {
979 980 981 982 983 984 985
                legacy_modes = true;
                break;
            }
            _ => {}
        }
    }

B
Brian Anderson 已提交
986
    let interner = map::HashMap();
987
    let vecs_implicitly_copyable =
988 989
        get_lint_level(s.lint_settings.default_settings,
                       lint::vecs_implicitly_copyable) == allow;
990 991
    @{diag: s.diagnostic(),
      interner: interner,
G
Graydon Hoare 已提交
992
      mut next_id: 0u,
993
      vecs_implicitly_copyable: vecs_implicitly_copyable,
994
      legacy_modes: legacy_modes,
995
      cstore: s.cstore,
996 997
      sess: s,
      def_map: dm,
P
Patrick Walton 已提交
998
      region_map: region_map,
999
      region_paramd_items: region_paramd_items,
1000
      node_types: @smallintmap::mk(),
1001
      node_type_substs: map::HashMap(),
1002
      items: amap,
1003
      intrinsic_defs: map::HashMap(),
1004
      freevars: freevars,
1005
      tcache: HashMap(),
1006
      rcache: mk_rcache(),
1007
      ccache: HashMap(),
1008 1009
      short_names_cache: new_ty_hash(),
      needs_drop_cache: new_ty_hash(),
1010
      needs_unwind_cleanup_cache: new_ty_hash(),
1011
      kind_cache: new_ty_hash(),
1012 1013 1014 1015 1016 1017
      ast_ty_to_ty_cache: HashMap(),
      enum_var_cache: HashMap(),
      trait_method_cache: HashMap(),
      ty_param_bounds: HashMap(),
      inferred_modes: HashMap(),
      adjustments: HashMap(),
1018
      normalized_cache: new_ty_hash(),
1019
      lang_items: move lang_items,
1020
      legacy_boxed_traits: HashMap(),
1021
      provided_methods: HashMap(),
1022
      provided_method_sources: HashMap(),
1023
      supertraits: HashMap(),
1024
      destructor_for_type: HashMap(),
1025 1026
      destructors: HashMap(),
      value_modes: HashMap()}
1027
}
1028 1029


1030
// Type constructors
B
Brian Anderson 已提交
1031
fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) }
1032 1033 1034

// 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 已提交
1035
fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
1036
    let key = {sty: to_unsafe_ptr(&st), o_def_id: o_def_id};
1037
    match cx.interner.find(key) {
1038
      Some(t) => unsafe { return cast::reinterpret_cast(&t); },
B
Brian Anderson 已提交
1039
      _ => ()
1040
    }
1041

1042
    let mut flags = 0u;
1043
    fn rflags(r: Region) -> uint {
1044
        (has_regions as uint) | {
1045
            match r {
1046
              ty::re_infer(_) => needs_infer as uint,
B
Brian Anderson 已提交
1047
              _ => 0u
1048
            }
N
Niko Matsakis 已提交
1049 1050
        }
    }
N
Niko Matsakis 已提交
1051
    fn sflags(substs: &substs) -> uint {
1052
        let mut f = 0u;
1053
        for substs.tps.each |tt| { f |= get(*tt).flags; }
B
Brian Anderson 已提交
1054
        substs.self_r.iter(|r| f |= rflags(*r));
B
Brian Anderson 已提交
1055
        return f;
N
Niko Matsakis 已提交
1056
    }
1057 1058
    match &st {
      &ty_estr(vstore_slice(r)) => {
1059
        flags |= rflags(r);
1060
      }
1061
      &ty_evec(ref mt, vstore_slice(r)) => {
1062 1063
        flags |= rflags(r);
        flags |= get(mt.ty).flags;
1064
      }
1065 1066
      &ty_nil | &ty_bot | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
      &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
1067 1068
      &ty_opaque_box => (),
      &ty_err => flags |= has_ty_err as uint,
1069 1070 1071 1072 1073
      &ty_param(_) => flags |= has_params as uint,
      &ty_infer(_) => flags |= needs_infer as uint,
      &ty_self => flags |= has_self as uint,
      &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
      &ty_trait(_, ref substs, _) => {
1074
        flags |= sflags(substs);
1075
      }
1076 1077
      &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
      &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
1078
        flags |= get(m.ty).flags;
1079
      }
1080
      &ty_rptr(r, ref m) => {
1081 1082
        flags |= rflags(r);
        flags |= get(m.ty).flags;
M
Marijn Haverbeke 已提交
1083
      }
1084 1085 1086
      &ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
      &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
      &ty_fn(ref f) => {
1087
        flags |= rflags(f.meta.region);
1088 1089
        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
        flags |= get(f.sig.output).flags;
M
Marijn Haverbeke 已提交
1090
      }
1091
    }
1092 1093 1094 1095 1096 1097

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

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

1098
    cx.next_id += 1u;
1099
    unsafe { cast::reinterpret_cast(&t) }
1100 1101
}

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

1104 1105
fn mk_err(cx: ctxt) -> t { mk_t(cx, ty_err) }

1106
fn mk_bot(cx: ctxt) -> t { mk_t(cx, ty_bot) }
1107

1108
fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) }
1109

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

1112 1113 1114 1115 1116 1117 1118 1119
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)) }

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

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

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

1126 1127 1128 1129 1130 1131
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)) }

1132 1133 1134 1135
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)) }

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

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

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

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

1144 1145 1146 1147
fn mk_estr(cx: ctxt, t: vstore) -> t {
    mk_t(cx, ty_estr(t))
}

N
Niko Matsakis 已提交
1148 1149
fn mk_enum(cx: ctxt, did: ast::def_id, +substs: substs) -> t {
    // take a copy of substs so that we own the vectors inside
1150
    mk_t(cx, ty_enum(did, substs))
1151
}
1152

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

1155 1156 1157
fn mk_imm_box(cx: ctxt, ty: t) -> t {
    mk_box(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1158

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

1161 1162 1163
fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
    mk_uniq(cx, mt {ty: ty, mutbl: ast::m_imm})
}
1164

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

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

1169
fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1170
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_mutbl})
1171
}
1172
fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1173
    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_imm})
1174 1175
}

1176 1177 1178
fn mk_mut_ptr(cx: ctxt, ty: t) -> t {
    mk_ptr(cx, mt {ty: ty, mutbl: ast::m_mutbl})
}
1179

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

1184
fn mk_nil_ptr(cx: ctxt) -> t {
1185
    mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::m_imm})
1186 1187
}

1188 1189 1190 1191
fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
    mk_t(cx, ty_evec(tm, t))
}

M
Michael Sullivan 已提交
1192 1193 1194
fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
    mk_t(cx, ty_unboxed_vec(tm))
}
1195
fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
1196
    mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::m_imm}))
1197
}
M
Michael Sullivan 已提交
1198

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

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

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

1206 1207
fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
         -> t {
N
Niko Matsakis 已提交
1208
    // take a copy of substs so that we own the vectors inside
1209
    mk_t(cx, ty_trait(did, substs, vstore))
1210 1211
}

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

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

1219 1220 1221
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)) }
1222

1223
fn mk_infer(cx: ctxt, +it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
1224

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

1227 1228 1229
fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
    mk_t(cx, ty_param({idx: n, def_id: k}))
}
1230

1231
fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
1232

1233 1234
fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t {
    mk_t(cx, ty_opaque_closure_ptr(proto))
1235 1236
}

1237 1238
fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }

1239
fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t {
1240
    mk_t_with_id(cx, /*bad*/copy get(base).sty, Some(def_id))
1241 1242 1243
}

// Converts s to its machine type equivalent
1244
pure fn mach_sty(cfg: @session::config, t: t) -> sty {
1245
    match get(t).sty {
B
Brian Anderson 已提交
1246 1247 1248
      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),
1249
      ref s => (/*bad*/copy *s)
1250 1251 1252
    }
}

1253
fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
1254 1255 1256 1257
        // 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) {
1258 1259 1260 1261
            ast::ProtoBorrowed => {
                return ast::by_ref;
            }
            _ => {}
1262 1263 1264
        }
    }
    return if tcx.legacy_modes {
1265 1266 1267 1268 1269 1270 1271 1272 1273
        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
        }
1274 1275
    } else {
        ast::by_copy
1276 1277 1278 1279 1280 1281 1282
    };

    fn type_is_fn(ty: t) -> bool {
        match get(ty).sty {
            ty_fn(*) => true,
            _ => false
        }
1283
    }
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295

    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
        }
    }
1296 1297
}

1298 1299
// Returns the narrowest lifetime enclosing the evaluation of the expression
// with id `id`.
1300
fn encl_region(cx: ctxt, id: ast::node_id) -> ty::Region {
1301
    match cx.region_map.find(id) {
B
Brian Anderson 已提交
1302 1303
      Some(encl_scope) => ty::re_scope(encl_scope),
      None => ty::re_static
1304 1305 1306
    }
}

1307
fn walk_ty(ty: t, f: fn(t)) {
B
Brian Anderson 已提交
1308
    maybe_walk_ty(ty, |t| { f(t); true });
1309 1310 1311
}

fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
B
Brian Anderson 已提交
1312
    if !f(ty) { return; }
1313
    match /*bad*/copy get(ty).sty {
1314
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
M
Michael Sullivan 已提交
1315
      ty_estr(_) | ty_type | ty_opaque_box | ty_self |
1316
      ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1317
      }
M
Michael Sullivan 已提交
1318
      ty_box(tm) | ty_evec(tm, _) | ty_unboxed_vec(tm) |
B
Brian Anderson 已提交
1319
      ty_ptr(tm) | ty_rptr(_, tm) => {
1320
        maybe_walk_ty(tm.ty, f);
1321
      }
1322
      ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1323 1324
      ty_trait(_, ref substs, _) => {
        for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); }
1325
      }
B
Brian Anderson 已提交
1326
      ty_rec(fields) => {
B
Brian Anderson 已提交
1327
        for fields.each |fl| { maybe_walk_ty(fl.mt.ty, f); }
M
Marijn Haverbeke 已提交
1328
      }
1329
      ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
N
Niko Matsakis 已提交
1330
      ty_fn(ref ft) => {
1331 1332
        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
        maybe_walk_ty(ft.sig.output, f);
M
Marijn Haverbeke 已提交
1333
      }
B
Brian Anderson 已提交
1334
      ty_uniq(tm) => { maybe_walk_ty(tm.ty, f); }
1335 1336 1337
    }
}

N
Niko Matsakis 已提交
1338
fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: fn(t) -> t) -> t {
N
Niko Matsakis 已提交
1339
    mk_t(tcx, fold_sty(sty, foldop))
1340
}
1341

1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
fn fold_sig(sig: &FnSig, fldop: fn(t) -> t) -> FnSig {
    let args = do sig.inputs.map |arg| {
        { mode: arg.mode, ty: fldop(arg.ty) }
    };

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

N
Niko Matsakis 已提交
1353 1354
fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
    fn fold_substs(substs: &substs, fldop: fn(t) -> t) -> substs {
1355
        {self_r: substs.self_r,
1356
         self_ty: substs.self_ty.map(|t| fldop(*t)),
1357
         tps: substs.tps.map(|t| fldop(*t))}
1358 1359
    }

1360
    match /*bad*/copy *sty {
1361
        ty_box(tm) => {
1362
            ty_box(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1363 1364
        }
        ty_uniq(tm) => {
1365
            ty_uniq(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1366 1367
        }
        ty_ptr(tm) => {
1368
            ty_ptr(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1369 1370
        }
        ty_unboxed_vec(tm) => {
1371
            ty_unboxed_vec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1372 1373
        }
        ty_evec(tm, vst) => {
1374
            ty_evec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
        }
        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);
1385
                let new_mt = mt {ty: new_ty, mutbl: fl.mt.mutbl};
1386 1387 1388 1389 1390
                {ident: fl.ident, mt: new_mt}
            };
            ty_rec(new_fields)
        }
        ty_tup(ts) => {
1391
            let new_ts = vec::map(ts, |tt| fldop(*tt));
1392 1393 1394
            ty_tup(new_ts)
        }
        ty_fn(ref f) => {
1395 1396
            let sig = fold_sig(&f.sig, fldop);
            ty_fn(FnTyBase {meta: f.meta, sig: sig})
1397 1398
        }
        ty_rptr(r, tm) => {
1399
            ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1400
        }
1401 1402
        ty_struct(did, ref substs) => {
            ty_struct(did, fold_substs(substs, fldop))
1403 1404
        }
        ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1405
        ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1406
        ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self => {
1407
            /*bad*/copy *sty
1408
        }
N
Niko Matsakis 已提交
1409 1410
    }
}
1411

N
Niko Matsakis 已提交
1412 1413
// Folds types from the bottom up.
fn fold_ty(cx: ctxt, t0: t, fldop: fn(t) -> t) -> t {
1414
    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
N
Niko Matsakis 已提交
1415 1416
    fldop(mk_t(cx, sty))
}
1417

1418 1419 1420
fn walk_regions_and_ty(
    cx: ctxt,
    ty: t,
1421
    walkr: fn(r: Region),
1422 1423 1424 1425 1426
    walkt: fn(t: t) -> bool) {

    if (walkt(ty)) {
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1427 1428 1429
            |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 });
1430 1431 1432
    }
}

1433 1434 1435
fn fold_regions_and_ty(
    cx: ctxt,
    ty: t,
1436
    fldr: fn(r: Region) -> Region,
1437 1438 1439 1440
    fldfnt: fn(t: t) -> t,
    fldt: fn(t: t) -> t) -> t {

    fn fold_substs(
N
Niko Matsakis 已提交
1441
        substs: &substs,
1442
        fldr: fn(r: Region) -> Region,
1443 1444
        fldt: fn(t: t) -> t) -> substs
    {
1445 1446
        {self_r: substs.self_r.map(|r| fldr(*r)),
         self_ty: substs.self_ty.map(|t| fldt(*t)),
1447
         tps: substs.tps.map(|t| fldt(*t))}
1448 1449 1450
    }

    let tb = ty::get(ty);
1451
    match tb.sty {
B
Brian Anderson 已提交
1452
      ty::ty_rptr(r, mt) => {
1453 1454
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1455
        ty::mk_rptr(cx, m_r, mt {ty: m_t, mutbl: mt.mutbl})
1456
      }
B
Brian Anderson 已提交
1457
      ty_estr(vstore_slice(r)) => {
1458 1459 1460
        let m_r = fldr(r);
        ty::mk_estr(cx, vstore_slice(m_r))
      }
B
Brian Anderson 已提交
1461
      ty_evec(mt, vstore_slice(r)) => {
1462 1463
        let m_r = fldr(r);
        let m_t = fldt(mt.ty);
1464
        ty::mk_evec(cx, mt {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
1465
      }
N
Niko Matsakis 已提交
1466
      ty_enum(def_id, ref substs) => {
1467 1468
        ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
      }
1469 1470
      ty_struct(def_id, ref substs) => {
        ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1471
      }
1472 1473
      ty_trait(def_id, ref substs, vst) => {
        ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
1474
      }
1475
      ty_fn(ref f) => {
1476 1477 1478
          ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region),
                                                ..f.meta},
                                  sig: fold_sig(&f.sig, fldfnt)})
1479
      }
N
Niko Matsakis 已提交
1480
      ref sty => {
B
Brian Anderson 已提交
1481
        fold_sty_to_ty(cx, sty, |t| fldt(t))
1482 1483 1484 1485
      }
    }
}

1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497
/* 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
{
1498
    let t0 = ty::mk_fn(cx, /*bad*/copy *f);
1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
    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");
        }
    }
}

1510 1511 1512 1513 1514
// 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,
1515 1516
    fldr: fn(r: Region, in_fn: bool) -> Region) -> t
{
1517
    fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1518
               fldr: fn(Region, bool) -> Region) -> t {
1519
        debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
B
Brian Anderson 已提交
1520
        if !type_has_regions(ty) { return ty; }
1521 1522
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1523 1524 1525
            |r| fldr(r, in_fn),
            |t| do_fold(cx, t, true, fldr),
            |t| do_fold(cx, t, in_fn, fldr))
1526 1527 1528 1529
    }
    do_fold(cx, ty, false, fldr)
}

1530
fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t {
N
Niko Matsakis 已提交
1531
    fn do_fold(cx: ctxt, t0: t, under_r: bool,
1532
               fldop: fn(Region, bool) -> Region) -> t {
N
Niko Matsakis 已提交
1533
        let tb = get(t0);
B
Brian Anderson 已提交
1534
        if !tbox_has_flag(tb, has_regions) { return t0; }
1535
        match tb.sty {
1536
          ty_rptr(r, mt {ty: t1, mutbl: m}) => {
N
Niko Matsakis 已提交
1537 1538
            let m_r = fldop(r, under_r);
            let m_t1 = do_fold(cx, t1, true, fldop);
1539
            ty::mk_rptr(cx, m_r, mt {ty: m_t1, mutbl: m})
1540
          }
B
Brian Anderson 已提交
1541
          ty_estr(vstore_slice(r)) => {
1542 1543 1544
            let m_r = fldop(r, under_r);
            ty::mk_estr(cx, vstore_slice(m_r))
          }
1545
          ty_evec(mt {ty: t1, mutbl: m}, vstore_slice(r)) => {
1546 1547
            let m_r = fldop(r, under_r);
            let m_t1 = do_fold(cx, t1, true, fldop);
1548
            ty::mk_evec(cx, mt {ty: m_t1, mutbl: m}, vstore_slice(m_r))
1549
          }
B
Brian Anderson 已提交
1550
          ty_fn(_) => {
N
Niko Matsakis 已提交
1551 1552
            // do not recurse into functions, which introduce fresh bindings
            t0
1553
          }
N
Niko Matsakis 已提交
1554
          ref sty => {
B
Brian Anderson 已提交
1555
            do fold_sty_to_ty(cx, sty) |t| {
N
Niko Matsakis 已提交
1556
                do_fold(cx, t, under_r, fldop)
1557
            }
1558
          }
N
Niko Matsakis 已提交
1559
      }
1560
    }
1561

N
Niko Matsakis 已提交
1562
    do_fold(cx, t0, false, fldop)
1563 1564
}

1565
// Substitute *only* type parameters.  Used in trans where regions are erased.
1566 1567
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; }
1568
    let tb = ty::get(typ);
1569
    if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1570
    match tb.sty {
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582
        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))
        }
1583 1584 1585
    }
}

N
Niko Matsakis 已提交
1586
fn substs_is_noop(substs: &substs) -> bool {
1587 1588 1589
    substs.tps.len() == 0u &&
        substs.self_r.is_none() &&
        substs.self_ty.is_none()
1590 1591
}

N
Niko Matsakis 已提交
1592
fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
P
Paul Stansifer 已提交
1593
    fmt!("substs(self_r=%s, self_ty=%s, tps=%?)",
1594
         substs.self_r.map_default(~"none", |r| region_to_str(cx, *r)),
1595 1596
         substs.self_ty.map_default(~"none",
                                    |t| ::util::ppaux::ty_to_str(cx, *t)),
1597
         tys_to_str(cx, substs.tps))
1598 1599
}

1600 1601 1602
fn param_bound_to_str(cx: ctxt, pb: &param_bound) -> ~str {
    match *pb {
        bound_copy => ~"copy",
1603
        bound_durable => ~"&static",
B
Brian Anderson 已提交
1604
        bound_owned => ~"owned",
1605
        bound_const => ~"const",
1606
        bound_trait(t) => ::util::ppaux::ty_to_str(cx, t)
1607 1608 1609 1610
    }
}

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

1614
fn subst(cx: ctxt,
N
Niko Matsakis 已提交
1615
         substs: &substs,
1616 1617
         typ: t) -> t {

P
Paul Stansifer 已提交
1618
    debug!("subst(substs=%s, typ=%s)",
1619
           substs_to_str(cx, substs),
1620
           ::util::ppaux::ty_to_str(cx, typ));
N
Niko Matsakis 已提交
1621

B
Brian Anderson 已提交
1622
    if substs_is_noop(substs) { return typ; }
1623
    let r = do_subst(cx, substs, typ);
1624
    debug!("  r = %s", ::util::ppaux::ty_to_str(cx, r));
B
Brian Anderson 已提交
1625
    return r;
1626 1627

    fn do_subst(cx: ctxt,
N
Niko Matsakis 已提交
1628
                substs: &substs,
1629 1630
                typ: t) -> t {
        let tb = get(typ);
B
Brian Anderson 已提交
1631
        if !tbox_has_flag(tb, needs_subst) { return typ; }
1632
        match tb.sty {
B
Brian Anderson 已提交
1633 1634 1635
          ty_param(p) => substs.tps[p.idx],
          ty_self => substs.self_ty.get(),
          _ => {
1636 1637
            fold_regions_and_ty(
                cx, typ,
1638
                |r| match r {
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650
                    re_bound(br_self) => {
                        match substs.self_r {
                            None => {
                                cx.sess.bug(
                                    fmt!("ty::subst: \
                                  Reference to self region when given substs \
                                  with no self region, ty = %s",
                                  ::util::ppaux::ty_to_str(cx, typ)))
                            }
                            Some(self_r) => self_r
                        }
                    }
B
Brian Anderson 已提交
1651
                    _ => r
1652
                },
B
Brian Anderson 已提交
1653 1654
                |t| do_subst(cx, substs, t),
                |t| do_subst(cx, substs, t))
1655 1656
          }
        }
N
Niko Matsakis 已提交
1657 1658
    }
}
1659

1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
// 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))
    }
}

1670
// Type utilities
1671

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

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

1676
fn type_is_ty_var(ty: t) -> bool {
1677
    match get(ty).sty {
1678
      ty_infer(TyVar(_)) => true,
B
Brian Anderson 已提交
1679
      _ => false
1680 1681 1682
    }
}

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

1685
fn type_is_structural(ty: t) -> bool {
1686
    match get(ty).sty {
1687
      ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_fn(_) |
1688 1689 1690
      ty_trait(*) |
      ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
B
Brian Anderson 已提交
1691 1692
      => true,
      _ => false
1693 1694 1695
    }
}

1696
fn type_is_copyable(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
1697
    return kind_can_be_copied(type_kind(cx, ty));
1698 1699
}

1700
fn type_is_sequence(ty: t) -> bool {
1701
    match get(ty).sty {
B
Brian Anderson 已提交
1702 1703
      ty_estr(_) | ty_evec(_, _) => true,
      _ => false
1704 1705 1706
    }
}

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

1714
fn sequence_element_type(cx: ctxt, ty: t) -> t {
1715
    match get(ty).sty {
B
Brian Anderson 已提交
1716 1717 1718 1719
      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"),
1720 1721 1722
    }
}

1723
fn get_element_type(ty: t, i: uint) -> t {
1724
    match /*bad*/copy get(ty).sty {
B
Brian Anderson 已提交
1725 1726 1727
      ty_rec(flds) => return flds[i].mt.ty,
      ty_tup(ts) => return ts[i],
      _ => fail ~"get_element_type called on invalid type"
1728 1729 1730
    }
}

1731
pure fn type_is_box(ty: t) -> bool {
1732
    match get(ty).sty {
B
Brian Anderson 已提交
1733 1734
      ty_box(_) => return true,
      _ => return false
1735
    }
M
Marijn Haverbeke 已提交
1736 1737
}

1738
pure fn type_is_boxed(ty: t) -> bool {
1739
    match get(ty).sty {
1740
      ty_box(_) | ty_opaque_box |
B
Brian Anderson 已提交
1741 1742
      ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
      _ => false
1743 1744 1745
    }
}

1746
pure fn type_is_region_ptr(ty: t) -> bool {
1747
    match get(ty).sty {
B
Brian Anderson 已提交
1748 1749
      ty_rptr(_, _) => true,
      _ => false
1750 1751 1752
    }
}

1753
pure fn type_is_slice(ty: t) -> bool {
1754
    match get(ty).sty {
B
Brian Anderson 已提交
1755 1756
      ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
      _ => return false
1757 1758 1759
    }
}

1760
pure fn type_is_unique_box(ty: t) -> bool {
1761
    match get(ty).sty {
B
Brian Anderson 已提交
1762 1763
      ty_uniq(_) => return true,
      _ => return false
1764
    }
M
Marijn Haverbeke 已提交
1765
}
1766

1767
pure fn type_is_unsafe_ptr(ty: t) -> bool {
1768
    match get(ty).sty {
B
Brian Anderson 已提交
1769 1770
      ty_ptr(_) => return true,
      _ => return false
1771 1772 1773
    }
}

1774
pure fn type_is_vec(ty: t) -> bool {
1775
    return match get(ty).sty {
B
Brian Anderson 已提交
1776 1777 1778
          ty_evec(_, _) | ty_unboxed_vec(_) => true,
          ty_estr(_) => true,
          _ => false
B
Brian Anderson 已提交
1779
        };
M
Marijn Haverbeke 已提交
1780 1781
}

1782
pure fn type_is_unique(ty: t) -> bool {
1783
    match get(ty).sty {
B
Brian Anderson 已提交
1784 1785 1786 1787
      ty_uniq(_) => return true,
      ty_evec(_, vstore_uniq) => true,
      ty_estr(vstore_uniq) => true,
      _ => return false
B
Brian Anderson 已提交
1788
    }
1789 1790
}

1791 1792 1793 1794 1795
/*
 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.)
*/
1796
pure fn type_is_scalar(ty: t) -> bool {
1797
    match get(ty).sty {
1798
      ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1799 1800
      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
      ty_ptr(_) => true,
B
Brian Anderson 已提交
1801
      _ => false
M
Marijn Haverbeke 已提交
1802
    }
1803 1804
}

1805
fn type_is_immediate(ty: t) -> bool {
B
Brian Anderson 已提交
1806
    return type_is_scalar(ty) || type_is_boxed(ty) ||
1807
        type_is_unique(ty) || type_is_region_ptr(ty);
1808 1809
}

1810
fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1811
    match cx.needs_drop_cache.find(ty) {
B
Brian Anderson 已提交
1812 1813
      Some(result) => return result,
      None => {/* fall through */ }
M
Marijn Haverbeke 已提交
1814 1815
    }

1816
    let mut accum = false;
1817
    let result = match /*bad*/copy get(ty).sty {
M
Marijn Haverbeke 已提交
1818
      // scalar types
1819
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1820
      ty_type | ty_ptr(_) | ty_rptr(_, _) |
1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
      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,

1833 1834 1835 1836
      ty_trait(_, _, vstore_box) |
      ty_trait(_, _, vstore_uniq) => true,
      ty_trait(_, _, vstore_fixed(_)) |
      ty_trait(_, _, vstore_slice(_)) => false,
1837

1838
      ty_param(*) | ty_infer(*) | ty_err => true,
1839

B
Brian Anderson 已提交
1840 1841 1842
      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 已提交
1843 1844 1845
        for flds.each |f| {
            if type_needs_drop(cx, f.mt.ty) { accum = true; }
        }
1846
        accum
M
Marijn Haverbeke 已提交
1847
      }
1848 1849
      ty_struct(did, ref substs) => {
         // Any struct with a dtor needs a drop
1850
         ty_dtor(cx, did).is_present() || {
1851
             for vec::each(ty::struct_fields(cx, did, substs)) |f| {
1852 1853 1854
                 if type_needs_drop(cx, f.mt.ty) { accum = true; }
             }
             accum
1855
         }
1856
      }
B
Brian Anderson 已提交
1857
      ty_tup(elts) => {
1858
          for elts.each |m| { if type_needs_drop(cx, *m) { accum = true; } }
1859
        accum
1860
      }
N
Niko Matsakis 已提交
1861
      ty_enum(did, ref substs) => {
1862
        let variants = enum_variants(cx, did);
1863
          for vec::each(*variants) |variant| {
B
Brian Anderson 已提交
1864
              for variant.args.each |aty| {
M
Marijn Haverbeke 已提交
1865
                // Perform any type parameter substitutions.
1866
                let arg_ty = subst(cx, substs, *aty);
1867
                if type_needs_drop(cx, arg_ty) { accum = true; }
1868
            }
1869
            if accum { break; }
1870
        }
1871
        accum
M
Marijn Haverbeke 已提交
1872
      }
N
Niko Matsakis 已提交
1873
      ty_fn(ref fty) => {
1874
        match fty.meta.proto {
1875 1876
          ast::ProtoBare | ast::ProtoBorrowed => false,
          ast::ProtoBox | ast::ProtoUniq => true,
1877 1878
        }
      }
1879
    };
1880

1881
    cx.needs_drop_cache.insert(ty, result);
B
Brian Anderson 已提交
1882
    return result;
1883 1884
}

1885 1886 1887 1888 1889
// 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 {
1890
    match cx.needs_unwind_cleanup_cache.find(ty) {
B
Brian Anderson 已提交
1891 1892
      Some(result) => return result,
      None => ()
1893 1894
    }

1895 1896 1897 1898
    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 已提交
1899
    return needs_unwind_cleanup;
1900 1901 1902
}

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

1906
    // Prevent infinite recursion
1907
    match tycache.find(ty) {
B
Brian Anderson 已提交
1908 1909
      Some(_) => return false,
      None => { tycache.insert(ty, ()); }
1910
    }
1911

1912
    let mut encountered_box = encountered_box;
1913
    let mut needs_unwind_cleanup = false;
B
Brian Anderson 已提交
1914
    do maybe_walk_ty(ty) |ty| {
1915
        let old_encountered_box = encountered_box;
1916
        let result = match get(ty).sty {
B
Brian Anderson 已提交
1917
          ty_box(_) | ty_opaque_box => {
1918 1919 1920
            encountered_box = true;
            true
          }
1921 1922
          ty_nil | ty_bot | ty_bool |
          ty_int(_) | ty_uint(_) | ty_float(_) |
B
Brian Anderson 已提交
1923
          ty_rec(_) | ty_tup(_) | ty_ptr(_) => {
1924 1925
            true
          }
N
Niko Matsakis 已提交
1926
          ty_enum(did, ref substs) => {
1927
            for vec::each(*enum_variants(cx, did)) |v| {
B
Brian Anderson 已提交
1928
                for v.args.each |aty| {
1929
                    let t = subst(cx, substs, *aty);
1930 1931 1932
                    needs_unwind_cleanup |=
                        type_needs_unwind_cleanup_(cx, t, tycache,
                                                   encountered_box);
1933 1934 1935 1936
                }
            }
            !needs_unwind_cleanup
          }
M
Michael Sullivan 已提交
1937
          ty_uniq(_) |
1938 1939 1940 1941
          ty_estr(vstore_uniq) |
          ty_estr(vstore_box) |
          ty_evec(_, vstore_uniq) |
          ty_evec(_, vstore_box)
B
Brian Anderson 已提交
1942
          => {
1943 1944 1945 1946 1947 1948 1949 1950 1951
            // 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 已提交
1952
          _ => {
1953 1954 1955
            needs_unwind_cleanup = true;
            false
          }
1956 1957 1958 1959
        };

        encountered_box = old_encountered_box;
        result
1960 1961
    }

B
Brian Anderson 已提交
1962
    return needs_unwind_cleanup;
1963 1964
}

1965
enum Kind { kind_(u32) }
1966

1967
/// can be copied (implicitly or explicitly)
1968
const KIND_MASK_COPY         : u32 = 0b000000000000000000000000001_u32;
1969

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

B
Brian Anderson 已提交
1973 1974
/// is durable (no borrowed ptrs)
const KIND_MASK_DURABLE      : u32 = 0b000000000000000000000000100_u32;
1975 1976

/// is deeply immutable
1977
const KIND_MASK_CONST        : u32 = 0b000000000000000000000001000_u32;
1978 1979

/// can be implicitly copied (must imply COPY)
1980 1981 1982 1983
const KIND_MASK_IMPLICIT     : u32 = 0b000000000000000000000010000_u32;

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

1985
fn kind_noncopyable() -> Kind {
1986 1987 1988
    kind_(0u32)
}

1989
fn kind_copyable() -> Kind {
1990 1991 1992
    kind_(KIND_MASK_COPY)
}

1993
fn kind_implicitly_copyable() -> Kind {
1994 1995 1996
    kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY)
}

1997
fn kind_safe_for_default_mode() -> Kind {
1998 1999 2000 2001
    // similar to implicit copy, but always includes vectors and strings
    kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT | KIND_MASK_COPY)
}

2002
fn kind_implicitly_sendable() -> Kind {
B
Brian Anderson 已提交
2003
    kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_OWNED)
2004 2005
}

2006
fn kind_safe_for_default_mode_send() -> Kind {
2007 2008
    // similar to implicit copy, but always includes vectors and strings
    kind_(KIND_MASK_DEFAULT_MODE | KIND_MASK_IMPLICIT |
B
Brian Anderson 已提交
2009
          KIND_MASK_COPY | KIND_MASK_OWNED)
2010 2011 2012
}


B
Brian Anderson 已提交
2013 2014
fn kind_owned_copy() -> Kind {
    kind_(KIND_MASK_COPY | KIND_MASK_OWNED)
2015
}
2016

B
Brian Anderson 已提交
2017 2018
fn kind_owned_only() -> Kind {
    kind_(KIND_MASK_OWNED)
2019 2020
}

2021
fn kind_const() -> Kind {
2022 2023 2024
    kind_(KIND_MASK_CONST)
}

B
Brian Anderson 已提交
2025 2026
fn kind_durable() -> Kind {
    kind_(KIND_MASK_DURABLE)
2027 2028
}

2029
fn kind_top() -> Kind {
2030 2031 2032
    kind_(0xffffffffu32)
}

2033
fn remove_const(k: Kind) -> Kind {
2034
    k - kind_const()
2035 2036
}

2037
fn remove_implicit(k: Kind) -> Kind {
2038
    k - kind_(KIND_MASK_IMPLICIT | KIND_MASK_DEFAULT_MODE)
2039 2040
}

B
Brian Anderson 已提交
2041 2042
fn remove_owned(k: Kind) -> Kind {
    k - kind_(KIND_MASK_OWNED)
2043 2044
}

B
Brian Anderson 已提交
2045 2046
fn remove_durable_owned(k: Kind) -> Kind {
    k - kind_(KIND_MASK_DURABLE) - kind_(KIND_MASK_OWNED)
2047 2048
}

2049
fn remove_copyable(k: Kind) -> Kind {
2050
    k - kind_(KIND_MASK_COPY | KIND_MASK_DEFAULT_MODE)
2051 2052
}

2053
impl Kind : ops::BitAnd<Kind,Kind> {
2054
    pure fn bitand(&self, other: &Kind) -> Kind {
2055
        unsafe {
2056
            lower_kind(*self, *other)
2057 2058 2059
        }
    }
}
2060

2061
impl Kind : ops::BitOr<Kind,Kind> {
2062
    pure fn bitor(&self, other: &Kind) -> Kind {
2063
        unsafe {
2064
            raise_kind(*self, *other)
2065 2066 2067
        }
    }
}
2068

2069
impl Kind : ops::Sub<Kind,Kind> {
2070
    pure fn sub(&self, other: &Kind) -> Kind {
2071
        unsafe {
2072
            kind_(**self & !**other)
2073 2074 2075
        }
    }
}
2076

2077
// Using these query functions is preferable to direct comparison or matching
2078 2079
// against the kind constants, as we may modify the kind hierarchy in the
// future.
2080
pure fn kind_can_be_implicitly_copied(k: Kind) -> bool {
2081
    *k & KIND_MASK_IMPLICIT == KIND_MASK_IMPLICIT
2082 2083
}

2084
pure fn kind_is_safe_for_default_mode(k: Kind) -> bool {
2085 2086 2087
    *k & KIND_MASK_DEFAULT_MODE == KIND_MASK_DEFAULT_MODE
}

2088
pure fn kind_can_be_copied(k: Kind) -> bool {
2089
    *k & KIND_MASK_COPY == KIND_MASK_COPY
2090 2091
}

2092
pure fn kind_can_be_sent(k: Kind) -> bool {
B
Brian Anderson 已提交
2093
    *k & KIND_MASK_OWNED == KIND_MASK_OWNED
2094 2095
}

B
Brian Anderson 已提交
2096 2097
pure fn kind_is_durable(k: Kind) -> bool {
    *k & KIND_MASK_DURABLE == KIND_MASK_DURABLE
2098 2099
}

2100
fn meta_kind(p: FnMeta) -> Kind {
2101
    match p.proto { // XXX consider the kind bounds!
2102
        ast::ProtoBare => {
B
Brian Anderson 已提交
2103
            kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2104 2105 2106 2107 2108
        }
        ast::ProtoBorrowed => {
            kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE)
        }
        ast::ProtoBox => {
B
Brian Anderson 已提交
2109
            kind_safe_for_default_mode() | kind_durable()
2110 2111
        }
        ast::ProtoUniq => {
B
Brian Anderson 已提交
2112
            kind_owned_copy() | kind_durable()
2113
        }
2114 2115 2116
    }
}

2117
fn kind_lteq(a: Kind, b: Kind) -> bool {
2118
    *a & *b == *a
M
Marijn Haverbeke 已提交
2119 2120
}

2121
fn lower_kind(a: Kind, b: Kind) -> Kind {
2122 2123 2124
    kind_(*a & *b)
}

2125
fn raise_kind(a: Kind, b: Kind) -> Kind {
2126
    kind_(*a | *b)
M
Marijn Haverbeke 已提交
2127 2128
}

2129 2130
#[test]
fn test_kinds() {
2131 2132
    // The kind "lattice" is defined by the subset operation on the
    // set of permitted operations.
B
Brian Anderson 已提交
2133 2134
    assert kind_lteq(kind_owned_copy(), kind_owned_copy());
    assert kind_lteq(kind_copyable(), kind_owned_copy());
2135
    assert kind_lteq(kind_copyable(), kind_copyable());
B
Brian Anderson 已提交
2136
    assert kind_lteq(kind_noncopyable(), kind_owned_copy());
2137 2138
    assert kind_lteq(kind_noncopyable(), kind_copyable());
    assert kind_lteq(kind_noncopyable(), kind_noncopyable());
2139 2140
    assert kind_lteq(kind_copyable(), kind_implicitly_copyable());
    assert kind_lteq(kind_copyable(), kind_implicitly_sendable());
B
Brian Anderson 已提交
2141 2142 2143
    assert kind_lteq(kind_owned_copy(), kind_implicitly_sendable());
    assert !kind_lteq(kind_owned_copy(), kind_implicitly_copyable());
    assert !kind_lteq(kind_copyable(), kind_owned_only());
2144 2145 2146 2147 2148
}

// 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
2149
// implicitly copied and to compute whether things have const kind.
2150
fn mutability_kind(m: mutability) -> Kind {
2151
    match (m) {
B
Brian Anderson 已提交
2152 2153 2154
      m_mutbl => remove_const(remove_implicit(kind_top())),
      m_const => remove_implicit(kind_top()),
      m_imm => kind_top()
2155 2156 2157
    }
}

2158
fn mutable_type_kind(cx: ctxt, ty: mt) -> Kind {
2159
    lower_kind(mutability_kind(ty.mutbl), type_kind(cx, ty.ty))
2160 2161
}

2162
fn type_kind(cx: ctxt, ty: t) -> Kind {
2163 2164 2165 2166 2167 2168
    type_kind_ext(cx, ty, false)
}

// If `allow_ty_var` is true, then this is a conservative assumption; we
// assume that type variables *do* have all kinds.
fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
2169
    match cx.kind_cache.find(ty) {
B
Brian Anderson 已提交
2170 2171
      Some(result) => return result,
      None => {/* fall through */ }
2172 2173 2174
    }

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

2177
    let mut result = match /*bad*/copy get(ty).sty {
2178
      // Scalar and unique types are sendable, constant, and owned
2179
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
B
Brian Anderson 已提交
2180
      ty_ptr(_) => {
B
Brian Anderson 已提交
2181
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2182 2183
      }

2184
      // Implicit copyability of strs is configurable
B
Brian Anderson 已提交
2185
      ty_estr(vstore_uniq) => {
2186
        if cx.vecs_implicitly_copyable {
B
Brian Anderson 已提交
2187
            kind_implicitly_sendable() | kind_const() | kind_durable()
2188
        } else {
B
Brian Anderson 已提交
2189
            kind_owned_copy() | kind_const() | kind_durable()
2190
        }
2191
      }
2192 2193

      // functions depend on the protocol
2194
      ty_fn(ref f) => meta_kind(f.meta),
2195 2196 2197

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

2202
      // XXX: This is wrong for ~Trait and &Trait!
2203
      ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_durable(),
2204

2205 2206 2207 2208 2209
      // 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 已提交
2210
      ty_rptr(_, _) => kind_safe_for_default_mode(),
2211

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

2216
      // Implicit copyability of vecs is configurable
B
Brian Anderson 已提交
2217
      ty_evec(tm, vstore_uniq) => {
2218
          if cx.vecs_implicitly_copyable {
2219
              mutable_type_kind(cx, tm)
2220 2221 2222
          } else {
              remove_implicit(mutable_type_kind(cx, tm))
          }
2223
      }
2224

2225 2226 2227
      // 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 已提交
2228
      ty_evec(tm, vstore_box) => {
B
Brian Anderson 已提交
2229
        remove_owned(kind_safe_for_default_mode() | mutable_type_kind(cx, tm))
2230
      }
2231 2232 2233
      ty_evec(tm, vstore_slice(re_static)) => {
        kind_safe_for_default_mode() | mutable_type_kind(cx, tm)
      }
B
Brian Anderson 已提交
2234
      ty_evec(tm, vstore_slice(_)) => {
B
Brian Anderson 已提交
2235
        remove_durable_owned(kind_safe_for_default_mode() |
B
Brian Anderson 已提交
2236
                           mutable_type_kind(cx, tm))
2237
      }
B
Brian Anderson 已提交
2238
      ty_evec(tm, vstore_fixed(_)) => {
2239
        mutable_type_kind(cx, tm)
2240
      }
2241 2242

      // All estrs are copyable; uniques and interiors are sendable.
B
Brian Anderson 已提交
2243
      ty_estr(vstore_box) => {
B
Brian Anderson 已提交
2244
        kind_safe_for_default_mode() | kind_const() | kind_durable()
2245
      }
2246
      ty_estr(vstore_slice(re_static)) => {
B
Brian Anderson 已提交
2247
        kind_safe_for_default_mode() | kind_owned_copy() | kind_const()
2248
      }
B
Brian Anderson 已提交
2249
      ty_estr(vstore_slice(_)) => {
2250
        kind_safe_for_default_mode() | kind_const()
2251
      }
B
Brian Anderson 已提交
2252
      ty_estr(vstore_fixed(_)) => {
B
Brian Anderson 已提交
2253
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2254
      }
2255

2256
      // Records lower to the lowest of their members.
B
Brian Anderson 已提交
2257
      ty_rec(flds) => {
2258
        let mut lowest = kind_top();
B
Brian Anderson 已提交
2259
        for flds.each |f| {
2260
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
2261
        }
M
Marijn Haverbeke 已提交
2262
        lowest
2263
      }
2264

2265 2266
      ty_struct(did, ref substs) => {
        // Structs are sendable if all their fields are sendable,
2267
        // likewise for copyable...
2268 2269
        // also factor out this code, copied from the records case
        let mut lowest = kind_top();
2270
        let flds = struct_fields(cx, did, substs);
B
Brian Anderson 已提交
2271
        for flds.each |f| {
2272 2273
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
        }
2274
        // ...but structs with dtors are never copyable (they can be
2275 2276
        // sendable)
        if ty::has_dtor(cx, did) {
2277
           lowest = remove_copyable(lowest);
2278
        }
2279
        lowest
2280
      }
2281

2282
      // Tuples lower to the lowest of their members.
B
Brian Anderson 已提交
2283
      ty_tup(tys) => {
2284
        let mut lowest = kind_top();
2285
        for tys.each |ty| { lowest = lower_kind(lowest, type_kind(cx, *ty)); }
M
Marijn Haverbeke 已提交
2286
        lowest
2287
      }
2288

2289
      // Enums lower to the lowest of their variants.
N
Niko Matsakis 已提交
2290
      ty_enum(did, ref substs) => {
2291
        let mut lowest = kind_top();
2292
        let variants = enum_variants(cx, did);
2293
        if variants.is_empty() {
B
Brian Anderson 已提交
2294
            lowest = kind_owned_only() | kind_durable();
2295
        } else {
2296
            for variants.each |variant| {
B
Brian Anderson 已提交
2297
                for variant.args.each |aty| {
2298
                    // Perform any type parameter substitutions.
2299
                    let arg_ty = subst(cx, substs, *aty);
2300
                    lowest = lower_kind(lowest, type_kind(cx, arg_ty));
2301
                    if lowest == kind_noncopyable() { break; }
2302
                }
2303 2304
            }
        }
M
Marijn Haverbeke 已提交
2305
        lowest
2306
      }
2307

B
Brian Anderson 已提交
2308
      ty_param(p) => {
2309
        param_bounds_to_kind(cx.ty_param_bounds.get(p.def_id.node))
2310
      }
2311

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

2316
      ty_infer(_) => {
2317 2318 2319 2320 2321
        if allow_ty_var {
            kind_top()
        } else {
            cx.sess.bug(~"Asked to compute kind of a type variable")
        }
2322
      }
2323

B
Brian Anderson 已提交
2324
      ty_type | ty_opaque_closure_ptr(_)
2325
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2326
        cx.sess.bug(~"Asked to compute kind of fictitious type");
2327
      }
M
Marijn Haverbeke 已提交
2328
    };
2329

2330 2331 2332
    // arbitrary threshold to prevent by-value copying of big records
    if kind_is_safe_for_default_mode(result) {
        if type_size(cx, ty) > 4 {
2333
            result = result - kind_(KIND_MASK_DEFAULT_MODE);
2334 2335 2336
        }
    }

2337
    cx.kind_cache.insert(ty, result);
B
Brian Anderson 已提交
2338
    return result;
2339 2340
}

2341 2342 2343 2344 2345
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))
}

2346 2347 2348
/// 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 {
2349
    match /*bad*/copy get(ty).sty {
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371
      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 已提交
2372
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2373 2374
      }

2375 2376
      ty_struct(did, ref substs) => {
        let flds = struct_fields(cx, did, substs);
T
Tim Chevalier 已提交
2377
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2378 2379
      }

B
Brian Anderson 已提交
2380
      ty_tup(tys) => {
T
Tim Chevalier 已提交
2381
        tys.foldl(0, |s, t| *s + type_size(cx, *t))
2382 2383
      }

N
Niko Matsakis 已提交
2384
      ty_enum(did, ref substs) => {
2385 2386 2387
        let variants = substd_enum_variants(cx, did, substs);
        variants.foldl( // find max size of any variant
            0,
T
Tim Chevalier 已提交
2388
            |m, v| uint::max(*m,
2389
                             // find size of this variant:
T
Tim Chevalier 已提交
2390
                             v.args.foldl(0, |s, a| *s + type_size(cx, *a))))
2391 2392
      }

B
Brian Anderson 已提交
2393
      ty_param(_) | ty_self => {
2394 2395 2396
        1
      }

2397
      ty_infer(_) => {
2398 2399
        cx.sess.bug(~"Asked to compute kind of a type variable");
      }
B
Brian Anderson 已提交
2400
      ty_type | ty_opaque_closure_ptr(_)
2401
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2402 2403 2404 2405 2406
        cx.sess.bug(~"Asked to compute kind of fictitious type");
      }
    }
}

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

2410
    fn type_requires(cx: ctxt, seen: @mut ~[def_id],
2411
                     r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2412
        debug!("type_requires(%s, %s)?",
2413 2414
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2415 2416

        let r = {
2417
            get(r_ty).sty == get(ty).sty ||
2418 2419 2420
                subtypes_require(cx, seen, r_ty, ty)
        };

P
Paul Stansifer 已提交
2421
        debug!("type_requires(%s, %s)? %b",
2422 2423
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2424
               r);
B
Brian Anderson 已提交
2425
        return r;
2426 2427
    }

2428
    fn subtypes_require(cx: ctxt, seen: @mut ~[def_id],
2429
                        r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2430
        debug!("subtypes_require(%s, %s)?",
2431 2432
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty));
2433

2434
        let r = match /*bad*/copy get(ty).sty {
2435 2436 2437 2438 2439 2440
          ty_nil |
          ty_bot |
          ty_bool |
          ty_int(_) |
          ty_uint(_) |
          ty_float(_) |
2441
          ty_estr(_) |
2442
          ty_fn(_) |
2443
          ty_infer(_) |
2444
          ty_err |
2445
          ty_param(_) |
2446
          ty_self |
2447 2448 2449
          ty_type |
          ty_opaque_box |
          ty_opaque_closure_ptr(_) |
2450
          ty_evec(_, _) |
B
Brian Anderson 已提交
2451
          ty_unboxed_vec(_) => {
2452 2453 2454 2455
            false
          }
          ty_box(mt) |
          ty_uniq(mt) |
B
Brian Anderson 已提交
2456
          ty_rptr(_, mt) => {
B
Brian Anderson 已提交
2457
            return type_requires(cx, seen, r_ty, mt.ty);
2458 2459
          }

2460
          ty_ptr(*) => {
2461 2462 2463
            false           // unsafe ptrs can always be NULL
          }

B
Brian Anderson 已提交
2464
          ty_rec(fields) => {
B
Brian Anderson 已提交
2465
            do vec::any(fields) |field| {
2466 2467 2468 2469
                type_requires(cx, seen, r_ty, field.mt.ty)
            }
          }

2470
          ty_trait(_, _, _) => {
2471 2472 2473
            false
          }

2474
          ty_struct(ref did, _) if vec::contains(*seen, did) => {
2475 2476 2477
            false
          }

2478
          ty_struct(did, ref substs) => {
2479
              seen.push(did);
2480
              let r = vec::any(struct_fields(cx, did, substs),
2481
                               |f| type_requires(cx, seen, r_ty, f.mt.ty));
N
Niko Matsakis 已提交
2482
              seen.pop();
2483 2484 2485
            r
          }

B
Brian Anderson 已提交
2486
          ty_tup(ts) => {
N
Niko Matsakis 已提交
2487
            vec::any(ts, |t| type_requires(cx, seen, r_ty, *t))
2488 2489
          }

N
Niko Matsakis 已提交
2490
          ty_enum(ref did, _) if vec::contains(*seen, did) => {
2491 2492 2493
            false
          }

2494 2495 2496 2497 2498
            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 已提交
2499
                        let sty = subst(cx, substs, *aty);
2500 2501 2502
                        type_requires(cx, seen, r_ty, sty)
                    })
                });
N
Niko Matsakis 已提交
2503
                seen.pop();
2504 2505
                r
            }
2506 2507
        };

P
Paul Stansifer 已提交
2508
        debug!("subtypes_require(%s, %s)? %b",
2509 2510
               ::util::ppaux::ty_to_str(cx, r_ty),
               ::util::ppaux::ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2511
               r);
2512

B
Brian Anderson 已提交
2513
        return r;
2514 2515
    }

2516
    let seen = @mut ~[];
2517 2518 2519
    !subtypes_require(cx, seen, r_ty, r_ty)
}

N
Niko Matsakis 已提交
2520
fn type_structurally_contains(cx: ctxt, ty: t, test: fn(x: &sty) -> bool) ->
B
Brian Anderson 已提交
2521
   bool {
2522
    let sty = &get(ty).sty;
2523 2524
    debug!("type_structurally_contains: %s",
           ::util::ppaux::ty_to_str(cx, ty));
B
Brian Anderson 已提交
2525
    if test(sty) { return true; }
2526
    match /*bad*/copy *sty {
N
Niko Matsakis 已提交
2527
      ty_enum(did, ref substs) => {
2528
        for vec::each(*enum_variants(cx, did)) |variant| {
B
Brian Anderson 已提交
2529
            for variant.args.each |aty| {
2530
                let sty = subst(cx, substs, *aty);
B
Brian Anderson 已提交
2531
                if type_structurally_contains(cx, sty, test) { return true; }
2532
            }
2533
        }
B
Brian Anderson 已提交
2534
        return false;
M
Marijn Haverbeke 已提交
2535
      }
B
Brian Anderson 已提交
2536
      ty_rec(fields) => {
B
Brian Anderson 已提交
2537
        for fields.each |field| {
B
Brian Anderson 已提交
2538 2539 2540
            if type_structurally_contains(cx, field.mt.ty, test) {
                return true;
            }
2541
        }
B
Brian Anderson 已提交
2542
        return false;
M
Marijn Haverbeke 已提交
2543
      }
2544 2545
      ty_struct(did, ref substs) => {
        for lookup_struct_fields(cx, did).each |field| {
2546
            let ft = lookup_field_type(cx, did, field.id, substs);
B
Brian Anderson 已提交
2547
            if type_structurally_contains(cx, ft, test) { return true; }
2548
        }
B
Brian Anderson 已提交
2549
        return false;
2550 2551
      }

B
Brian Anderson 已提交
2552
      ty_tup(ts) => {
B
Brian Anderson 已提交
2553
        for ts.each |tt| {
2554
            if type_structurally_contains(cx, *tt, test) { return true; }
2555
        }
B
Brian Anderson 已提交
2556
        return false;
2557
      }
B
Brian Anderson 已提交
2558
      ty_evec(mt, vstore_fixed(_)) => {
B
Brian Anderson 已提交
2559
        return type_structurally_contains(cx, mt.ty, test);
2560
      }
B
Brian Anderson 已提交
2561
      _ => return false
M
Marijn Haverbeke 已提交
2562 2563 2564
    }
}

2565
fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
2566
    return type_structurally_contains(cx, ty, |sty| {
N
Niko Matsakis 已提交
2567
        match *sty {
2568 2569
          ty_uniq(_) |
          ty_evec(_, vstore_uniq) |
B
Brian Anderson 已提交
2570 2571
          ty_estr(vstore_uniq) => true,
          _ => false,
2572
        }
2573
    });
2574 2575
}

2576
fn type_is_integral(ty: t) -> bool {
2577
    match get(ty).sty {
2578
      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) | ty_bool => true,
B
Brian Anderson 已提交
2579
      _ => false
M
Marijn Haverbeke 已提交
2580 2581 2582
    }
}

2583 2584 2585 2586 2587 2588 2589
fn type_is_char(ty: t) -> bool {
    match get(ty).sty {
        ty_int(ty_char) => true,
        _ => false
    }
}

2590
fn type_is_fp(ty: t) -> bool {
2591
    match get(ty).sty {
2592
      ty_infer(FloatVar(_)) | ty_float(_) => true,
B
Brian Anderson 已提交
2593
      _ => false
M
Marijn Haverbeke 已提交
2594 2595 2596
    }
}

2597
fn type_is_numeric(ty: t) -> bool {
B
Brian Anderson 已提交
2598
    return type_is_integral(ty) || type_is_fp(ty);
2599 2600
}

2601
fn type_is_signed(ty: t) -> bool {
2602
    match get(ty).sty {
B
Brian Anderson 已提交
2603 2604
      ty_int(_) => true,
      _ => false
M
Marijn Haverbeke 已提交
2605 2606 2607
    }
}

2608 2609
// Whether a type is Plain Old Data -- meaning it does not contain pointers
// that the cycle collector might care about.
2610
fn type_is_pod(cx: ctxt, ty: t) -> bool {
2611
    let mut result = true;
2612
    match /*bad*/copy get(ty).sty {
B
Brian Anderson 已提交
2613
      // Scalar types
2614
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
B
Brian Anderson 已提交
2615
      ty_type | ty_ptr(_) => result = true,
B
Brian Anderson 已提交
2616
      // Boxed types
M
Michael Sullivan 已提交
2617
      ty_box(_) | ty_uniq(_) | ty_fn(_) |
2618 2619
      ty_estr(vstore_uniq) | ty_estr(vstore_box) |
      ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2620
      ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
B
Brian Anderson 已提交
2621
      // Structural types
N
Niko Matsakis 已提交
2622
      ty_enum(did, ref substs) => {
2623
        let variants = enum_variants(cx, did);
2624
        for vec::each(*variants) |variant| {
2625
            let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
B
Brian Anderson 已提交
2626 2627

            // Perform any type parameter substitutions.
2628
            let tup_ty = subst(cx, substs, tup_ty);
B
Brian Anderson 已提交
2629
            if !type_is_pod(cx, tup_ty) { result = false; }
2630
        }
B
Brian Anderson 已提交
2631
      }
B
Brian Anderson 已提交
2632
      ty_rec(flds) => {
B
Brian Anderson 已提交
2633
        for flds.each |f| {
B
Brian Anderson 已提交
2634
            if !type_is_pod(cx, f.mt.ty) { result = false; }
P
Patrick Walton 已提交
2635
        }
B
Brian Anderson 已提交
2636
      }
B
Brian Anderson 已提交
2637
      ty_tup(elts) => {
2638
        for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
B
Brian Anderson 已提交
2639
      }
B
Brian Anderson 已提交
2640 2641
      ty_estr(vstore_fixed(_)) => result = true,
      ty_evec(mt, vstore_fixed(_)) | ty_unboxed_vec(mt) => {
2642 2643
        result = type_is_pod(cx, mt.ty);
      }
B
Brian Anderson 已提交
2644 2645
      ty_param(_) => result = false,
      ty_opaque_closure_ptr(_) => result = true,
2646 2647
      ty_struct(did, ref substs) => {
        result = vec::any(lookup_struct_fields(cx, did), |f| {
2648 2649 2650
            let fty = ty::lookup_item_type(cx, f.id);
            let sty = subst(cx, substs, fty.ty);
            type_is_pod(cx, sty)
2651
        });
2652
      }
2653

B
Brian Anderson 已提交
2654
      ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2655 2656 2657
        result = false;
      }

2658
      ty_infer(*) | ty_self(*) | ty_err => {
2659
        cx.sess.bug(~"non concrete type in type_is_pod");
2660
      }
P
Patrick Walton 已提交
2661 2662
    }

B
Brian Anderson 已提交
2663
    return result;
P
Patrick Walton 已提交
2664 2665
}

2666
fn type_is_enum(ty: t) -> bool {
2667
    match get(ty).sty {
B
Brian Anderson 已提交
2668 2669
      ty_enum(_, _) => return true,
      _ => return false
2670 2671 2672
    }
}

P
Patrick Walton 已提交
2673
// Whether a type is enum like, that is a enum type with only nullary
2674
// constructors
2675
fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2676
    match get(ty).sty {
2677
      ty_enum(did, _) => {
2678
        let variants = enum_variants(cx, did);
B
Brian Anderson 已提交
2679
        let some_n_ary = vec::any(*variants, |v| vec::len(v.args) > 0u);
B
Brian Anderson 已提交
2680
        return !some_n_ary;
2681
      }
B
Brian Anderson 已提交
2682
      _ => return false
2683 2684 2685
    }
}

B
Brian Anderson 已提交
2686
fn type_param(ty: t) -> Option<uint> {
2687
    match get(ty).sty {
B
Brian Anderson 已提交
2688
      ty_param(p) => return Some(p.idx),
B
Brian Anderson 已提交
2689
      _ => {/* fall through */ }
2690
    }
B
Brian Anderson 已提交
2691
    return None;
2692 2693
}

2694 2695
// Returns the type and mutability of *t.
//
2696 2697 2698 2699
// 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)
2700
}
2701 2702

fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
N
Niko Matsakis 已提交
2703
    match *sty {
B
Brian Anderson 已提交
2704
      ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
B
Brian Anderson 已提交
2705
        Some(mt)
2706 2707
      }

2708
      ty_ptr(mt) if explicit => {
B
Brian Anderson 已提交
2709
        Some(mt)
2710 2711
      }

N
Niko Matsakis 已提交
2712
      ty_enum(did, ref substs) => {
2713 2714 2715
        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]);
2716
            Some(mt {ty: v_t, mutbl: ast::m_imm})
2717
        } else {
B
Brian Anderson 已提交
2718
            None
2719 2720 2721
        }
      }

2722 2723
      ty_struct(did, ref substs) => {
        let fields = struct_fields(cx, did, substs);
2724 2725
        if fields.len() == 1 && fields[0].ident ==
                syntax::parse::token::special_idents::unnamed_field {
2726
            Some(mt {ty: fields[0].mt.ty, mutbl: ast::m_imm})
2727 2728 2729 2730 2731
        } else {
            None
        }
      }

B
Brian Anderson 已提交
2732
      _ => None
2733 2734 2735
    }
}

2736
fn type_autoderef(cx: ctxt, t: t) -> t {
2737
    let mut t = t;
2738
    loop {
2739
        match deref(cx, t, false) {
B
Brian Anderson 已提交
2740 2741
          None => return t,
          Some(mt) => t = mt.ty
2742 2743
        }
    }
2744 2745 2746
}

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

B
Brian Anderson 已提交
2751
fn index_sty(cx: ctxt, sty: &sty) -> Option<mt> {
N
Niko Matsakis 已提交
2752
    match *sty {
B
Brian Anderson 已提交
2753
      ty_evec(mt, _) => Some(mt),
2754
      ty_estr(_) => Some(mt {ty: mk_u8(cx), mutbl: ast::m_imm}),
B
Brian Anderson 已提交
2755
      _ => None
2756
    }
2757 2758
}

2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770
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) =>
2771 2772 2773 2774
          to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f),

          ty::br_fresh(ref x) =>
          to_bytes::iter_bytes_2(&4u8, x, lsb0, f)
2775 2776 2777
        }
    }
}
2778

2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792
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),
2793

2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812
          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),
        }
    }
}
2813

2814 2815 2816 2817 2818 2819 2820
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)
    }
}
2821

2822 2823 2824 2825 2826 2827
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)
    }
}
2828

2829 2830 2831 2832 2833 2834
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)
    }
}
2835

2836 2837 2838 2839 2840 2841
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)
    }
}
2842

2843 2844
impl FnMeta : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
2845
        to_bytes::iter_bytes_5(&self.purity,
2846
                               &self.proto,
2847
                               &self.onceness,
2848 2849 2850 2851 2852
                               &self.region,
                               &self.bounds,
                               lsb0, f);
    }
}
2853

2854 2855 2856 2857 2858 2859 2860
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);
    }
}
2861

2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887
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),
2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898

          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) =>
2899
          to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925

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

2926
          ty_struct(ref did, ref substs) =>
2927 2928 2929 2930
          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),
2931 2932

          ty_err => 25u8.iter_bytes(lsb0, f)
2933 2934 2935 2936
        }
    }
}

B
Brian Anderson 已提交
2937 2938
fn br_hashmap<V:Copy>() -> HashMap<bound_region, V> {
    map::HashMap()
N
Niko Matsakis 已提交
2939 2940
}

2941
fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
P
Paul Stansifer 已提交
2942
    //io::println(fmt!("%?/%?", id, cx.node_types.size()));
2943
    match smallintmap::find(*cx.node_types, id as uint) {
B
Brian Anderson 已提交
2944 2945
       Some(t) => t,
       None => cx.sess.bug(
2946
           fmt!("node_id_to_type: no type for node `%s`",
P
Paul Stansifer 已提交
2947
                ast_map::node_id_to_str(cx.items, id,
P
Paul Stansifer 已提交
2948
                                        cx.sess.parse_sess.interner)))
T
Tim Chevalier 已提交
2949
    }
2950 2951
}

2952
fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2953
    match cx.node_type_substs.find(id) {
B
Brian Anderson 已提交
2954 2955
      None => return ~[],
      Some(ts) => return ts
2956 2957 2958
    }
}

2959
fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
B
Brian Anderson 已提交
2960
    return cx.node_type_substs.contains_key(id);
2961 2962
}

2963
// Type accessors for substructures of types
2964
fn ty_fn_args(fty: t) -> ~[arg] {
2965
    match get(fty).sty {
2966
      ty_fn(ref f) => /*bad*/copy f.sig.inputs,
B
Brian Anderson 已提交
2967
      _ => fail ~"ty_fn_args() called on non-fn type"
2968 2969 2970
    }
}

2971
fn ty_fn_proto(fty: t) -> Proto {
2972
    match get(fty).sty {
2973
      ty_fn(ref f) => f.meta.proto,
B
Brian Anderson 已提交
2974
      _ => fail ~"ty_fn_proto() called on non-fn type"
M
Marijn Haverbeke 已提交
2975
    }
G
Graydon Hoare 已提交
2976 2977
}

2978
fn ty_fn_purity(fty: t) -> ast::purity {
2979
    match get(fty).sty {
2980
      ty_fn(ref f) => f.meta.purity,
2981 2982 2983 2984
      _ => fail ~"ty_fn_purity() called on non-fn type"
    }
}

2985
pure fn ty_fn_ret(fty: t) -> t {
2986
    match get(fty).sty {
2987 2988
        ty_fn(ref f) => f.sig.output,
        _ => fail ~"ty_fn_ret() called on non-fn type"
2989
    }
G
Graydon Hoare 已提交
2990 2991
}

2992
fn is_fn_ty(fty: t) -> bool {
2993
    match get(fty).sty {
2994 2995 2996 2997 2998
      ty_fn(_) => true,
      _ => false
    }
}

2999
fn ty_region(ty: t) -> Region {
3000
    match get(ty).sty {
3001
      ty_rptr(r, _) => r,
3002
      ref s => fail fmt!("ty_region() invoked on non-rptr: %?", (*s))
3003
    }
G
Graydon Hoare 已提交
3004 3005
}

3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
fn replace_fn_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
    /*!
     *
     * Returns a new function type based on `fn_type` but returning a value of
     * type `ret_type` instead. */

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

3027
// Returns a vec of all the input and output types of fty.
3028 3029
fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
    vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
3030 3031
}

3032 3033
// Just checks whether it's a fn that returns bool,
// not its purity.
3034 3035
fn is_pred_ty(fty: t) -> bool {
    is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
3036 3037
}

3038
// Type accessors for AST nodes
N
Niko Matsakis 已提交
3039
fn block_ty(cx: ctxt, b: &ast::blk) -> t {
B
Brian Anderson 已提交
3040
    return node_id_to_type(cx, b.node.id);
3041
}
3042 3043


3044 3045
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
3046
fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
B
Brian Anderson 已提交
3047
    return node_id_to_type(cx, pat.id);
3048 3049
}

3050

3051 3052 3053 3054
// 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"
3055
// instead of "fn(t) -> T with T = int". If this isn't what you want, see
3056
// expr_ty_params_and_ty() below.
3057
fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
B
Brian Anderson 已提交
3058
    return node_id_to_type(cx, expr.id);
3059 3060
}

3061
fn expr_ty_params_and_ty(cx: ctxt,
3062
                         expr: @ast::expr) -> {params: ~[t], ty: t} {
B
Brian Anderson 已提交
3063
    return {params: node_id_to_type_params(cx, expr.id),
M
Marijn Haverbeke 已提交
3064
         ty: node_id_to_type(cx, expr.id)};
3065 3066
}

3067
fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
B
Brian Anderson 已提交
3068
    return node_id_has_type_params(cx, expr.id);
3069 3070
}

3071 3072
fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
                      id: ast::node_id)
B
Brian Anderson 已提交
3073
    -> Option<@~[param_bounds]> {
3074 3075 3076
    do method_map.find(id).map |method| {
        match method.origin {
          typeck::method_static(did) => {
3077 3078
            // n.b.: When we encode impl methods, the bounds
            // that we encode include both the impl bounds
3079 3080 3081 3082 3083
            // and then the method bounds themselves...
            ty::lookup_item_type(tcx, did).bounds
          }
          typeck::method_param({trait_id:trt_id,
                                method_num:n_mth, _}) |
3084 3085
          typeck::method_trait(trt_id, n_mth, _) |
          typeck::method_self(trt_id, n_mth) => {
3086 3087 3088 3089 3090
            // ...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;
3091 3092
            let mth = /*bad*/copy ty::trait_methods(tcx, trt_id)[n_mth];
            @(vec::append(/*bad*/copy *trt_bounds, *mth.tps))
3093 3094 3095 3096 3097
          }
        }
    }
}

3098 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
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(*) |
3146
                ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172

                // 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(*) |
3173
        ast::expr_method_call(*) |
3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186
        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(*) |
3187
        ast::expr_lit(@ast::spanned {node: lit_str(_), _}) |
3188
        ast::expr_vstore(_, ast::expr_vstore_slice) |
3189
        ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3190
        ast::expr_vstore(_, ast::expr_vstore_fixed(_)) |
3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238
        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(*) |
3239
        ast::expr_vstore(_, ast::expr_vstore_box) |
3240
        ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3241
        ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3242 3243 3244
            RvalueDatumExpr
        }

3245 3246
        ast::expr_paren(e) => expr_kind(tcx, method_map, e),

3247 3248 3249 3250 3251
        ast::expr_mac(*) => {
            tcx.sess.span_bug(
                expr.span,
                ~"macro expression remains after expansion");
        }
M
Marijn Haverbeke 已提交
3252 3253 3254
    }
}

3255
fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3256
    match s.node {
B
Brian Anderson 已提交
3257
      ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
B
Brian Anderson 已提交
3258
        return id;
3259
      }
3260
      ast::stmt_mac(*) => fail ~"unexpanded macro in trans"
3261 3262 3263
    }
}

3264
fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3265
    let mut i = 0u;
B
Brian Anderson 已提交
3266 3267
    for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
    return None;
3268 3269
}

3270 3271 3272 3273 3274 3275 3276 3277 3278
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))));
}

3279 3280
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 已提交
3281
      Some(f) => f,
3282
      // Do we only call this when we know the field is legit?
3283
      None => fail (fmt!("get_field: ty doesn't have a field %s",
3284
                         tcx.sess.str_of(id)))
T
Tim Chevalier 已提交
3285 3286 3287
    }
}

3288
fn get_fields(rec_ty:t) -> ~[field] {
3289
    match /*bad*/copy get(rec_ty).sty {
3290 3291 3292
      ty_rec(fields) => fields,
      // Can we check at the caller?
      _ => fail ~"get_fields: not a record type"
3293 3294 3295
    }
}

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

3302 3303 3304 3305 3306 3307
/// 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| {
3308
        match get(ty).sty {
B
Brian Anderson 已提交
3309
          ty_param(p) => {
3310
            rslt.push(p);
3311
          }
B
Brian Anderson 已提交
3312
          _ => ()
3313 3314 3315 3316 3317
        }
    }
    rslt
}

3318
fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3319 3320 3321

    // Returns a vec of all the type variables occurring in `ty`. It may
    // contain duplicates.  (Integral type vars aren't counted.)
3322
    fn vars_in_type(ty: t) -> ~[TyVid] {
3323
        let mut rslt = ~[];
B
Brian Anderson 已提交
3324
        do walk_ty(ty) |ty| {
3325
            match get(ty).sty {
3326
              ty_infer(TyVar(v)) => rslt.push(v),
B
Brian Anderson 已提交
3327 3328
              _ => ()
            }
3329 3330 3331 3332
        }
        rslt
    }

3333
    // Fast path
B
Brian Anderson 已提交
3334
    if !type_needs_infer(rt) { return; }
B
Brian Anderson 已提交
3335

T
Tim Chevalier 已提交
3336
    // Occurs check!
N
Niko Matsakis 已提交
3337
    if vec::contains(vars_in_type(rt), &vid) {
T
Tim Chevalier 已提交
3338 3339 3340
            // 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.
3341
            tcx.sess.span_fatal
3342
                (sp, ~"type inference failed because I \
3343
                     could not find a type\n that's both of the form "
3344 3345
                 + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
                 ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
3346
                 ~" - such a type would have to be infinitely large.");
3347
    }
T
Tim Chevalier 已提交
3348
}
3349

3350 3351
// Maintains a little union-set tree for inferred modes.  `canon()` returns
// the current head value for `m0`.
B
Brian Anderson 已提交
3352
fn canon<T:Copy cmp::Eq>(tbl: HashMap<ast::node_id, ast::inferable<T>>,
3353
                         +m0: ast::inferable<T>) -> ast::inferable<T> {
3354 3355
    match m0 {
      ast::infer(id) => match tbl.find(id) {
B
Brian Anderson 已提交
3356
        None => m0,
3357 3358
        Some(ref m1) => {
            let cm1 = canon(tbl, (*m1));
3359
            // path compression:
3360
            if cm1 != (*m1) { tbl.insert(id, cm1); }
3361 3362
            cm1
        }
3363
      },
B
Brian Anderson 已提交
3364
      _ => m0
3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376
    }
}

// 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 {
3377
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3378
      ast::infer(_) => {
P
Paul Stansifer 已提交
3379
        cx.sess.bug(fmt!("mode %? was never resolved", m));
3380
      }
B
Brian Anderson 已提交
3381
      ast::expl(m0) => m0
3382 3383 3384
    }
}

3385
fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { resolved_mode(cx, a.mode) }
3386 3387

// Unifies `m1` and `m2`.  Returns unified value or failure code.
3388
fn unify_mode(cx: ctxt, modes: expected_found<ast::mode>)
3389
    -> Result<ast::mode, type_err> {
3390 3391 3392

    let m1 = modes.expected;
    let m2 = modes.found;
3393
    match (canon_mode(cx, m1), canon_mode(cx, m2)) {
B
Brian Anderson 已提交
3394
      (m1, m2) if (m1 == m2) => {
3395
        result::Ok(m1)
3396
      }
E
Erick Tryzelaar 已提交
3397
      (ast::infer(_), ast::infer(id2)) => {
3398
        cx.inferred_modes.insert(id2, m1);
3399
        result::Ok(m1)
3400
      }
B
Brian Anderson 已提交
3401
      (ast::infer(id), m) | (m, ast::infer(id)) => {
3402
        cx.inferred_modes.insert(id, m);
3403
        result::Ok(m1)
3404
      }
E
Erick Tryzelaar 已提交
3405
      (_, _) => {
3406
        result::Err(terr_mode_mismatch(modes))
3407 3408 3409 3410 3411 3412 3413
      }
    }
}

// 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) {
3414
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3415
      ast::infer(id) => {
3416 3417
        cx.inferred_modes.insert(id, ast::expl(m_def));
      }
B
Brian Anderson 已提交
3418
      ast::expl(_) => ()
3419 3420 3421
    }
}

3422
fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3423
    match get(t).sty {
N
Niko Matsakis 已提交
3424
      ty_nil | ty_bot | ty_bool | ty_int(_) |
M
Michael Sullivan 已提交
3425
      ty_uint(_) | ty_float(_) | ty_estr(_) |
B
Brian Anderson 已提交
3426
      ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
3427
        ::util::ppaux::ty_to_str(cx, t)
N
Niko Matsakis 已提交
3428 3429
      }

P
Paul Stansifer 已提交
3430
      ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3431 3432 3433 3434 3435 3436 3437 3438
      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 已提交
3439
      ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3440
      ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3441
      ty_tup(_) => ~"tuple",
3442 3443
      ty_infer(TyVar(_)) => ~"inferred type",
      ty_infer(IntVar(_)) => ~"integral variable",
3444
      ty_infer(FloatVar(_)) => ~"floating-point variable",
B
Brian Anderson 已提交
3445
      ty_param(_) => ~"type parameter",
3446 3447
      ty_self => ~"self",
      ty_err => ~"type error"
N
Niko Matsakis 已提交
3448 3449 3450
    }
}

N
Niko Matsakis 已提交
3451
fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3452 3453 3454 3455 3456 3457 3458 3459 3460
    /*!
     *
     * 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. */

3461
    fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3462 3463 3464
        match k {
            terr_vec => ~"[]",
            terr_str => ~"str",
3465 3466
            terr_fn => ~"fn",
            terr_trait => ~"trait"
3467
        }
3468 3469
    }

N
Niko Matsakis 已提交
3470
    match *err {
3471 3472 3473
        terr_mismatch => ~"types differ",
        terr_purity_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3474
                 values.expected.to_str(), values.found.to_str())
3475
        }
3476 3477
        terr_onceness_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
3478
                 values.expected.to_str(), values.found.to_str())
3479
        }
3480 3481
        terr_proto_mismatch(values) => {
            fmt!("expected %s closure, found %s closure",
3482 3483
                 proto_ty_to_str(cx, values.expected, false),
                 proto_ty_to_str(cx, values.found, false))
3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516
        }
        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",
3517 3518
                 pprust::mode_to_str(values.expected),
                 pprust::mode_to_str(values.found))
3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538
        }
        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))
        }
3539
        terr_vstores_differ(k, ref values) => {
3540 3541
            fmt!("%s storage differs: expected %s but found %s",
                 terr_vstore_kind_to_str(k),
3542 3543
                 vstore_to_str(cx, (*values).expected),
                 vstore_to_str(cx, (*values).found))
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559
        }
        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"
3560
        }
3561 3562 3563 3564
        terr_integer_as_char => {
            ~"integer literals can't be inferred to char type \
              (try an explicit cast)"
        }
3565 3566 3567 3568
        terr_no_floating_point_type => {
            ~"couldn't determine an appropriate floating point type for \
              floating point literal"
        }
3569 3570 3571
    }
}

3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588
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, ~"");
        }
3589 3590 3591 3592 3593 3594 3595 3596 3597 3598
        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, ~"");
        }
3599 3600 3601 3602
        _ => {}
    }
}

3603
fn def_has_ty_params(def: ast::def) -> bool {
3604
    match def {
3605
      ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
B
Brian Anderson 已提交
3606 3607
        => true,
      _ => false
3608 3609 3610
    }
}

3611 3612
fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
    cx.trait_method_cache.insert(ast_util::local_def(id), ms);
3613 3614
}

3615
fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3616 3617
    if is_local(id) {
        match cx.items.find(id.node) {
3618
            Some(ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
3619 3620 3621
                        node: item_trait(_, _, ref ms),
                        _
                    }, _)) =>
3622
                match ast_util::split_trait_methods((/*bad*/copy *ms)) {
3623
                   (_, p) => p.map(|method| method.ident)
3624
                },
3625
            _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3626 3627
                                  id))
        }
3628
    } else {
3629
        csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3630 3631 3632
    }
}

3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648
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 {
3649
            ty_trait(def_id, ref substs, _) => {
3650 3651
                result.push(InstantiatedTraitRef {
                    def_id: def_id,
3652
                    tpt: { substs: (/*bad*/copy *substs), ty: *trait_type }
3653 3654 3655 3656 3657 3658 3659 3660 3661
                });
            }
            _ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
        }
    }

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

3663
fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
3664
    match cx.trait_method_cache.find(id) {
3665
      // Local traits are supposed to have been added explicitly.
B
Brian Anderson 已提交
3666
      Some(ms) => ms,
3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678
      _ => {
        // 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
      }
3679 3680
    }
}
3681

3682 3683 3684
/*
  Could this return a list of (def_id, substs) pairs?
 */
3685 3686 3687 3688
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 已提交
3689
            ty::ty_trait(did, ref substs, _) => {
3690
                mk_trait(cx, did, (/*bad*/copy *substs), vstore)
P
Patrick Walton 已提交
3691
            }
3692 3693 3694 3695
            _ => cx.sess.bug(~"impl_traits: not a trait")
        }
    }

3696
    if id.crate == ast::local_crate {
P
Paul Stansifer 已提交
3697
        debug!("(impl_traits) searching for trait impl %?", id);
3698
        match cx.items.find(id.node) {
3699
           Some(ast_map::node_item(@ast::item {
3700
                        node: ast::item_impl(_, opt_trait, _, _),
3701
                        _},
B
Brian Anderson 已提交
3702
                    _)) => {
3703

B
Brian Anderson 已提交
3704
               do option::map_default(&opt_trait, ~[]) |trait_ref| {
3705 3706 3707
                       ~[vstoreify(cx,
                                   node_id_to_type(cx, trait_ref.ref_id),
                                   vstore)]
3708
                   }
3709
           }
B
Brian Anderson 已提交
3710
           _ => ~[]
3711
        }
3712
    } else {
3713 3714
        vec::map(csearch::get_impl_traits(cx, id),
                 |x| vstoreify(cx, *x, vstore))
3715 3716 3717
    }
}

B
Brian Anderson 已提交
3718
fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3719
    match get(ty).sty {
3720
      ty_trait(id, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
B
Brian Anderson 已提交
3721
      _ => None
3722 3723 3724
    }
}

3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736
/// 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 {
3737
                ast::item_struct(struct_def, _) => {
3738 3739 3740 3741 3742 3743 3744 3745 3746 3747
                    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")
    }
}

3748
// Enum information
3749 3750 3751 3752 3753 3754 3755 3756 3757 3758
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 已提交
3759

3760 3761
fn substd_enum_variants(cx: ctxt,
                        id: ast::def_id,
3762
                        substs: &substs) -> ~[VariantInfo] {
B
Brian Anderson 已提交
3763 3764
    do vec::map(*enum_variants(cx, id)) |variant_info| {
        let substd_args = vec::map(variant_info.args,
3765
                                   |aty| subst(cx, substs, *aty));
3766

3767
        let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3768

3769
        @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
3770
                      ../*bad*/copy **variant_info}
3771 3772 3773
    }
}

3774
fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
P
Paul Stansifer 已提交
3775
    ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3776 3777
}

3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795
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()
    }
}

3796
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
3797
   Otherwise return none. */
3798 3799
fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
    match cx.destructor_for_type.find(struct_id) {
3800
        Some(method_def_id) => return TraitDtor(method_def_id),
3801 3802 3803
        None => {}  // Continue.
    }

3804 3805
    if is_local(struct_id) {
       match cx.items.find(struct_id.node) {
3806
           Some(ast_map::node_item(@ast::item {
3807 3808 3809
               node: ast::item_struct(@ast::struct_def { dtor: Some(ref dtor),
                                                         _ },
                                      _),
3810 3811
               _
           }, _)) =>
3812
               LegacyDtor(local_def((*dtor).node.id)),
3813
           _ =>
3814
               NoDtor
3815 3816 3817
       }
    }
    else {
3818
      match csearch::struct_dtor(cx.sess.cstore, struct_id) {
3819 3820 3821
        None => NoDtor,
        Some(did) => LegacyDtor(did),
      }
3822 3823 3824
    }
}

3825 3826
fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
    ty_dtor(cx, struct_id).is_present()
3827 3828
}

3829 3830 3831 3832 3833
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);
3834
        match node {
B
Brian Anderson 已提交
3835
          ast_map::node_item(item, path) => {
3836
            let item_elt = match item.node {
B
Brian Anderson 已提交
3837
              item_mod(_) | item_foreign_mod(_) => {
3838 3839
                ast_map::path_mod(item.ident)
              }
B
Brian Anderson 已提交
3840
              _ => {
3841 3842 3843
                ast_map::path_name(item.ident)
              }
            };
3844
            vec::append_one(/*bad*/copy *path, item_elt)
3845 3846
          }

B
Brian Anderson 已提交
3847
          ast_map::node_foreign_item(nitem, _, path) => {
3848 3849
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(nitem.ident))
3850 3851
          }

B
Brian Anderson 已提交
3852
          ast_map::node_method(method, _, path) => {
3853 3854
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
3855
          }
B
Brian Anderson 已提交
3856
          ast_map::node_trait_method(trait_method, _, path) => {
3857
            let method = ast_util::trait_method_to_ty_method(*trait_method);
3858 3859
            vec::append_one(/*bad*/copy *path,
                            ast_map::path_name(method.ident))
3860
          }
3861

3862
          ast_map::node_variant(ref variant, _, path) => {
3863
            vec::append_one(vec::init(*path),
3864
                            ast_map::path_name((*variant).node.name))
3865 3866
          }

B
Brian Anderson 已提交
3867
          ast_map::node_dtor(_, _, _, path) => {
3868
            vec::append_one(/*bad*/copy *path, ast_map::path_name(
P
Paul Stansifer 已提交
3869
                syntax::parse::token::special_idents::literally_dtor))
T
Tim Chevalier 已提交
3870 3871
          }

3872
          ast_map::node_struct_ctor(_, item, path) => {
3873
            vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
3874 3875
          }

3876 3877 3878
          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 已提交
3879
            cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3880 3881 3882 3883 3884
          }
        }
    }
}

3885
fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3886
    enum_variants(cx, id).len() == 1
3887 3888
}

3889
fn type_is_empty(cx: ctxt, t: t) -> bool {
3890
    match ty::get(t).sty {
B
Brian Anderson 已提交
3891 3892
       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
       _ => false
3893 3894 3895
     }
}

3896
fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3897
    match cx.enum_var_cache.find(id) {
B
Brian Anderson 已提交
3898
      Some(variants) => return variants,
B
Brian Anderson 已提交
3899
      _ => { /* fallthrough */ }
3900
    }
3901

3902
    let result = if ast::local_crate != id.crate {
3903
        @csearch::get_enum_variants(cx, id)
3904
    } else {
3905 3906 3907 3908 3909
        /*
          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
         */
3910
        match cx.items.get(id.node) {
3911
          ast_map::node_item(@ast::item {
P
Patrick Walton 已提交
3912 3913 3914
                    node: ast::item_enum(ref enum_definition, _),
                    _
                }, _) => {
3915
            let variants = /*bad*/copy (*enum_definition).variants;
3916
            let mut disr_val = -1;
B
Brian Anderson 已提交
3917
            @vec::map(variants, |variant| {
3918
                match variant.node.kind {
3919
                    ast::tuple_variant_kind(ref args) => {
3920 3921
                        let ctor_ty = node_id_to_type(cx, variant.node.id);
                        let arg_tys = {
3922
                            if args.len() > 0u {
3923 3924 3925 3926 3927 3928
                                ty_fn_args(ctor_ty).map(|a| a.ty)
                            } else {
                                ~[]
                            }
                        };
                        match variant.node.disr_expr {
B
Brian Anderson 已提交
3929
                          Some (ex) => {
3930 3931 3932 3933 3934 3935 3936 3937
                            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
                        }
3938
                        @VariantInfo_{args: arg_tys,
3939 3940 3941
                          ctor_ty: ctor_ty,
                          name: variant.node.name,
                          id: ast_util::local_def(variant.node.id),
3942 3943
                          disr_val: disr_val,
                          vis: variant.node.vis
3944
                         }
3945
                    }
3946
                    ast::struct_variant_kind(_) => {
3947
                        fail ~"struct variant kinds unimpl in enum_variants"
3948 3949 3950 3951
                    }
                    ast::enum_variant_kind(_) => {
                        fail ~"enum variant kinds unimpl in enum_variants"
                    }
3952
                }
3953
            })
M
Marijn Haverbeke 已提交
3954
          }
B
Brian Anderson 已提交
3955
          _ => cx.sess.bug(~"tag_variants: id not bound to an enum")
3956
        }
3957
    };
3958
    cx.enum_var_cache.insert(id, result);
3959
    result
3960 3961
}

3962

P
Patrick Walton 已提交
3963
// Returns information about the enum variant with the given ID:
3964
fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id,
3965
                        variant_id: ast::def_id) -> VariantInfo {
3966
    let variants = enum_variants(cx, enum_id);
3967 3968
    let mut i = 0;
    while i < variants.len() {
B
Brian Anderson 已提交
3969
        let variant = variants[i];
3970
        if variant.id == variant_id { return variant; }
3971
        i += 1;
3972
    }
3973
    cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
3974 3975
}

3976

3977 3978
// 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.
3979
fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
3980
    match cx.tcache.find(did) {
3981
      Some(tpt) => {
3982 3983
        // The item is in this crate. The caller should have added it to the
        // type cache already
3984 3985 3986
        return tpt;
      }
      None => {
3987
        assert did.crate != ast::local_crate;
M
Marijn Haverbeke 已提交
3988 3989
        let tyt = csearch::get_type(cx, did);
        cx.tcache.insert(did, tyt);
B
Brian Anderson 已提交
3990
        return tyt;
M
Marijn Haverbeke 已提交
3991
      }
3992
    }
T
Tim Chevalier 已提交
3993 3994
}

T
Tim Chevalier 已提交
3995
// Look up a field ID, whether or not it's local
3996 3997
// 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 已提交
3998
                     substs: &substs) -> ty::t {
3999

4000
    let t = if id.crate == ast::local_crate {
T
Tim Chevalier 已提交
4001 4002 4003
        node_id_to_type(tcx, id.node)
    }
    else {
4004
        match tcx.tcache.find(id) {
B
Brian Anderson 已提交
4005 4006
           Some(tpt) => tpt.ty,
           None => {
4007
               let tpt = csearch::get_field_type(tcx, struct_id, id);
T
Tim Chevalier 已提交
4008
               tcx.tcache.insert(id, tpt);
4009
               tpt.ty
T
Tim Chevalier 已提交
4010 4011
           }
        }
4012
    };
4013
    subst(tcx, substs, t)
T
Tim Chevalier 已提交
4014 4015
}

4016 4017 4018
// 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] {
4019
  if did.crate == ast::local_crate {
4020
    match cx.items.find(did.node) {
B
Brian Anderson 已提交
4021
       Some(ast_map::node_item(i,_)) => {
4022
         match i.node {
4023
            ast::item_struct(struct_def, _) => {
4024
               struct_field_tys(/*bad*/copy struct_def.fields)
4025
            }
4026
            _ => cx.sess.bug(~"struct ID bound to non-struct")
T
Tim Chevalier 已提交
4027
         }
T
Tim Chevalier 已提交
4028
       }
4029 4030
       Some(ast_map::node_variant(ref variant, _, _)) => {
          match (*variant).node.kind {
4031
            ast::struct_variant_kind(struct_def) => {
4032
              struct_field_tys(/*bad*/copy struct_def.fields)
4033 4034 4035 4036 4037 4038 4039
            }
            _ => {
              cx.sess.bug(~"struct ID bound to enum variant that isn't \
                            struct-like")
            }
          }
       }
B
Brian Anderson 已提交
4040
       _ => {
P
Paul Stansifer 已提交
4041
           cx.sess.bug(
4042
               fmt!("struct ID not bound to an item: %s",
P
Paul Stansifer 已提交
4043
                    ast_map::node_id_to_str(cx.items, did.node,
P
Paul Stansifer 已提交
4044
                                            cx.sess.parse_sess.interner)));
4045
       }
T
Tim Chevalier 已提交
4046
    }
T
Tim Chevalier 已提交
4047
        }
4048
  else {
4049
        return csearch::get_struct_fields(cx, did);
T
Tim Chevalier 已提交
4050 4051 4052
    }
}

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

4062
pure fn is_public(f: field_ty) -> bool {
4063 4064 4065 4066 4067
    // XXX: This is wrong.
    match f.vis {
        public | inherited => true,
        private => false
    }
4068 4069
}

4070
fn struct_field_tys(fields: ~[@struct_field]) -> ~[field_ty] {
4071
    let mut rslt = ~[];
4072 4073 4074
    for fields.each |field| {
        match field.node.kind {
            named_field(ident, mutability, visibility) => {
4075 4076 4077 4078
                rslt.push({ident: ident,
                           id: ast_util::local_def(field.node.id),
                           vis: visibility,
                           mutability: mutability});
4079
            }
4080 4081 4082 4083 4084
            unnamed_field => {
                rslt.push({ident:
                    syntax::parse::token::special_idents::unnamed_field,
                           id: ast_util::local_def(field.node.id),
                           vis: ast::public,
4085
                           mutability: ast::struct_immutable});
4086
            }
T
Tim Chevalier 已提交
4087 4088 4089
       }
    }
    rslt
T
Tim Chevalier 已提交
4090 4091
}

4092 4093
// Return a list of fields corresponding to the struct's items
// (as if the struct was a record). trans uses this
4094
// Takes a list of substs with which to instantiate field types
4095 4096 4097
// 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.
4098
fn struct_mutable_fields(cx:ctxt,
N
Niko Matsakis 已提交
4099 4100
                                 did: ast::def_id,
                                 substs: &substs) -> ~[field] {
4101
    struct_item_fields(cx, did, substs, |_mt| m_mutbl)
4102 4103
}

4104
// Same as struct_mutable_fields, but doesn't change
4105
// mutability.
4106
fn struct_fields(cx:ctxt,
N
Niko Matsakis 已提交
4107 4108
                         did: ast::def_id,
                         substs: &substs) -> ~[field] {
4109 4110 4111
    struct_item_fields(cx, did, substs, |mt| match mt {
      struct_mutable => m_mutbl,
        struct_immutable => m_imm })
4112 4113 4114
}


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

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

    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 {
4151
        match op {
B
Brian Anderson 已提交
4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169
          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 已提交
4170 4171 4172
        }
    }

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

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

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

B
Brian Anderson 已提交
4198
    return tbl[tycat(ty)][opcat(op)];
4199 4200
}

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

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

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

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

4229 4230 4231 4232
        ty_estr(vstore) =>
            // This type has a vstore. Get rid of it
            mk_estr(cx, normalize_vstore(vstore)),

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

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

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

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

        _ =>
            t
4272 4273
    };

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

4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296
// 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;
        }
4297 4298 4299 4300 4301 4302 4303
        const_eval::const_bool(_) => {
            tcx.sess.span_err(span,
                              ~"expected signed or unsigned integer for \
                                repeat count but found boolean");
            return 0;
        }

4304 4305 4306
    }
}

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

4320 4321 4322 4323 4324 4325 4326 4327 4328 4329
// 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,

B
Brian Anderson 已提交
4330
            ty::bound_copy | ty::bound_owned |
B
Brian Anderson 已提交
4331
            ty::bound_const | ty::bound_durable => {
4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377
                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;
}

4378
impl mt : cmp::Eq {
4379 4380 4381 4382
    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) }
4383
}
4384

4385
impl arg : cmp::Eq {
4386 4387 4388 4389
    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) }
4390
}
4391

4392
impl field : cmp::Eq {
4393 4394 4395 4396
    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) }
4397
}
4398

4399
impl vstore : cmp::Eq {
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 4426 4427 4428
    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) }
4429
}
4430

4431
impl TyVid : cmp::Eq {
4432 4433
    pure fn eq(&self, other: &TyVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &TyVid) -> bool { *(*self) != *(*other) }
4434
}
4435

4436
impl IntVid : cmp::Eq {
4437 4438
    pure fn eq(&self, other: &IntVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &IntVid) -> bool { *(*self) != *(*other) }
4439
}
4440

4441
impl FloatVid : cmp::Eq {
4442 4443
    pure fn eq(&self, other: &FloatVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &FloatVid) -> bool { *(*self) != *(*other) }
4444 4445
}

4446
impl FnVid : cmp::Eq {
4447 4448
    pure fn eq(&self, other: &FnVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &FnVid) -> bool { *(*self) != *(*other) }
4449
}
4450

4451
impl RegionVid : cmp::Eq {
4452 4453
    pure fn eq(&self, other: &RegionVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &RegionVid) -> bool { *(*self) != *(*other) }
4454
}
4455

4456
impl Region : cmp::Eq {
4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491
    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) }
4492
}
4493

4494
impl bound_region : cmp::Eq {
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: &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
                }
            }
4521 4522 4523 4524 4525 4526
            br_fresh(e0a) => {
                match (*other) {
                    br_fresh(e0b) => e0a == e0b,
                    _ => false
                }
            }
4527 4528 4529
        }
    }
    pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) }
4530
}
4531

4532
impl substs : cmp::Eq {
4533 4534 4535 4536 4537 4538
    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) }
4539
}
4540

4541
impl sty : cmp::Eq {
4542
    pure fn eq(&self, other: &sty) -> bool {
4543
        match (/*bad*/copy *self) {
4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585
            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
                }
            }
4586
            ty_enum(e0a, ref e1a) => {
4587
                match (*other) {
4588
                    ty_enum(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622
                    _ => 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) => {
4623
                match (/*bad*/copy *other) {
4624 4625 4626 4627
                    ty_rec(e0b) => e0a == e0b,
                    _ => false
                }
            }
4628
            ty_fn(ref e0a) => {
4629
                match (*other) {
4630
                    ty_fn(ref e0b) => (*e0a) == (*e0b),
4631 4632 4633
                    _ => false
                }
            }
4634
            ty_trait(e0a, ref e1a, e2a) => {
4635
                match (*other) {
4636 4637
                    ty_trait(e0b, ref e1b, e2b) =>
                        e0a == e0b && (*e1a) == (*e1b) && e2a == e2b,
4638 4639 4640
                    _ => false
                }
            }
4641
            ty_struct(e0a, ref e1a) => {
4642
                match (*other) {
4643
                    ty_struct(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4644 4645 4646 4647
                    _ => false
                }
            }
            ty_tup(e0a) => {
4648
                match (/*bad*/copy *other) {
4649 4650 4651 4652
                    ty_tup(e0b) => e0a == e0b,
                    _ => false
                }
            }
4653
            ty_infer(ref e0a) => {
4654
                match (*other) {
4655
                    ty_infer(ref e0b) => *e0a == *e0b,
4656 4657 4658
                    _ => false
                }
            }
4659 4660 4661 4662 4663 4664
            ty_err => {
                match (*other) {
                    ty_err => true,
                    _ => false
                }
            }
4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703
            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) }
4704
}
4705

4706
impl param_bound : cmp::Eq {
4707 4708 4709 4710 4711 4712 4713 4714
    pure fn eq(&self, other: &param_bound) -> bool {
        match (*self) {
            bound_copy => {
                match (*other) {
                    bound_copy => true,
                    _ => false
                }
            }
B
Brian Anderson 已提交
4715
            bound_durable => {
4716
                match (*other) {
B
Brian Anderson 已提交
4717
                    bound_durable => true,
4718 4719 4720
                    _ => false
                }
            }
B
Brian Anderson 已提交
4721
            bound_owned => {
4722
                match (*other) {
B
Brian Anderson 已提交
4723
                    bound_owned => true,
4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740
                    _ => false
                }
            }
            bound_const => {
                match (*other) {
                    bound_const => true,
                    _ => false
                }
            }
            bound_trait(e0a) => {
                match (*other) {
                    bound_trait(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
B
Brian Anderson 已提交
4741
    pure fn ne(&self, other: &param_bound) -> bool { !self.eq(other) }
4742
}
4743

4744
impl Kind : cmp::Eq {
4745 4746
    pure fn eq(&self, other: &Kind) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &Kind) -> bool { *(*self) != *(*other) }
4747
}
4748

4749

4750 4751 4752 4753 4754 4755 4756
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: