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

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

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

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

222
// Data types
223

224 225
// Note: after typeck, you should use resolved_mode() to convert this mode
// into an rmode, which will take into account the results of mode inference.
T
Tim Chevalier 已提交
226
type arg = {mode: ast::mode, ty: t};
227

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

230
type param_bounds = @~[param_bound];
231

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

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

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

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

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

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

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

282 283 284 285 286
impl creader_cache_key : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f);
    }
}
287

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

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

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

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

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

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

314
impl region_variance : cmp::Eq {
315 316 317 318 319 320 321 322 323 324 325
    pure fn eq(&self, other: &region_variance) -> bool {
        match ((*self), (*other)) {
            (rv_covariant, rv_covariant) => true,
            (rv_invariant, rv_invariant) => true,
            (rv_contravariant, rv_contravariant) => true,
            (rv_covariant, _) => false,
            (rv_invariant, _) => false,
            (rv_contravariant, _) => false
        }
    }
    pure fn ne(&self, other: &region_variance) -> bool { !(*self).eq(other) }
326
}
327

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

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

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

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

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

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

359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
// Stores information about provided methods (a.k.a. default methods) in
// implementations.
//
// This is a map from ID of each implementation to the method info and trait
// method ID of each of the default methods belonging to the trait that that
// implementation implements.
type ProvidedMethodsMap = HashMap<def_id,@DVec<@ProvidedMethodInfo>>;

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

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

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

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

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

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

      // Stores the type parameters which were substituted to obtain the type
      // of this node.  This only applies to nodes that refer to entities
      // parameterized by type parameters, such as generic fns, types, or
      // other items.
B
Brian Anderson 已提交
406
      node_type_substs: HashMap<node_id, ~[t]>,
407

M
Marijn Haverbeke 已提交
408
      items: ast_map::map,
B
Brian Anderson 已提交
409
      intrinsic_defs: HashMap<ast::ident, (ast::def_id, t)>,
M
Marijn Haverbeke 已提交
410 411 412
      freevars: freevars::freevar_map,
      tcache: type_cache,
      rcache: creader_cache,
413
      ccache: constness_cache,
B
Brian Anderson 已提交
414 415 416
      short_names_cache: HashMap<t, @~str>,
      needs_drop_cache: HashMap<t, bool>,
      needs_unwind_cleanup_cache: HashMap<t, bool>,
417 418
      kind_cache: HashMap<t, Kind>,
      ast_ty_to_ty_cache: HashMap<@ast::Ty, ast_ty_to_ty_cache_entry>,
419
      enum_var_cache: HashMap<def_id, @~[VariantInfo]>,
B
Brian Anderson 已提交
420 421 422
      trait_method_cache: HashMap<def_id, @~[method]>,
      ty_param_bounds: HashMap<ast::node_id, param_bounds>,
      inferred_modes: HashMap<ast::node_id, ast::mode>,
423
      adjustments: HashMap<ast::node_id, @AutoAdjustment>,
424
      normalized_cache: HashMap<t, t>,
425
      lang_items: middle::lang_items::LanguageItems,
426
      legacy_boxed_traits: HashMap<node_id, ()>,
B
Brian Anderson 已提交
427 428 429
      // A mapping from an implementation ID to the method info and trait
      // method ID of the provided (a.k.a. default) methods in the traits that
      // that implementation implements.
430
      provided_methods: ProvidedMethodsMap,
431
      provided_method_sources: HashMap<ast::def_id, ProvidedMethodSource>,
432
      supertraits: HashMap<ast::def_id, @~[InstantiatedTraitRef]>,
433 434 435 436 437 438 439 440

      // A mapping from the def ID of an enum or struct type to the def ID
      // of the method that implements its destructor. If the type is not
      // present in this map, it does not have a destructor. This map is
      // populated during the coherence phase of typechecking.
      destructor_for_type: HashMap<ast::def_id, ast::def_id>,

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

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

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

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

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

463 464 465 466 467 468 469
// To reduce refcounting cost, we're representing types as unsafe pointers
// throughout the compiler. These are simply casted t_box values. Use ty::get
// to cast them back to a box. (Without the cast, compiler performance suffers
// ~15%.) This does mean that a t value relies on the ctxt to keep its box
// alive, and using ty::get is unsafe when the ctxt is no longer alive.
enum t_opaque {}
type t = *t_opaque;
470

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

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

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

/**
 * Signature of a function type, which I have arbitrarily
 * decided to use to refer to the input/output types.
 *
 * - `inputs` is the list of arguments and their modes.
 * - `output` is the return type. */
struct FnSig {
514 515
    inputs: ~[arg],
    output: t
516 517 518 519 520 521 522 523
}

/**
 * Function type: combines the meta information and the
 * type signature.  This particular type is parameterized
 * by the meta information because, in some cases, the
 * meta information is inferred. */
struct FnTyBase<M: cmp::Eq> {
524 525
    meta: M,
    sig: FnSig
526 527 528
}

type FnTy = FnTyBase<FnMeta>;
529

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

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

539 540 541 542 543
impl param_ty : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_2(&self.idx, &self.def_id, lsb0, f)
    }
}
544 545


546
/// Representation of regions:
547 548
#[auto_serialize]
#[auto_deserialize]
549
enum Region {
550 551 552 553 554 555 556 557 558
    /// Bound regions are found (primarily) in function types.  They indicate
    /// region parameters that have yet to be replaced with actual regions
    /// (analogous to type parameters, except that due to the monomorphic
    /// nature of our type system, bound type parameters are always replaced
    /// with fresh type variables whenever an item is referenced, so type
    /// parameters only appear "free" in types.  Regions in contrast can
    /// appear free or bound.).  When a function is called, all bound regions
    /// tied to that function's node-id are replaced with fresh region
    /// variables whose value is then inferred.
N
Niko Matsakis 已提交
559
    re_bound(bound_region),
560 561 562 563

    /// When checking a function body, the types of all arguments and so forth
    /// that refer to bound region parameters are modified to refer to free
    /// region parameters.
N
Niko Matsakis 已提交
564
    re_free(node_id, bound_region),
565 566

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

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

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

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

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

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

588 589 590 591 592 593 594 595 596
    /**
     * Handles capture-avoiding substitution in a rather subtle case.  If you
     * have a closure whose argument types are being inferred based on the
     * expected type, and the expected type includes bound regions, then we
     * will wrap those bound regions in a br_cap_avoid() with the id of the
     * fn expression.  This ensures that the names are not "captured" by the
     * enclosing scope, which may define the same names.  For an example of
     * where this comes up, see src/test/compile-fail/regions-ret-borrowed.rs
     * and regions-ret-borrowed-1.rs. */
597
    br_cap_avoid(ast::node_id, @bound_region),
598 599
}

600
type opt_region = Option<Region>;
601

602 603 604 605 606 607 608 609 610
/**
 * The type substs represents the kinds of things that can be substituted to
 * convert a polytype into a monotype.  Note however that substituting bound
 * regions other than `self` is done through a different mechanism:
 *
 * - `tps` represents the type parameters in scope.  They are indexed
 *   according to the order in which they were declared.
 *
 * - `self_r` indicates the region parameter `self` that is present on nominal
611
 *   types (enums, structs) declared as having a region parameter.  `self_r`
612 613 614 615 616 617 618
 *   should always be none for types that are not region-parameterized and
 *   Some(_) for types that are.  The only bound region parameter that should
 *   appear within a region-parameterized type is `self`.
 *
 * - `self_ty` is the type to which `self` should be remapped, if any.  The
 *   `self` type is rather funny in that it can only appear on traits and is
 *   always substituted away to the implementing type for a trait. */
619 620
type substs = {
    self_r: opt_region,
B
Brian Anderson 已提交
621
    self_ty: Option<ty::t>,
622
    tps: ~[t]
623 624
};

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

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

650
    ty_infer(InferTy), // soething used only during inference/typeck
651 652 653
    ty_err, // Also only used during inference/typeck, to represent
            // the type of an erroneous expression (helps cut down
            // on non-useful type error messages)
654

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

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

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

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

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

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

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

725 726 727 728 729 730 731 732 733
impl InferTy : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
          IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f),
          FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f)
        }
    }
}
734

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

742 743 744 745 746 747 748 749
impl InferRegion : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
            ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f),
            ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f)
        }
    }
}
750 751

impl InferRegion : cmp::Eq {
752 753 754 755 756 757 758 759 760 761 762 763 764 765
    pure fn eq(&self, other: &InferRegion) -> bool {
        match ((*self), *other) {
            (ReVar(rva), ReVar(rvb)) => {
                rva == rvb
            }
            (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
                rva == rvb
            }
            _ => false
        }
    }
    pure fn ne(&self, other: &InferRegion) -> bool {
        !((*self) == (*other))
    }
766 767
}

768 769 770 771
impl param_bound : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          bound_copy => 0u8.iter_bytes(lsb0, f),
B
Brian Anderson 已提交
772
          bound_durable => 1u8.iter_bytes(lsb0, f),
B
Brian Anderson 已提交
773
          bound_owned => 2u8.iter_bytes(lsb0, f),
774 775 776 777 778 779
          bound_const => 3u8.iter_bytes(lsb0, f),
          bound_trait(ref t) =>
          to_bytes::iter_bytes_2(&4u8, t, lsb0, f)
        }
    }
}
780

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

891 892 893 894 895 896 897 898 899 900
/// A polytype.
///
/// - `bounds`: The list of bounds for each type parameter.  The length of the
///   list also tells you how many type parameters there are.
///
/// - `rp`: true if the type is region-parameterized.  Types can have at
///   most one region parameter, always called `&self`.
///
/// - `ty`: the base type.  May have reference to the (unsubstituted) bound
///   region `&self` or to (unsubstituted) ty_param types
901
type ty_param_bounds_and_ty = {bounds: @~[param_bounds],
B
Brian Anderson 已提交
902
                               region_param: Option<region_variance>,
903
                               ty: t};
904

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Converts s to its machine type equivalent
1190
pure fn mach_sty(cfg: @session::config, t: t) -> sty {
1191
    match get(t).sty {
B
Brian Anderson 已提交
1192 1193 1194
      ty_int(ast::ty_i) => ty_int(cfg.int_type),
      ty_uint(ast::ty_u) => ty_uint(cfg.uint_type),
      ty_float(ast::ty_f) => ty_float(cfg.float_type),
1195
      ref s => (*s)
1196 1197 1198
    }
}

1199
fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
1200 1201 1202 1203
        // FIXME(#2202) --- We retain by-ref for fn& things to workaround a
        // memory leak that otherwise results when @fn is upcast to &fn.
    if type_is_fn(ty) {
        match ty_fn_proto(ty) {
1204 1205 1206 1207
            ast::ProtoBorrowed => {
                return ast::by_ref;
            }
            _ => {}
1208 1209 1210
        }
    }
    return if tcx.legacy_modes {
1211 1212 1213 1214 1215 1216 1217 1218 1219
        if type_is_borrowed(ty) {
            // the old mode default was ++ for things like &ptr, but to be
            // forward-compatible with non-legacy, we should use +
            ast::by_copy
        } else if ty::type_is_immediate(ty) {
            ast::by_val
        } else {
            ast::by_ref
        }
1220 1221
    } else {
        ast::by_copy
1222 1223 1224 1225 1226 1227 1228
    };

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

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

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

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

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

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

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

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

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

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

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

    if (walkt(ty)) {
        fold_regions_and_ty(
            cx, ty,
B
Brian Anderson 已提交
1369 1370 1371
            |r| { walkr(r); r },
            |t| { walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t },
            |t| { walkt(t); walk_regions_and_ty(cx, t, walkr, walkt); t });
1372 1373 1374
    }
}

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

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

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

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

1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
/* A little utility: it often happens that I have a `fn_ty`,
 * but I want to use some function like `fold_regions_and_ty()`
 * that is defined over all types.  This utility converts to
 * a full type and back.  It's not the best way to do this (somewhat
 * inefficient to do the conversion), it would be better to refactor
 * all this folding business.  However, I've been waiting on that
 * until trait support is improved. */
fn apply_op_on_t_to_ty_fn(
    cx: ctxt,
    f: &FnTy,
    t_op: fn(t) -> t) -> FnTy
{
    let t0 = ty::mk_fn(cx, *f);
    let t1 = t_op(t0);
    match ty::get(t1).sty {
        ty::ty_fn(copy f) => {
            move f
        }
        _ => {
            cx.sess.bug(~"`t_op` did not return a function type");
        }
    }
}

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

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

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

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

1515
// Substitute *only* type parameters.  Used in trans where regions are erased.
1516 1517
fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
    if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1518
    let tb = ty::get(typ);
1519
    if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1520
    match tb.sty {
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
        ty_param(p) => tps[p.idx],
        ty_self => {
            match self_ty_opt {
                None => cx.sess.bug(~"ty_self unexpected here"),
                Some(self_ty) => {
                    subst_tps(cx, tps, self_ty_opt, self_ty)
                }
            }
        }
        ref sty => {
            fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t))
        }
1533 1534 1535
    }
}

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

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

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

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

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

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

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

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

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

1611
// Type utilities
1612

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

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

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

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

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

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

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

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

1655
fn sequence_element_type(cx: ctxt, ty: t) -> t {
1656
    match get(ty).sty {
B
Brian Anderson 已提交
1657 1658 1659 1660
      ty_estr(_) => return mk_mach_uint(cx, ast::ty_u8),
      ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
      _ => cx.sess.bug(
          ~"sequence_element_type called on non-sequence value"),
1661 1662 1663
    }
}

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

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

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

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

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

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

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

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

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

1732 1733 1734 1735 1736
/*
 A scalar type is one that denotes an atomic datum, with no sub-components.
 (A ty_ptr is scalar because it represents a non-managed pointer, so its
 contents are abstract to rustc.)
*/
1737
pure fn type_is_scalar(ty: t) -> bool {
1738
    match get(ty).sty {
1739
      ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1740 1741
      ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
      ty_ptr(_) => true,
B
Brian Anderson 已提交
1742
      _ => false
M
Marijn Haverbeke 已提交
1743
    }
1744 1745
}

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

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

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

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

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

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

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

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

1826 1827 1828 1829 1830
// Some things don't need cleanups during unwinding because the
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
// cleanups.
fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1831
    match cx.needs_unwind_cleanup_cache.find(ty) {
B
Brian Anderson 已提交
1832 1833
      Some(result) => return result,
      None => ()
1834 1835
    }

1836 1837 1838 1839
    let tycache = new_ty_hash();
    let needs_unwind_cleanup =
        type_needs_unwind_cleanup_(cx, ty, tycache, false);
    cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
B
Brian Anderson 已提交
1840
    return needs_unwind_cleanup;
1841 1842 1843
}

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

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

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

        encountered_box = old_encountered_box;
        result
1901 1902
    }

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

1906
enum Kind { kind_(u32) }
1907

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

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

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

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

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

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

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

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

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

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

1943
fn kind_implicitly_sendable() -> Kind {
B
Brian Anderson 已提交
1944
    kind_(KIND_MASK_IMPLICIT | KIND_MASK_COPY | KIND_MASK_OWNED)
1945 1946
}

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


B
Brian Anderson 已提交
1954 1955
fn kind_owned_copy() -> Kind {
    kind_(KIND_MASK_COPY | KIND_MASK_OWNED)
1956
}
1957

B
Brian Anderson 已提交
1958 1959
fn kind_owned_only() -> Kind {
    kind_(KIND_MASK_OWNED)
1960 1961
}

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

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

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

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

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

B
Brian Anderson 已提交
1982 1983
fn remove_owned(k: Kind) -> Kind {
    k - kind_(KIND_MASK_OWNED)
1984 1985
}

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

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

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

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

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

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

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

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

2033
pure fn kind_can_be_sent(k: Kind) -> bool {
B
Brian Anderson 已提交
2034
    *k & KIND_MASK_OWNED == KIND_MASK_OWNED
2035 2036
}

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

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

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

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

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

2070 2071
#[test]
fn test_kinds() {
2072 2073
    // The kind "lattice" is defined by the subset operation on the
    // set of permitted operations.
B
Brian Anderson 已提交
2074 2075
    assert kind_lteq(kind_owned_copy(), kind_owned_copy());
    assert kind_lteq(kind_copyable(), kind_owned_copy());
2076
    assert kind_lteq(kind_copyable(), kind_copyable());
B
Brian Anderson 已提交
2077
    assert kind_lteq(kind_noncopyable(), kind_owned_copy());
2078 2079
    assert kind_lteq(kind_noncopyable(), kind_copyable());
    assert kind_lteq(kind_noncopyable(), kind_noncopyable());
2080 2081
    assert kind_lteq(kind_copyable(), kind_implicitly_copyable());
    assert kind_lteq(kind_copyable(), kind_implicitly_sendable());
B
Brian Anderson 已提交
2082 2083 2084
    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());
2085 2086 2087 2088 2089
}

// Return the most permissive kind that a composite object containing a field
// with the given mutability can have.
// This is used to prevent objects containing mutable state from being
2090
// implicitly copied and to compute whether things have const kind.
2091
fn mutability_kind(m: mutability) -> Kind {
2092
    match (m) {
B
Brian Anderson 已提交
2093 2094 2095
      m_mutbl => remove_const(remove_implicit(kind_top())),
      m_const => remove_implicit(kind_top()),
      m_imm => kind_top()
2096 2097 2098
    }
}

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

2103
fn type_kind(cx: ctxt, ty: t) -> Kind {
2104 2105 2106 2107 2108 2109
    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 {
2110
    match cx.kind_cache.find(ty) {
B
Brian Anderson 已提交
2111 2112
      Some(result) => return result,
      None => {/* fall through */ }
2113 2114 2115
    }

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

2118
    let mut result = match get(ty).sty {
2119
      // Scalar and unique types are sendable, constant, and owned
2120
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
B
Brian Anderson 已提交
2121
      ty_ptr(_) => {
B
Brian Anderson 已提交
2122
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2123 2124
      }

2125
      // Implicit copyability of strs is configurable
B
Brian Anderson 已提交
2126
      ty_estr(vstore_uniq) => {
2127
        if cx.vecs_implicitly_copyable {
B
Brian Anderson 已提交
2128
            kind_implicitly_sendable() | kind_const() | kind_durable()
2129
        } else {
B
Brian Anderson 已提交
2130
            kind_owned_copy() | kind_const() | kind_durable()
2131
        }
2132
      }
2133 2134

      // functions depend on the protocol
2135
      ty_fn(ref f) => meta_kind(f.meta),
2136 2137 2138

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

2143
      // Trait instances are (for now) like shared boxes, basically
2144
<<<<<<< HEAD
B
Brian Anderson 已提交
2145
      ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_durable(),
2146 2147 2148 2149
=======
      // XXX: This is wrong for ~Trait and &Trait!
      ty_trait(_, _, _) => kind_safe_for_default_mode() | kind_owned(),
>>>>>>> librustc: Have coherence check Copy kind bounds when determining whether parameter substitutions could possibly unify. r=nmatsakis
2150

2151 2152 2153 2154 2155
      // 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 已提交
2156
      ty_rptr(_, _) => kind_safe_for_default_mode(),
2157

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

2162
      // Implicit copyability of vecs is configurable
B
Brian Anderson 已提交
2163
      ty_evec(tm, vstore_uniq) => {
2164
          if cx.vecs_implicitly_copyable {
2165
              mutable_type_kind(cx, tm)
2166 2167 2168
          } else {
              remove_implicit(mutable_type_kind(cx, tm))
          }
2169
      }
2170

2171 2172 2173
      // 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 已提交
2174
      ty_evec(tm, vstore_box) => {
B
Brian Anderson 已提交
2175
        remove_owned(kind_safe_for_default_mode() | mutable_type_kind(cx, tm))
2176
      }
2177 2178 2179
      ty_evec(tm, vstore_slice(re_static)) => {
        kind_safe_for_default_mode() | mutable_type_kind(cx, tm)
      }
B
Brian Anderson 已提交
2180
      ty_evec(tm, vstore_slice(_)) => {
B
Brian Anderson 已提交
2181
        remove_durable_owned(kind_safe_for_default_mode() |
B
Brian Anderson 已提交
2182
                           mutable_type_kind(cx, tm))
2183
      }
B
Brian Anderson 已提交
2184
      ty_evec(tm, vstore_fixed(_)) => {
2185
        mutable_type_kind(cx, tm)
2186
      }
2187 2188

      // All estrs are copyable; uniques and interiors are sendable.
B
Brian Anderson 已提交
2189
      ty_estr(vstore_box) => {
B
Brian Anderson 已提交
2190
        kind_safe_for_default_mode() | kind_const() | kind_durable()
2191
      }
2192
      ty_estr(vstore_slice(re_static)) => {
B
Brian Anderson 已提交
2193
        kind_safe_for_default_mode() | kind_owned_copy() | kind_const()
2194
      }
B
Brian Anderson 已提交
2195
      ty_estr(vstore_slice(_)) => {
2196
        kind_safe_for_default_mode() | kind_const()
2197
      }
B
Brian Anderson 已提交
2198
      ty_estr(vstore_fixed(_)) => {
B
Brian Anderson 已提交
2199
        kind_safe_for_default_mode_send() | kind_const() | kind_durable()
2200
      }
2201

2202
      // Records lower to the lowest of their members.
B
Brian Anderson 已提交
2203
      ty_rec(flds) => {
2204
        let mut lowest = kind_top();
B
Brian Anderson 已提交
2205
        for flds.each |f| {
2206
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
2207
        }
M
Marijn Haverbeke 已提交
2208
        lowest
2209
      }
2210

2211 2212
      ty_struct(did, ref substs) => {
        // Structs are sendable if all their fields are sendable,
2213
        // likewise for copyable...
2214 2215
        // also factor out this code, copied from the records case
        let mut lowest = kind_top();
2216
        let flds = struct_fields(cx, did, substs);
B
Brian Anderson 已提交
2217
        for flds.each |f| {
2218 2219
            lowest = lower_kind(lowest, mutable_type_kind(cx, f.mt));
        }
2220
        // ...but structs with dtors are never copyable (they can be
2221 2222
        // sendable)
        if ty::has_dtor(cx, did) {
2223
           lowest = remove_copyable(lowest);
2224
        }
2225
        lowest
2226
      }
2227

2228
      // Tuples lower to the lowest of their members.
B
Brian Anderson 已提交
2229
      ty_tup(tys) => {
2230
        let mut lowest = kind_top();
2231
        for tys.each |ty| { lowest = lower_kind(lowest, type_kind(cx, *ty)); }
M
Marijn Haverbeke 已提交
2232
        lowest
2233
      }
2234

2235
      // Enums lower to the lowest of their variants.
N
Niko Matsakis 已提交
2236
      ty_enum(did, ref substs) => {
2237
        let mut lowest = kind_top();
2238 2239
        let variants = enum_variants(cx, did);
        if vec::len(*variants) == 0u {
B
Brian Anderson 已提交
2240
            lowest = kind_owned_only() | kind_durable();
2241
        } else {
2242
            for vec::each(*variants) |variant| {
B
Brian Anderson 已提交
2243
                for variant.args.each |aty| {
2244
                    // Perform any type parameter substitutions.
2245
                    let arg_ty = subst(cx, substs, *aty);
2246
                    lowest = lower_kind(lowest, type_kind(cx, arg_ty));
2247
                    if lowest == kind_noncopyable() { break; }
2248
                }
2249 2250
            }
        }
M
Marijn Haverbeke 已提交
2251
        lowest
2252
      }
2253

B
Brian Anderson 已提交
2254
      ty_param(p) => {
2255
        param_bounds_to_kind(cx.ty_param_bounds.get(p.def_id.node))
2256
      }
2257

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

2262
      ty_infer(_) => {
2263 2264 2265 2266 2267
        if allow_ty_var {
            kind_top()
        } else {
            cx.sess.bug(~"Asked to compute kind of a type variable")
        }
2268
      }
2269

B
Brian Anderson 已提交
2270
      ty_type | ty_opaque_closure_ptr(_)
2271
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2272
        cx.sess.bug(~"Asked to compute kind of fictitious type");
2273
      }
M
Marijn Haverbeke 已提交
2274
    };
2275

2276 2277 2278
    // arbitrary threshold to prevent by-value copying of big records
    if kind_is_safe_for_default_mode(result) {
        if type_size(cx, ty) > 4 {
2279
            result = result - kind_(KIND_MASK_DEFAULT_MODE);
2280 2281 2282
        }
    }

2283
    cx.kind_cache.insert(ty, result);
B
Brian Anderson 已提交
2284
    return result;
2285 2286
}

2287 2288 2289 2290 2291
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))
}

2292 2293 2294
/// 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 {
2295
    match get(ty).sty {
2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317
      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 已提交
2318
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2319 2320
      }

2321 2322
      ty_struct(did, ref substs) => {
        let flds = struct_fields(cx, did, substs);
T
Tim Chevalier 已提交
2323
        flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2324 2325
      }

B
Brian Anderson 已提交
2326
      ty_tup(tys) => {
T
Tim Chevalier 已提交
2327
        tys.foldl(0, |s, t| *s + type_size(cx, *t))
2328 2329
      }

N
Niko Matsakis 已提交
2330
      ty_enum(did, ref substs) => {
2331 2332 2333
        let variants = substd_enum_variants(cx, did, substs);
        variants.foldl( // find max size of any variant
            0,
T
Tim Chevalier 已提交
2334
            |m, v| uint::max(*m,
2335
                             // find size of this variant:
T
Tim Chevalier 已提交
2336
                             v.args.foldl(0, |s, a| *s + type_size(cx, *a))))
2337 2338
      }

B
Brian Anderson 已提交
2339
      ty_param(_) | ty_self => {
2340 2341 2342
        1
      }

2343
      ty_infer(_) => {
2344 2345
        cx.sess.bug(~"Asked to compute kind of a type variable");
      }
B
Brian Anderson 已提交
2346
      ty_type | ty_opaque_closure_ptr(_)
2347
      | ty_opaque_box | ty_unboxed_vec(_) | ty_err => {
2348 2349 2350 2351 2352
        cx.sess.bug(~"Asked to compute kind of fictitious type");
      }
    }
}

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

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

        let r = {
2363
            get(r_ty).sty == get(ty).sty ||
2364 2365 2366
                subtypes_require(cx, seen, r_ty, ty)
        };

P
Paul Stansifer 已提交
2367
        debug!("type_requires(%s, %s)? %b",
2368 2369
               ty_to_str(cx, r_ty),
               ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2370
               r);
B
Brian Anderson 已提交
2371
        return r;
2372 2373
    }

2374
    fn subtypes_require(cx: ctxt, seen: @mut ~[def_id],
2375
                        r_ty: t, ty: t) -> bool {
P
Paul Stansifer 已提交
2376
        debug!("subtypes_require(%s, %s)?",
2377
               ty_to_str(cx, r_ty),
P
Paul Stansifer 已提交
2378
               ty_to_str(cx, ty));
2379

2380
        let r = match get(ty).sty {
2381 2382 2383 2384 2385 2386
          ty_nil |
          ty_bot |
          ty_bool |
          ty_int(_) |
          ty_uint(_) |
          ty_float(_) |
2387
          ty_estr(_) |
2388
          ty_fn(_) |
2389
          ty_infer(_) |
2390
          ty_err |
2391
          ty_param(_) |
2392
          ty_self |
2393 2394 2395
          ty_type |
          ty_opaque_box |
          ty_opaque_closure_ptr(_) |
2396
          ty_evec(_, _) |
B
Brian Anderson 已提交
2397
          ty_unboxed_vec(_) => {
2398 2399 2400 2401
            false
          }
          ty_box(mt) |
          ty_uniq(mt) |
B
Brian Anderson 已提交
2402
          ty_rptr(_, mt) => {
B
Brian Anderson 已提交
2403
            return type_requires(cx, seen, r_ty, mt.ty);
2404 2405
          }

2406
          ty_ptr(*) => {
2407 2408 2409
            false           // unsafe ptrs can always be NULL
          }

B
Brian Anderson 已提交
2410
          ty_rec(fields) => {
B
Brian Anderson 已提交
2411
            do vec::any(fields) |field| {
2412 2413 2414 2415
                type_requires(cx, seen, r_ty, field.mt.ty)
            }
          }

2416
          ty_trait(_, _, _) => {
2417 2418 2419
            false
          }

2420
          ty_struct(ref did, _) if vec::contains(*seen, did) => {
2421 2422 2423
            false
          }

2424
          ty_struct(did, ref substs) => {
2425
              seen.push(did);
2426
              let r = vec::any(struct_fields(cx, did, substs),
2427
                               |f| type_requires(cx, seen, r_ty, f.mt.ty));
N
Niko Matsakis 已提交
2428
              seen.pop();
2429 2430 2431
            r
          }

B
Brian Anderson 已提交
2432
          ty_tup(ts) => {
N
Niko Matsakis 已提交
2433
            vec::any(ts, |t| type_requires(cx, seen, r_ty, *t))
2434 2435
          }

N
Niko Matsakis 已提交
2436
          ty_enum(ref did, _) if vec::contains(*seen, did) => {
2437 2438 2439
            false
          }

2440 2441 2442 2443 2444
            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 已提交
2445
                        let sty = subst(cx, substs, *aty);
2446 2447 2448
                        type_requires(cx, seen, r_ty, sty)
                    })
                });
N
Niko Matsakis 已提交
2449
                seen.pop();
2450 2451
                r
            }
2452 2453
        };

P
Paul Stansifer 已提交
2454
        debug!("subtypes_require(%s, %s)? %b",
2455 2456
               ty_to_str(cx, r_ty),
               ty_to_str(cx, ty),
P
Paul Stansifer 已提交
2457
               r);
2458

B
Brian Anderson 已提交
2459
        return r;
2460 2461
    }

2462
    let seen = @mut ~[];
2463 2464 2465
    !subtypes_require(cx, seen, r_ty, r_ty)
}

N
Niko Matsakis 已提交
2466
fn type_structurally_contains(cx: ctxt, ty: t, test: fn(x: &sty) -> bool) ->
B
Brian Anderson 已提交
2467
   bool {
2468
    let sty = &get(ty).sty;
P
Paul Stansifer 已提交
2469
    debug!("type_structurally_contains: %s", ty_to_str(cx, ty));
B
Brian Anderson 已提交
2470
    if test(sty) { return true; }
N
Niko Matsakis 已提交
2471 2472
    match *sty {
      ty_enum(did, ref substs) => {
2473
        for vec::each(*enum_variants(cx, did)) |variant| {
B
Brian Anderson 已提交
2474
            for variant.args.each |aty| {
2475
                let sty = subst(cx, substs, *aty);
B
Brian Anderson 已提交
2476
                if type_structurally_contains(cx, sty, test) { return true; }
2477
            }
2478
        }
B
Brian Anderson 已提交
2479
        return false;
M
Marijn Haverbeke 已提交
2480
      }
B
Brian Anderson 已提交
2481
      ty_rec(fields) => {
B
Brian Anderson 已提交
2482
        for fields.each |field| {
B
Brian Anderson 已提交
2483 2484 2485
            if type_structurally_contains(cx, field.mt.ty, test) {
                return true;
            }
2486
        }
B
Brian Anderson 已提交
2487
        return false;
M
Marijn Haverbeke 已提交
2488
      }
2489 2490
      ty_struct(did, ref substs) => {
        for lookup_struct_fields(cx, did).each |field| {
2491
            let ft = lookup_field_type(cx, did, field.id, substs);
B
Brian Anderson 已提交
2492
            if type_structurally_contains(cx, ft, test) { return true; }
2493
        }
B
Brian Anderson 已提交
2494
        return false;
2495 2496
      }

B
Brian Anderson 已提交
2497
      ty_tup(ts) => {
B
Brian Anderson 已提交
2498
        for ts.each |tt| {
2499
            if type_structurally_contains(cx, *tt, test) { return true; }
2500
        }
B
Brian Anderson 已提交
2501
        return false;
2502
      }
B
Brian Anderson 已提交
2503
      ty_evec(mt, vstore_fixed(_)) => {
B
Brian Anderson 已提交
2504
        return type_structurally_contains(cx, mt.ty, test);
2505
      }
B
Brian Anderson 已提交
2506
      _ => return false
M
Marijn Haverbeke 已提交
2507 2508 2509
    }
}

2510
fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
B
Brian Anderson 已提交
2511
    return type_structurally_contains(cx, ty, |sty| {
N
Niko Matsakis 已提交
2512
        match *sty {
2513 2514
          ty_uniq(_) |
          ty_evec(_, vstore_uniq) |
B
Brian Anderson 已提交
2515 2516
          ty_estr(vstore_uniq) => true,
          _ => false,
2517
        }
2518
    });
2519 2520
}

2521
fn type_is_integral(ty: t) -> bool {
2522
    match get(ty).sty {
2523
      ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) | ty_bool => true,
B
Brian Anderson 已提交
2524
      _ => false
M
Marijn Haverbeke 已提交
2525 2526 2527
    }
}

2528
fn type_is_fp(ty: t) -> bool {
2529
    match get(ty).sty {
2530
      ty_infer(FloatVar(_)) | ty_float(_) => true,
B
Brian Anderson 已提交
2531
      _ => false
M
Marijn Haverbeke 已提交
2532 2533 2534
    }
}

2535
fn type_is_numeric(ty: t) -> bool {
B
Brian Anderson 已提交
2536
    return type_is_integral(ty) || type_is_fp(ty);
2537 2538
}

2539
fn type_is_signed(ty: t) -> bool {
2540
    match get(ty).sty {
B
Brian Anderson 已提交
2541 2542
      ty_int(_) => true,
      _ => false
M
Marijn Haverbeke 已提交
2543 2544 2545
    }
}

2546 2547
// Whether a type is Plain Old Data -- meaning it does not contain pointers
// that the cycle collector might care about.
2548
fn type_is_pod(cx: ctxt, ty: t) -> bool {
2549
    let mut result = true;
2550
    match get(ty).sty {
B
Brian Anderson 已提交
2551
      // Scalar types
2552
      ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
B
Brian Anderson 已提交
2553
      ty_type | ty_ptr(_) => result = true,
B
Brian Anderson 已提交
2554
      // Boxed types
M
Michael Sullivan 已提交
2555
      ty_box(_) | ty_uniq(_) | ty_fn(_) |
2556 2557
      ty_estr(vstore_uniq) | ty_estr(vstore_box) |
      ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2558
      ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
B
Brian Anderson 已提交
2559
      // Structural types
N
Niko Matsakis 已提交
2560
      ty_enum(did, ref substs) => {
2561
        let variants = enum_variants(cx, did);
2562
        for vec::each(*variants) |variant| {
B
Brian Anderson 已提交
2563 2564 2565
            let tup_ty = mk_tup(cx, variant.args);

            // Perform any type parameter substitutions.
2566
            let tup_ty = subst(cx, substs, tup_ty);
B
Brian Anderson 已提交
2567
            if !type_is_pod(cx, tup_ty) { result = false; }
2568
        }
B
Brian Anderson 已提交
2569
      }
B
Brian Anderson 已提交
2570
      ty_rec(flds) => {
B
Brian Anderson 已提交
2571
        for flds.each |f| {
B
Brian Anderson 已提交
2572
            if !type_is_pod(cx, f.mt.ty) { result = false; }
P
Patrick Walton 已提交
2573
        }
B
Brian Anderson 已提交
2574
      }
B
Brian Anderson 已提交
2575
      ty_tup(elts) => {
2576
        for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
B
Brian Anderson 已提交
2577
      }
B
Brian Anderson 已提交
2578 2579
      ty_estr(vstore_fixed(_)) => result = true,
      ty_evec(mt, vstore_fixed(_)) | ty_unboxed_vec(mt) => {
2580 2581
        result = type_is_pod(cx, mt.ty);
      }
B
Brian Anderson 已提交
2582 2583
      ty_param(_) => result = false,
      ty_opaque_closure_ptr(_) => result = true,
2584 2585
      ty_struct(did, ref substs) => {
        result = vec::any(lookup_struct_fields(cx, did), |f| {
2586 2587 2588
            let fty = ty::lookup_item_type(cx, f.id);
            let sty = subst(cx, substs, fty.ty);
            type_is_pod(cx, sty)
2589
        });
2590
      }
2591

B
Brian Anderson 已提交
2592
      ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2593 2594 2595
        result = false;
      }

2596
      ty_infer(*) | ty_self(*) | ty_err => {
2597
        cx.sess.bug(~"non concrete type in type_is_pod");
2598
      }
P
Patrick Walton 已提交
2599 2600
    }

B
Brian Anderson 已提交
2601
    return result;
P
Patrick Walton 已提交
2602 2603
}

2604
fn type_is_enum(ty: t) -> bool {
2605
    match get(ty).sty {
B
Brian Anderson 已提交
2606 2607
      ty_enum(_, _) => return true,
      _ => return false
2608 2609 2610
    }
}

P
Patrick Walton 已提交
2611
// Whether a type is enum like, that is a enum type with only nullary
2612
// constructors
2613
fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2614
    match get(ty).sty {
2615
      ty_enum(did, _) => {
2616
        let variants = enum_variants(cx, did);
B
Brian Anderson 已提交
2617
        let some_n_ary = vec::any(*variants, |v| vec::len(v.args) > 0u);
B
Brian Anderson 已提交
2618
        return !some_n_ary;
2619
      }
B
Brian Anderson 已提交
2620
      _ => return false
2621 2622 2623
    }
}

B
Brian Anderson 已提交
2624
fn type_param(ty: t) -> Option<uint> {
2625
    match get(ty).sty {
B
Brian Anderson 已提交
2626
      ty_param(p) => return Some(p.idx),
B
Brian Anderson 已提交
2627
      _ => {/* fall through */ }
2628
    }
B
Brian Anderson 已提交
2629
    return None;
2630 2631
}

2632 2633
// Returns the type and mutability of *t.
//
2634 2635 2636 2637
// 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)
2638
}
2639 2640

fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
N
Niko Matsakis 已提交
2641
    match *sty {
B
Brian Anderson 已提交
2642
      ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
B
Brian Anderson 已提交
2643
        Some(mt)
2644 2645
      }

2646
      ty_ptr(mt) if explicit => {
B
Brian Anderson 已提交
2647
        Some(mt)
2648 2649
      }

N
Niko Matsakis 已提交
2650
      ty_enum(did, ref substs) => {
2651 2652 2653
        let variants = enum_variants(cx, did);
        if vec::len(*variants) == 1u && vec::len(variants[0].args) == 1u {
            let v_t = subst(cx, substs, variants[0].args[0]);
B
Brian Anderson 已提交
2654
            Some({ty: v_t, mutbl: ast::m_imm})
2655
        } else {
B
Brian Anderson 已提交
2656
            None
2657 2658 2659
        }
      }

2660 2661
      ty_struct(did, ref substs) => {
        let fields = struct_fields(cx, did, substs);
2662 2663 2664 2665 2666 2667 2668 2669
        if fields.len() == 1 && fields[0].ident ==
                syntax::parse::token::special_idents::unnamed_field {
            Some({ty: fields[0].mt.ty, mutbl: ast::m_imm})
        } else {
            None
        }
      }

B
Brian Anderson 已提交
2670
      _ => None
2671 2672 2673
    }
}

2674
fn type_autoderef(cx: ctxt, t: t) -> t {
2675
    let mut t = t;
2676
    loop {
2677
        match deref(cx, t, false) {
B
Brian Anderson 已提交
2678 2679
          None => return t,
          Some(mt) => t = mt.ty
2680 2681
        }
    }
2682 2683 2684
}

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

B
Brian Anderson 已提交
2689
fn index_sty(cx: ctxt, sty: &sty) -> Option<mt> {
N
Niko Matsakis 已提交
2690
    match *sty {
B
Brian Anderson 已提交
2691 2692 2693
      ty_evec(mt, _) => Some(mt),
      ty_estr(_) => Some({ty: mk_u8(cx), mutbl: ast::m_imm}),
      _ => None
2694
    }
2695 2696
}

2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712
impl bound_region : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        match *self {
          ty::br_self => 0u8.iter_bytes(lsb0, f),

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

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

          ty::br_cap_avoid(ref id, ref br) =>
          to_bytes::iter_bytes_3(&3u8, id, br, lsb0, f)
        }
    }
}
2713

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

2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747
          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),
        }
    }
}
2748

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

2757 2758 2759 2760 2761 2762
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)
    }
}
2763

2764 2765 2766 2767 2768 2769
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)
    }
}
2770

2771 2772 2773 2774 2775 2776
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)
    }
}
2777

2778 2779 2780 2781 2782 2783 2784 2785 2786 2787
impl FnMeta : to_bytes::IterBytes {
    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
        to_bytes::iter_bytes_5(&self.purity,
                               &self.proto,
                               &self.region,
                               &self.bounds,
                               &self.ret_style,
                               lsb0, f);
    }
}
2788

2789 2790 2791 2792 2793 2794 2795
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);
    }
}
2796

2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822
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),
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833

          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) =>
2834 2835 2836
          to_bytes::iter_bytes_3(&12u8,
                                 &ft.meta,
                                 &ft.sig,
2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863
                                 lsb0, f),

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

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

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

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

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

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

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

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

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

2864
          ty_struct(ref did, ref substs) =>
2865 2866 2867 2868
          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),
2869 2870

          ty_err => 25u8.iter_bytes(lsb0, f)
2871 2872 2873 2874
        }
    }
}

B
Brian Anderson 已提交
2875 2876
fn br_hashmap<V:Copy>() -> HashMap<bound_region, V> {
    map::HashMap()
N
Niko Matsakis 已提交
2877 2878
}

2879
fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
P
Paul Stansifer 已提交
2880
    //io::println(fmt!("%?/%?", id, cx.node_types.size()));
2881
    match smallintmap::find(*cx.node_types, id as uint) {
B
Brian Anderson 已提交
2882 2883
       Some(t) => t,
       None => cx.sess.bug(
2884
           fmt!("node_id_to_type: no type for node `%s`",
P
Paul Stansifer 已提交
2885
                ast_map::node_id_to_str(cx.items, id,
P
Paul Stansifer 已提交
2886
                                        cx.sess.parse_sess.interner)))
T
Tim Chevalier 已提交
2887
    }
2888 2889
}

2890
fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2891
    match cx.node_type_substs.find(id) {
B
Brian Anderson 已提交
2892 2893
      None => return ~[],
      Some(ts) => return ts
2894 2895 2896
    }
}

2897
fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
B
Brian Anderson 已提交
2898
    return cx.node_type_substs.contains_key(id);
2899 2900
}

2901
// Type accessors for substructures of types
2902
fn ty_fn_args(fty: t) -> ~[arg] {
2903
    match get(fty).sty {
2904
      ty_fn(ref f) => f.sig.inputs,
B
Brian Anderson 已提交
2905
      _ => fail ~"ty_fn_args() called on non-fn type"
2906 2907 2908
    }
}

2909
fn ty_fn_proto(fty: t) -> Proto {
2910
    match get(fty).sty {
2911
      ty_fn(ref f) => f.meta.proto,
B
Brian Anderson 已提交
2912
      _ => fail ~"ty_fn_proto() called on non-fn type"
M
Marijn Haverbeke 已提交
2913
    }
G
Graydon Hoare 已提交
2914 2915
}

2916
fn ty_fn_purity(fty: t) -> ast::purity {
2917
    match get(fty).sty {
2918
      ty_fn(ref f) => f.meta.purity,
2919 2920 2921 2922
      _ => fail ~"ty_fn_purity() called on non-fn type"
    }
}

2923
pure fn ty_fn_ret(fty: t) -> t {
2924
    match get(fty).sty {
2925
      ty_fn(ref f) => f.sig.output,
B
Brian Anderson 已提交
2926
      _ => fail ~"ty_fn_ret() called on non-fn type"
2927
    }
G
Graydon Hoare 已提交
2928 2929
}

2930
fn ty_fn_ret_style(fty: t) -> ast::ret_style {
2931
    match get(fty).sty {
2932
      ty_fn(ref f) => f.meta.ret_style,
B
Brian Anderson 已提交
2933
      _ => fail ~"ty_fn_ret_style() called on non-fn type"
2934 2935 2936
    }
}

2937
fn is_fn_ty(fty: t) -> bool {
2938
    match get(fty).sty {
2939 2940 2941 2942 2943
      ty_fn(_) => true,
      _ => false
    }
}

2944
fn ty_region(ty: t) -> Region {
2945
    match get(ty).sty {
2946
      ty_rptr(r, _) => r,
2947
      ref s => fail fmt!("ty_region() invoked on non-rptr: %?", (*s))
2948
    }
G
Graydon Hoare 已提交
2949 2950
}

2951
// Returns a vec of all the input and output types of fty.
2952 2953
fn tys_in_fn_ty(fty: &FnTy) -> ~[t] {
    vec::append_one(fty.sig.inputs.map(|a| a.ty), fty.sig.output)
2954 2955
}

2956 2957
// Just checks whether it's a fn that returns bool,
// not its purity.
2958 2959
fn is_pred_ty(fty: t) -> bool {
    is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
2960 2961
}

2962
// Type accessors for AST nodes
N
Niko Matsakis 已提交
2963
fn block_ty(cx: ctxt, b: &ast::blk) -> t {
B
Brian Anderson 已提交
2964
    return node_id_to_type(cx, b.node.id);
2965
}
2966 2967


2968 2969
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
2970
fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
B
Brian Anderson 已提交
2971
    return node_id_to_type(cx, pat.id);
2972 2973
}

2974

2975 2976 2977 2978
// 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"
2979
// instead of "fn(t) -> T with T = int". If this isn't what you want, see
2980
// expr_ty_params_and_ty() below.
2981
fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
B
Brian Anderson 已提交
2982
    return node_id_to_type(cx, expr.id);
2983 2984
}

2985
fn expr_ty_params_and_ty(cx: ctxt,
2986
                         expr: @ast::expr) -> {params: ~[t], ty: t} {
B
Brian Anderson 已提交
2987
    return {params: node_id_to_type_params(cx, expr.id),
M
Marijn Haverbeke 已提交
2988
         ty: node_id_to_type(cx, expr.id)};
2989 2990
}

2991
fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
B
Brian Anderson 已提交
2992
    return node_id_has_type_params(cx, expr.id);
2993 2994
}

2995 2996
fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map,
                      id: ast::node_id)
B
Brian Anderson 已提交
2997
    -> Option<@~[param_bounds]> {
2998 2999 3000
    do method_map.find(id).map |method| {
        match method.origin {
          typeck::method_static(did) => {
3001 3002
            // n.b.: When we encode impl methods, the bounds
            // that we encode include both the impl bounds
3003 3004 3005 3006 3007
            // and then the method bounds themselves...
            ty::lookup_item_type(tcx, did).bounds
          }
          typeck::method_param({trait_id:trt_id,
                                method_num:n_mth, _}) |
3008 3009
          typeck::method_trait(trt_id, n_mth, _) |
          typeck::method_self(trt_id, n_mth) => {
3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021
            // ...trait methods bounds, in contrast, include only the
            // method bounds, so we must preprend the tps from the
            // trait itself.  This ought to be harmonized.
            let trt_bounds =
                ty::lookup_item_type(tcx, trt_id).bounds;
            let mth = ty::trait_methods(tcx, trt_id)[n_mth];
            @(vec::append(*trt_bounds, *mth.tps))
          }
        }
    }
}

3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069
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(*) |
3070
                ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096

                // 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(*) |
3097
        ast::expr_method_call(*) |
3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111
        ast::expr_rec(*) |
        ast::expr_struct(*) |
        ast::expr_tup(*) |
        ast::expr_if(*) |
        ast::expr_match(*) |
        ast::expr_fn(*) |
        ast::expr_fn_block(*) |
        ast::expr_loop_body(*) |
        ast::expr_do_body(*) |
        ast::expr_block(*) |
        ast::expr_copy(*) |
        ast::expr_unary_move(*) |
        ast::expr_repeat(*) |
        ast::expr_lit(@{node: lit_str(_), _}) |
3112
        ast::expr_vstore(_, ast::expr_vstore_slice) |
3113
        ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3114
        ast::expr_vstore(_, ast::expr_vstore_fixed(_)) |
3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162
        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(*) |
3163
        ast::expr_vstore(_, ast::expr_vstore_box) |
3164
        ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3165
        ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3166 3167 3168
            RvalueDatumExpr
        }

3169 3170
        ast::expr_paren(e) => expr_kind(tcx, method_map, e),

3171 3172 3173 3174 3175
        ast::expr_mac(*) => {
            tcx.sess.span_bug(
                expr.span,
                ~"macro expression remains after expansion");
        }
M
Marijn Haverbeke 已提交
3176 3177 3178
    }
}

3179
fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3180
    match s.node {
B
Brian Anderson 已提交
3181
      ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
B
Brian Anderson 已提交
3182
        return id;
3183
      }
3184
      ast::stmt_mac(*) => fail ~"unexpanded macro in trans"
3185 3186 3187
    }
}

3188
fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3189
    let mut i = 0u;
B
Brian Anderson 已提交
3190 3191
    for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
    return None;
3192 3193
}

3194 3195 3196 3197 3198 3199 3200 3201 3202
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))));
}

3203 3204
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 已提交
3205
      Some(f) => f,
3206
      // Do we only call this when we know the field is legit?
3207
      None => fail (fmt!("get_field: ty doesn't have a field %s",
3208
                         tcx.sess.str_of(id)))
T
Tim Chevalier 已提交
3209 3210 3211
    }
}

3212
fn get_fields(rec_ty:t) -> ~[field] {
3213
    match get(rec_ty).sty {
3214 3215 3216
      ty_rec(fields) => fields,
      // Can we check at the caller?
      _ => fail ~"get_fields: not a record type"
3217 3218 3219
    }
}

B
Brian Anderson 已提交
3220
fn method_idx(id: ast::ident, meths: &[method]) -> Option<uint> {
3221
    let mut i = 0u;
B
Brian Anderson 已提交
3222 3223
    for meths.each |m| { if m.ident == id { return Some(i); } i += 1u; }
    return None;
3224 3225
}

3226 3227 3228 3229 3230 3231
/// 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| {
3232
        match get(ty).sty {
B
Brian Anderson 已提交
3233
          ty_param(p) => {
3234
            rslt.push(p);
3235
          }
B
Brian Anderson 已提交
3236
          _ => ()
3237 3238 3239 3240 3241
        }
    }
    rslt
}

3242
fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3243 3244 3245

    // Returns a vec of all the type variables occurring in `ty`. It may
    // contain duplicates.  (Integral type vars aren't counted.)
3246
    fn vars_in_type(ty: t) -> ~[TyVid] {
3247
        let mut rslt = ~[];
B
Brian Anderson 已提交
3248
        do walk_ty(ty) |ty| {
3249
            match get(ty).sty {
3250
              ty_infer(TyVar(v)) => rslt.push(v),
B
Brian Anderson 已提交
3251 3252
              _ => ()
            }
3253 3254 3255 3256
        }
        rslt
    }

3257
    // Fast path
B
Brian Anderson 已提交
3258
    if !type_needs_infer(rt) { return; }
B
Brian Anderson 已提交
3259

T
Tim Chevalier 已提交
3260
    // Occurs check!
N
Niko Matsakis 已提交
3261
    if vec::contains(vars_in_type(rt), &vid) {
T
Tim Chevalier 已提交
3262 3263 3264
            // 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.
3265
            tcx.sess.span_fatal
3266
                (sp, ~"type inference failed because I \
3267
                     could not find a type\n that's both of the form "
3268
                 + ty_to_str(tcx, mk_var(tcx, vid)) +
3269 3270
                 ~" and of the form " + ty_to_str(tcx, rt) +
                 ~" - such a type would have to be infinitely large.");
3271
    }
T
Tim Chevalier 已提交
3272
}
3273

3274 3275
// Maintains a little union-set tree for inferred modes.  `canon()` returns
// the current head value for `m0`.
B
Brian Anderson 已提交
3276
fn canon<T:Copy cmp::Eq>(tbl: HashMap<ast::node_id, ast::inferable<T>>,
3277
                         +m0: ast::inferable<T>) -> ast::inferable<T> {
3278 3279
    match m0 {
      ast::infer(id) => match tbl.find(id) {
B
Brian Anderson 已提交
3280
        None => m0,
3281 3282
        Some(ref m1) => {
            let cm1 = canon(tbl, (*m1));
3283
            // path compression:
3284
            if cm1 != (*m1) { tbl.insert(id, cm1); }
3285 3286
            cm1
        }
3287
      },
B
Brian Anderson 已提交
3288
      _ => m0
3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300
    }
}

// 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 {
3301
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3302
      ast::infer(_) => {
P
Paul Stansifer 已提交
3303
        cx.sess.bug(fmt!("mode %? was never resolved", m));
3304
      }
B
Brian Anderson 已提交
3305
      ast::expl(m0) => m0
3306 3307 3308
    }
}

3309
fn arg_mode(cx: ctxt, a: arg) -> ast::rmode { resolved_mode(cx, a.mode) }
3310 3311

// Unifies `m1` and `m2`.  Returns unified value or failure code.
3312
fn unify_mode(cx: ctxt, modes: expected_found<ast::mode>)
3313
    -> Result<ast::mode, type_err> {
3314 3315 3316

    let m1 = modes.expected;
    let m2 = modes.found;
3317
    match (canon_mode(cx, m1), canon_mode(cx, m2)) {
B
Brian Anderson 已提交
3318
      (m1, m2) if (m1 == m2) => {
3319
        result::Ok(m1)
3320
      }
E
Erick Tryzelaar 已提交
3321
      (ast::infer(_), ast::infer(id2)) => {
3322
        cx.inferred_modes.insert(id2, m1);
3323
        result::Ok(m1)
3324
      }
B
Brian Anderson 已提交
3325
      (ast::infer(id), m) | (m, ast::infer(id)) => {
3326
        cx.inferred_modes.insert(id, m);
3327
        result::Ok(m1)
3328
      }
E
Erick Tryzelaar 已提交
3329
      (_, _) => {
3330
        result::Err(terr_mode_mismatch(modes))
3331 3332 3333 3334 3335 3336 3337
      }
    }
}

// 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) {
3338
    match canon_mode(cx, m) {
B
Brian Anderson 已提交
3339
      ast::infer(id) => {
3340 3341
        cx.inferred_modes.insert(id, ast::expl(m_def));
      }
B
Brian Anderson 已提交
3342
      ast::expl(_) => ()
3343 3344 3345
    }
}

3346
fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3347
    match get(t).sty {
N
Niko Matsakis 已提交
3348
      ty_nil | ty_bot | ty_bool | ty_int(_) |
M
Michael Sullivan 已提交
3349
      ty_uint(_) | ty_float(_) | ty_estr(_) |
B
Brian Anderson 已提交
3350
      ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
N
Niko Matsakis 已提交
3351 3352 3353
        ty_to_str(cx, t)
      }

P
Paul Stansifer 已提交
3354
      ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3355 3356 3357 3358 3359 3360 3361 3362
      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 已提交
3363
      ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3364
      ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
B
Brian Anderson 已提交
3365
      ty_tup(_) => ~"tuple",
3366 3367
      ty_infer(TyVar(_)) => ~"inferred type",
      ty_infer(IntVar(_)) => ~"integral variable",
3368
      ty_infer(FloatVar(_)) => ~"floating-point variable",
B
Brian Anderson 已提交
3369
      ty_param(_) => ~"type parameter",
3370 3371
      ty_self => ~"self",
      ty_err => ~"type error"
N
Niko Matsakis 已提交
3372 3373 3374
    }
}

N
Niko Matsakis 已提交
3375
fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3376 3377 3378 3379 3380 3381 3382 3383 3384
    /*!
     *
     * 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. */

3385
    fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3386 3387 3388
        match k {
            terr_vec => ~"[]",
            terr_str => ~"str",
3389 3390
            terr_fn => ~"fn",
            terr_trait => ~"trait"
3391
        }
3392 3393
    }

N
Niko Matsakis 已提交
3394
    match *err {
3395 3396 3397 3398 3399 3400 3401
        terr_mismatch => ~"types differ",
        terr_ret_style_mismatch(values) => {
            fn to_str(s: ast::ret_style) -> ~str {
                match s {
                    ast::noreturn => ~"non-returning",
                    ast::return_val => ~"return-by-value"
                }
3402
            }
3403 3404 3405 3406 3407 3408 3409 3410 3411
            fmt!("expected %s function, found %s function",
                 to_str(values.expected),
                 to_str(values.expected))
        }
        terr_purity_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
                 purity_to_str(values.expected),
                 purity_to_str(values.found))
        }
3412 3413 3414 3415 3416
        terr_onceness_mismatch(values) => {
            fmt!("expected %s fn but found %s fn",
                 onceness_to_str(values.expected),
                 onceness_to_str(values.found))
        }
3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474
        terr_proto_mismatch(values) => {
            fmt!("expected %s closure, found %s closure",
                 proto_ty_to_str(cx, values.expected),
                 proto_ty_to_str(cx, values.found))
        }
        terr_mutability => ~"values differ in mutability",
        terr_box_mutability => ~"boxed values differ in mutability",
        terr_vec_mutability => ~"vectors differ in mutability",
        terr_ptr_mutability => ~"pointers differ in mutability",
        terr_ref_mutability => ~"references differ in mutability",
        terr_ty_param_size(values) => {
            fmt!("expected a type with %? type params \
                  but found one with %? type params",
                 values.expected, values.found)
        }
        terr_tuple_size(values) => {
            fmt!("expected a tuple with %? elements \
                  but found one with %? elements",
                 values.expected, values.found)
        }
        terr_record_size(values) => {
            fmt!("expected a record with %? fields \
                  but found one with %? fields",
                 values.expected, values.found)
        }
        terr_record_mutability => {
            ~"record elements differ in mutability"
        }
        terr_record_fields(values) => {
            fmt!("expected a record with field `%s` but found one with field \
                  `%s`",
                 cx.sess.str_of(values.expected),
                 cx.sess.str_of(values.found))
        }
        terr_arg_count => ~"incorrect number of function parameters",
        terr_mode_mismatch(values) => {
            fmt!("expected argument mode %s, but found %s",
                 mode_to_str(values.expected), mode_to_str(values.found))
        }
        terr_regions_does_not_outlive(*) => {
            fmt!("lifetime mismatch")
        }
        terr_regions_not_same(*) => {
            fmt!("lifetimes are not the same")
        }
        terr_regions_no_overlap(*) => {
            fmt!("lifetimes do not intersect")
        }
        terr_regions_insufficiently_polymorphic(br, _) => {
            fmt!("expected bound lifetime parameter %s, \
                  but found concrete lifetime",
                 bound_region_to_str(cx, br))
        }
        terr_regions_overly_polymorphic(br, _) => {
            fmt!("expected concrete lifetime, \
                  but found bound lifetime parameter %s",
                 bound_region_to_str(cx, br))
        }
3475
        terr_vstores_differ(k, ref values) => {
3476 3477
            fmt!("%s storage differs: expected %s but found %s",
                 terr_vstore_kind_to_str(k),
3478 3479
                 vstore_to_str(cx, (*values).expected),
                 vstore_to_str(cx, (*values).found))
3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495
        }
        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"
3496
        }
3497 3498 3499 3500
        terr_no_floating_point_type => {
            ~"couldn't determine an appropriate floating point type for \
              floating point literal"
        }
3501 3502 3503
    }
}

3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520
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, ~"");
        }
3521 3522 3523 3524 3525 3526 3527 3528 3529 3530
        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, ~"");
        }
3531 3532 3533 3534
        _ => {}
    }
}

3535
fn def_has_ty_params(def: ast::def) -> bool {
3536
    match def {
3537
      ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
B
Brian Anderson 已提交
3538 3539
        => true,
      _ => false
3540 3541 3542
    }
}

3543 3544
fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
    cx.trait_method_cache.insert(ast_util::local_def(id), ms);
3545 3546
}

3547
fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3548 3549
    if is_local(id) {
        match cx.items.find(id.node) {
P
Patrick Walton 已提交
3550 3551 3552 3553
            Some(ast_map::node_item(@{
                        node: item_trait(_, _, ref ms),
                        _
                    }, _)) =>
3554
                match ast_util::split_trait_methods((*ms)) {
3555
                   (_, p) => p.map(|method| method.ident)
3556
                },
3557
            _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3558 3559
                                  id))
        }
3560
    } else {
3561
        csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3562 3563 3564
    }
}

3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580
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 {
3581
            ty_trait(def_id, ref substs, _) => {
3582 3583
                result.push(InstantiatedTraitRef {
                    def_id: def_id,
3584
                    tpt: { substs: (*substs), ty: *trait_type }
3585 3586 3587 3588 3589 3590 3591 3592 3593
                });
            }
            _ => cx.sess.bug(~"trait_supertraits: trait ref wasn't a trait")
        }
    }

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

3595
fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
3596
    match cx.trait_method_cache.find(id) {
3597
      // Local traits are supposed to have been added explicitly.
B
Brian Anderson 已提交
3598
      Some(ms) => ms,
3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610
      _ => {
        // 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
      }
3611 3612
    }
}
3613

3614 3615 3616
/*
  Could this return a list of (def_id, substs) pairs?
 */
3617 3618 3619 3620
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 已提交
3621 3622 3623
            ty::ty_trait(did, ref substs, _) => {
                mk_trait(cx, did, (*substs), vstore)
            }
3624 3625 3626 3627
            _ => cx.sess.bug(~"impl_traits: not a trait")
        }
    }

3628
    if id.crate == ast::local_crate {
P
Paul Stansifer 已提交
3629
        debug!("(impl_traits) searching for trait impl %?", id);
3630
        match cx.items.find(id.node) {
B
Brian Anderson 已提交
3631
           Some(ast_map::node_item(@{
3632
                        node: ast::item_impl(_, opt_trait, _, _),
3633
                        _},
B
Brian Anderson 已提交
3634
                    _)) => {
3635

B
Brian Anderson 已提交
3636
               do option::map_default(&opt_trait, ~[]) |trait_ref| {
3637 3638 3639
                       ~[vstoreify(cx,
                                   node_id_to_type(cx, trait_ref.ref_id),
                                   vstore)]
3640
                   }
3641
           }
B
Brian Anderson 已提交
3642
           _ => ~[]
3643
        }
3644
    } else {
3645 3646
        vec::map(csearch::get_impl_traits(cx, id),
                 |x| vstoreify(cx, *x, vstore))
3647 3648 3649
    }
}

B
Brian Anderson 已提交
3650
fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3651
    match get(ty).sty {
3652
      ty_trait(id, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
B
Brian Anderson 已提交
3653
      _ => None
3654 3655 3656
    }
}

3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668
/// 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 {
3669
                ast::item_struct(struct_def, _) => {
3670 3671 3672 3673 3674 3675 3676 3677 3678 3679
                    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")
    }
}

3680
// Enum information
3681 3682 3683 3684 3685 3686 3687 3688 3689 3690
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 已提交
3691

3692 3693
fn substd_enum_variants(cx: ctxt,
                        id: ast::def_id,
3694
                        substs: &substs) -> ~[VariantInfo] {
B
Brian Anderson 已提交
3695 3696
    do vec::map(*enum_variants(cx, id)) |variant_info| {
        let substd_args = vec::map(variant_info.args,
3697
                                   |aty| subst(cx, substs, *aty));
3698

3699
        let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3700

3701 3702
        @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
                      ..**variant_info}
3703 3704 3705
    }
}

3706
fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
P
Paul Stansifer 已提交
3707
    ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3708 3709
}

3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727
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()
    }
}

3728
/* If struct_id names a struct with a dtor, return Some(the dtor's id).
3729
   Otherwise return none. */
3730 3731
fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
    match cx.destructor_for_type.find(struct_id) {
3732
        Some(method_def_id) => return TraitDtor(method_def_id),
3733 3734 3735
        None => {}  // Continue.
    }

3736 3737
    if is_local(struct_id) {
       match cx.items.find(struct_id.node) {
B
Brian Anderson 已提交
3738
           Some(ast_map::node_item(@{
3739
               node: ast::item_struct(@{ dtor: Some(ref dtor), _ }, _),
3740 3741
               _
           }, _)) =>
3742
               LegacyDtor(local_def((*dtor).node.id)),
3743
           _ =>
3744
               NoDtor
3745 3746 3747
       }
    }
    else {
3748
      match csearch::struct_dtor(cx.sess.cstore, struct_id) {
3749 3750 3751
        None => NoDtor,
        Some(did) => LegacyDtor(did),
      }
3752 3753 3754
    }
}

3755 3756
fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
    ty_dtor(cx, struct_id).is_present()
3757 3758
}

3759 3760 3761 3762 3763
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);
3764
        match node {
B
Brian Anderson 已提交
3765
          ast_map::node_item(item, path) => {
3766
            let item_elt = match item.node {
B
Brian Anderson 已提交
3767
              item_mod(_) | item_foreign_mod(_) => {
3768 3769
                ast_map::path_mod(item.ident)
              }
B
Brian Anderson 已提交
3770
              _ => {
3771 3772 3773
                ast_map::path_name(item.ident)
              }
            };
3774
            vec::append_one(*path, item_elt)
3775 3776
          }

B
Brian Anderson 已提交
3777
          ast_map::node_foreign_item(nitem, _, path) => {
3778
            vec::append_one(*path, ast_map::path_name(nitem.ident))
3779 3780
          }

B
Brian Anderson 已提交
3781
          ast_map::node_method(method, _, path) => {
3782
            vec::append_one(*path, ast_map::path_name(method.ident))
3783
          }
B
Brian Anderson 已提交
3784
          ast_map::node_trait_method(trait_method, _, path) => {
3785 3786 3787
            let method = ast_util::trait_method_to_ty_method(*trait_method);
            vec::append_one(*path, ast_map::path_name(method.ident))
          }
3788

3789
          ast_map::node_variant(ref variant, _, path) => {
3790
            vec::append_one(vec::init(*path),
3791
                            ast_map::path_name((*variant).node.name))
3792 3793
          }

B
Brian Anderson 已提交
3794
          ast_map::node_dtor(_, _, _, path) => {
P
Paul Stansifer 已提交
3795 3796
            vec::append_one(*path, ast_map::path_name(
                syntax::parse::token::special_idents::literally_dtor))
T
Tim Chevalier 已提交
3797 3798
          }

3799 3800 3801 3802
          ast_map::node_struct_ctor(_, item, path) => {
            vec::append_one(*path, ast_map::path_name(item.ident))
          }

3803 3804 3805
          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 已提交
3806
            cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3807 3808 3809 3810 3811
          }
        }
    }
}

3812
fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3813
    enum_variants(cx, id).len() == 1
3814 3815
}

3816
fn type_is_empty(cx: ctxt, t: t) -> bool {
3817
    match ty::get(t).sty {
B
Brian Anderson 已提交
3818 3819
       ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
       _ => false
3820 3821 3822
     }
}

3823
fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3824
    match cx.enum_var_cache.find(id) {
B
Brian Anderson 已提交
3825
      Some(variants) => return variants,
B
Brian Anderson 已提交
3826
      _ => { /* fallthrough */ }
3827
    }
3828

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

3889

P
Patrick Walton 已提交
3890
// Returns information about the enum variant with the given ID:
3891
fn enum_variant_with_id(cx: ctxt, enum_id: ast::def_id,
3892
                        variant_id: ast::def_id) -> VariantInfo {
3893
    let variants = enum_variants(cx, enum_id);
3894 3895
    let mut i = 0;
    while i < variants.len() {
B
Brian Anderson 已提交
3896
        let variant = variants[i];
3897
        if variant.id == variant_id { return variant; }
3898
        i += 1;
3899
    }
3900
    cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
3901 3902
}

3903

3904 3905
// 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.
3906
fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
3907
    match cx.tcache.find(did) {
3908
      Some(tpt) => {
3909 3910
        // The item is in this crate. The caller should have added it to the
        // type cache already
3911 3912 3913
        return tpt;
      }
      None => {
3914
        assert did.crate != ast::local_crate;
M
Marijn Haverbeke 已提交
3915 3916
        let tyt = csearch::get_type(cx, did);
        cx.tcache.insert(did, tyt);
B
Brian Anderson 已提交
3917
        return tyt;
M
Marijn Haverbeke 已提交
3918
      }
3919
    }
T
Tim Chevalier 已提交
3920 3921
}

T
Tim Chevalier 已提交
3922
// Look up a field ID, whether or not it's local
3923 3924
// 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 已提交
3925
                     substs: &substs) -> ty::t {
3926

3927
    let t = if id.crate == ast::local_crate {
T
Tim Chevalier 已提交
3928 3929 3930
        node_id_to_type(tcx, id.node)
    }
    else {
3931
        match tcx.tcache.find(id) {
B
Brian Anderson 已提交
3932 3933
           Some(tpt) => tpt.ty,
           None => {
3934
               let tpt = csearch::get_field_type(tcx, struct_id, id);
T
Tim Chevalier 已提交
3935
               tcx.tcache.insert(id, tpt);
3936
               tpt.ty
T
Tim Chevalier 已提交
3937 3938
           }
        }
3939
    };
3940
    subst(tcx, substs, t)
T
Tim Chevalier 已提交
3941 3942
}

3943 3944 3945
// 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] {
3946
  if did.crate == ast::local_crate {
3947
    match cx.items.find(did.node) {
B
Brian Anderson 已提交
3948
       Some(ast_map::node_item(i,_)) => {
3949
         match i.node {
3950 3951
            ast::item_struct(struct_def, _) => {
               struct_field_tys(struct_def.fields)
3952
            }
3953
            _ => cx.sess.bug(~"struct ID bound to non-struct")
T
Tim Chevalier 已提交
3954
         }
T
Tim Chevalier 已提交
3955
       }
3956 3957
       Some(ast_map::node_variant(ref variant, _, _)) => {
          match (*variant).node.kind {
3958
            ast::struct_variant_kind(struct_def) => {
3959
              struct_field_tys(struct_def.fields)
3960 3961 3962 3963 3964 3965 3966
            }
            _ => {
              cx.sess.bug(~"struct ID bound to enum variant that isn't \
                            struct-like")
            }
          }
       }
B
Brian Anderson 已提交
3967
       _ => {
P
Paul Stansifer 已提交
3968
           cx.sess.bug(
3969
               fmt!("struct ID not bound to an item: %s",
P
Paul Stansifer 已提交
3970
                    ast_map::node_id_to_str(cx.items, did.node,
P
Paul Stansifer 已提交
3971
                                            cx.sess.parse_sess.interner)));
3972
       }
T
Tim Chevalier 已提交
3973
    }
T
Tim Chevalier 已提交
3974
        }
3975
  else {
3976
        return csearch::get_struct_fields(cx, did);
T
Tim Chevalier 已提交
3977 3978 3979
    }
}

3980
fn lookup_struct_field(cx: ctxt, parent: ast::def_id, field_id: ast::def_id)
3981
    -> field_ty {
3982
    match vec::find(lookup_struct_fields(cx, parent),
B
Brian Anderson 已提交
3983
                 |f| f.id.node == field_id.node) {
B
Brian Anderson 已提交
3984
        Some(t) => t,
3985
        None => cx.sess.bug(~"struct ID not found in parent's fields")
3986 3987 3988
    }
}

3989
pure fn is_public(f: field_ty) -> bool {
3990 3991 3992 3993 3994
    // XXX: This is wrong.
    match f.vis {
        public | inherited => true,
        private => false
    }
3995 3996
}

3997
fn struct_field_tys(fields: ~[@struct_field]) -> ~[field_ty] {
3998
    let mut rslt = ~[];
3999 4000 4001
    for fields.each |field| {
        match field.node.kind {
            named_field(ident, mutability, visibility) => {
4002 4003 4004 4005
                rslt.push({ident: ident,
                           id: ast_util::local_def(field.node.id),
                           vis: visibility,
                           mutability: mutability});
4006
            }
4007 4008 4009 4010 4011
            unnamed_field => {
                rslt.push({ident:
                    syntax::parse::token::special_idents::unnamed_field,
                           id: ast_util::local_def(field.node.id),
                           vis: ast::public,
4012
                           mutability: ast::struct_immutable});
4013
            }
T
Tim Chevalier 已提交
4014 4015 4016
       }
    }
    rslt
T
Tim Chevalier 已提交
4017 4018
}

4019 4020
// Return a list of fields corresponding to the struct's items
// (as if the struct was a record). trans uses this
4021
// Takes a list of substs with which to instantiate field types
4022 4023 4024
// 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.
4025
fn struct_mutable_fields(cx:ctxt,
N
Niko Matsakis 已提交
4026 4027
                                 did: ast::def_id,
                                 substs: &substs) -> ~[field] {
4028
    struct_item_fields(cx, did, substs, |_mt| m_mutbl)
4029 4030
}

4031
// Same as struct_mutable_fields, but doesn't change
4032
// mutability.
4033
fn struct_fields(cx:ctxt,
N
Niko Matsakis 已提交
4034 4035
                         did: ast::def_id,
                         substs: &substs) -> ~[field] {
4036 4037 4038
    struct_item_fields(cx, did, substs, |mt| match mt {
      struct_mutable => m_mutbl,
        struct_immutable => m_imm })
4039 4040 4041
}


4042
fn struct_item_fields(cx:ctxt,
N
Niko Matsakis 已提交
4043 4044
                     did: ast::def_id,
                     substs: &substs,
4045
                     frob_mutability: fn(struct_mutability) -> mutability)
4046 4047
    -> ~[field] {
    let mut rslt = ~[];
4048
    for lookup_struct_fields(cx, did).each |f| {
G
Graydon Hoare 已提交
4049
       // consider all instance vars mut, because the
T
Tim Chevalier 已提交
4050
       // constructor may mutate all vars
4051
       rslt.push({ident: f.ident, mt:
4052
               {ty: lookup_field_type(cx, did, f.id, substs),
4053
                    mutbl: frob_mutability(f.mutability)}});
T
Tim Chevalier 已提交
4054 4055 4056 4057
    }
    rslt
}

4058
fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
M
Marijn Haverbeke 已提交
4059 4060 4061 4062
    const tycat_other: int = 0;
    const tycat_bool: int = 1;
    const tycat_int: int = 2;
    const tycat_float: int = 3;
M
Michael Sullivan 已提交
4063 4064
    const tycat_struct: int = 4;
    const tycat_bot: int = 5;
M
Marijn Haverbeke 已提交
4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075

    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 {
4076
        match op {
B
Brian Anderson 已提交
4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094
          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 已提交
4095 4096 4097
        }
    }

4098
    fn tycat(ty: t) -> int {
4099
        match get(ty).sty {
B
Brian Anderson 已提交
4100
          ty_bool => tycat_bool,
4101
          ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4102
          ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
B
Brian Anderson 已提交
4103 4104 4105
          ty_rec(_) | ty_tup(_) | ty_enum(_, _) => tycat_struct,
          ty_bot => tycat_bot,
          _ => tycat_other
M
Marijn Haverbeke 已提交
4106 4107 4108 4109 4110
        }
    }

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

4112
    let tbl = ~[
4113 4114 4115
    /*.          add,     shift,   bit
      .             sub,     rel,     logic
      .                mult,    eq,         */
4116
    /*other*/   ~[f, f, f, f, f, f, f, f],
4117 4118 4119
    /*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],
4120 4121
    /*bot*/     ~[f, f, f, f, f, f, f, f],
    /*struct*/  ~[t, t, t, t, f, f, t, t]];
B
Brian Anderson 已提交
4122

B
Brian Anderson 已提交
4123
    return tbl[tycat(ty)][opcat(op)];
4124 4125
}

4126
fn ty_params_to_tys(tcx: ty::ctxt, tps: ~[ast::ty_param]) -> ~[t] {
B
Brian Anderson 已提交
4127
    vec::from_fn(tps.len(), |i| {
4128 4129 4130
                ty::mk_param(tcx, i, ast_util::local_def(tps[i].id))
        })
}
4131

4132
/// Returns an equivalent type with all the typedefs and self regions removed.
4133
fn normalize_ty(cx: ctxt, t: t) -> t {
4134 4135 4136 4137 4138 4139 4140 4141 4142 4143
    fn normalize_mt(cx: ctxt, mt: mt) -> mt {
        { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
    }
    fn normalize_vstore(vstore: vstore) -> vstore {
        match vstore {
            vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
            vstore_slice(_) => vstore_slice(re_static)
        }
    }

4144
    match cx.normalized_cache.find(t) {
B
Brian Anderson 已提交
4145 4146
      Some(t) => return t,
      None => ()
B
Brian Anderson 已提交
4147 4148
    }

4149
    let t = match get(t).sty {
4150 4151 4152 4153
        ty_evec(mt, vstore) =>
            // This type has a vstore. Get rid of it
            mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),

4154 4155 4156 4157
        ty_estr(vstore) =>
            // This type has a vstore. Get rid of it
            mk_estr(cx, normalize_vstore(vstore)),

E
Erick Tryzelaar 已提交
4158
        ty_rptr(_, mt) =>
4159
            // This type has a region. Get rid of it
4160 4161
            mk_rptr(cx, re_static, normalize_mt(cx, mt)),

4162 4163
        ty_fn(ref fn_ty) => {
            mk_fn(cx, FnTyBase {
4164 4165 4166 4167
                meta: FnMeta {
                    region: ty::re_static,
                    ..fn_ty.meta
                },
4168 4169 4170
                sig: fn_ty.sig
            })
        }
4171

4172 4173
        ty_enum(did, ref r) =>
            match (*r).self_r {
B
Brian Anderson 已提交
4174
                Some(_) =>
4175
                    // Use re_static since trans doesn't care about regions
E
Eric Holk 已提交
4176
                    mk_enum(cx, did,
4177 4178
                     {self_r: Some(ty::re_static),
                      self_ty: None,
4179
                      tps: (*r).tps}),
B
Brian Anderson 已提交
4180
                None =>
4181 4182 4183
                    t
            },

4184
        ty_struct(did, ref r) =>
4185
            match (*r).self_r {
B
Brian Anderson 已提交
4186
              Some(_) =>
4187
                // Ditto.
4188 4189 4190
                mk_struct(cx, did, {self_r: Some(ty::re_static),
                                    self_ty: None,
                                    tps: (*r).tps}),
B
Brian Anderson 已提交
4191
              None =>
4192 4193 4194 4195 4196
                t
            },

        _ =>
            t
4197 4198
    };

4199
    let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
B
Brian Anderson 已提交
4200 4201
    let t_norm = mk_t(cx, sty);
    cx.normalized_cache.insert(t, t_norm);
B
Brian Anderson 已提交
4202
    return t_norm;
4203 4204
}

4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221
// 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;
        }
4222 4223 4224 4225 4226 4227 4228
        const_eval::const_bool(_) => {
            tcx.sess.span_err(span,
                              ~"expected signed or unsigned integer for \
                                repeat count but found boolean");
            return 0;
        }

4229 4230 4231
    }
}

4232 4233 4234
// Determine what purity to check a nested function under
pure fn determine_inherited_purity(parent_purity: ast::purity,
                                   child_purity: ast::purity,
4235
                                   child_proto: ast::Proto) -> ast::purity {
4236 4237 4238
    // 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
4239 4240 4241 4242
    match child_proto {
        ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity,
        _ => child_purity
    }
4243 4244
}

4245 4246 4247 4248 4249 4250 4251 4252 4253 4254
// 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 已提交
4255
            ty::bound_copy | ty::bound_owned |
B
Brian Anderson 已提交
4256
            ty::bound_const | ty::bound_durable => {
4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302
                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;
}

4303
impl mt : cmp::Eq {
4304 4305 4306 4307
    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) }
4308
}
4309

4310
impl arg : cmp::Eq {
4311 4312 4313 4314
    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) }
4315
}
4316

4317
impl field : cmp::Eq {
4318 4319 4320 4321
    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) }
4322
}
4323

4324
impl vstore : cmp::Eq {
4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353
    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) }
4354
}
4355

4356
impl FnMeta : cmp::Eq {
4357 4358 4359 4360 4361 4362 4363
    pure fn eq(&self, other: &FnMeta) -> bool {
        (*self).purity == (*other).purity &&
        (*self).proto == (*other).proto &&
        (*self).bounds == (*other).bounds &&
        (*self).ret_style == (*other).ret_style
    }
    pure fn ne(&self, other: &FnMeta) -> bool { !(*self).eq(other) }
4364
}
4365

4366
impl FnSig : cmp::Eq {
4367 4368 4369 4370 4371
    pure fn eq(&self, other: &FnSig) -> bool {
        (*self).inputs == (*other).inputs &&
        (*self).output == (*other).output
    }
    pure fn ne(&self, other: &FnSig) -> bool { !(*self).eq(other) }
4372
}
4373

4374
impl<M: cmp::Eq> FnTyBase<M> : cmp::Eq {
4375 4376 4377 4378
    pure fn eq(&self, other: &FnTyBase<M>) -> bool {
        (*self).meta == (*other).meta && (*self).sig == (*other).sig
    }
    pure fn ne(&self, other: &FnTyBase<M>) -> bool { !(*self).eq(other) }
4379
}
4380

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

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

4391
impl FloatVid : cmp::Eq {
4392 4393
    pure fn eq(&self, other: &FloatVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &FloatVid) -> bool { *(*self) != *(*other) }
4394 4395
}

4396
impl FnVid : cmp::Eq {
4397 4398
    pure fn eq(&self, other: &FnVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &FnVid) -> bool { *(*self) != *(*other) }
4399
}
4400

4401
impl RegionVid : cmp::Eq {
4402 4403
    pure fn eq(&self, other: &RegionVid) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &RegionVid) -> bool { *(*self) != *(*other) }
4404
}
4405

4406
impl Region : cmp::Eq {
4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441
    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) }
4442
}
4443

4444
impl bound_region : cmp::Eq {
4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473
    pure fn eq(&self, other: &bound_region) -> bool {
        match (*self) {
            br_self => {
                match (*other) {
                    br_self => true,
                    _ => false
                }
            }
            br_anon(e0a) => {
                match (*other) {
                    br_anon(e0b) => e0a == e0b,
                    _ => false
                }
            }
            br_named(e0a) => {
                match (*other) {
                    br_named(e0b) => e0a == e0b,
                    _ => false
                }
            }
            br_cap_avoid(e0a, e1a) => {
                match (*other) {
                    br_cap_avoid(e0b, e1b) => e0a == e0b && e1a == e1b,
                    _ => false
                }
            }
        }
    }
    pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) }
4474
}
4475

4476
impl substs : cmp::Eq {
4477 4478 4479 4480 4481 4482
    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) }
4483
}
4484

4485
impl InferTy : cmp::Eq {
4486 4487 4488 4489
    pure fn eq(&self, other: &InferTy) -> bool {
        (*self).to_hash() == (*other).to_hash()
    }
    pure fn ne(&self, other: &InferTy) -> bool { !(*self).eq(other) }
4490
}
4491

4492
impl sty : cmp::Eq {
4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536
    pure fn eq(&self, other: &sty) -> bool {
        match (*self) {
            ty_nil => {
                match (*other) {
                    ty_nil => true,
                    _ => false
                }
            }
            ty_bot => {
                match (*other) {
                    ty_bot => true,
                    _ => false
                }
            }
            ty_bool => {
                match (*other) {
                    ty_bool => true,
                    _ => false
                }
            }
            ty_int(e0a) => {
                match (*other) {
                    ty_int(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_uint(e0a) => {
                match (*other) {
                    ty_uint(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_float(e0a) => {
                match (*other) {
                    ty_float(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_estr(e0a) => {
                match (*other) {
                    ty_estr(e0b) => e0a == e0b,
                    _ => false
                }
            }
4537
            ty_enum(e0a, ref e1a) => {
4538
                match (*other) {
4539
                    ty_enum(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578
                    _ => false
                }
            }
            ty_box(e0a) => {
                match (*other) {
                    ty_box(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_uniq(e0a) => {
                match (*other) {
                    ty_uniq(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_evec(e0a, e1a) => {
                match (*other) {
                    ty_evec(e0b, e1b) => e0a == e0b && e1a == e1b,
                    _ => false
                }
            }
            ty_ptr(e0a) => {
                match (*other) {
                    ty_ptr(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_rptr(e0a, e1a) => {
                match (*other) {
                    ty_rptr(e0b, e1b) => e0a == e0b && e1a == e1b,
                    _ => false
                }
            }
            ty_rec(e0a) => {
                match (*other) {
                    ty_rec(e0b) => e0a == e0b,
                    _ => false
                }
            }
4579
            ty_fn(ref e0a) => {
4580
                match (*other) {
4581
                    ty_fn(ref e0b) => (*e0a) == (*e0b),
4582 4583 4584
                    _ => false
                }
            }
4585
            ty_trait(e0a, ref e1a, e2a) => {
4586
                match (*other) {
4587 4588
                    ty_trait(e0b, ref e1b, e2b) =>
                        e0a == e0b && (*e1a) == (*e1b) && e2a == e2b,
4589 4590 4591
                    _ => false
                }
            }
4592
            ty_struct(e0a, ref e1a) => {
4593
                match (*other) {
4594
                    ty_struct(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609
                    _ => false
                }
            }
            ty_tup(e0a) => {
                match (*other) {
                    ty_tup(e0b) => e0a == e0b,
                    _ => false
                }
            }
            ty_infer(e0a) => {
                match (*other) {
                    ty_infer(e0b) => e0a == e0b,
                    _ => false
                }
            }
4610 4611 4612 4613 4614 4615
            ty_err => {
                match (*other) {
                    ty_err => true,
                    _ => false
                }
            }
4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654
            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) }
4655
}
4656

4657
impl param_bound : cmp::Eq {
4658 4659 4660 4661 4662 4663 4664 4665
    pure fn eq(&self, other: &param_bound) -> bool {
        match (*self) {
            bound_copy => {
                match (*other) {
                    bound_copy => true,
                    _ => false
                }
            }
B
Brian Anderson 已提交
4666
            bound_durable => {
4667
                match (*other) {
B
Brian Anderson 已提交
4668
                    bound_durable => true,
4669 4670 4671
                    _ => false
                }
            }
B
Brian Anderson 已提交
4672
            bound_owned => {
4673
                match (*other) {
B
Brian Anderson 已提交
4674
                    bound_owned => true,
4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691
                    _ => false
                }
            }
            bound_const => {
                match (*other) {
                    bound_const => true,
                    _ => false
                }
            }
            bound_trait(e0a) => {
                match (*other) {
                    bound_trait(e0b) => e0a == e0b,
                    _ => false
                }
            }
        }
    }
B
Brian Anderson 已提交
4692
    pure fn ne(&self, other: &param_bound) -> bool { !self.eq(other) }
4693
}
4694

4695
impl Kind : cmp::Eq {
4696 4697
    pure fn eq(&self, other: &Kind) -> bool { *(*self) == *(*other) }
    pure fn ne(&self, other: &Kind) -> bool { *(*self) != *(*other) }
4698
}
4699

4700

4701 4702 4703 4704 4705 4706 4707
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End: