ty.rs 91.7 KB
Newer Older
1
import std::int;
2 3 4
import std::str;
import std::uint;
import std::vec;
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
import std::box;
import std::ufind;
import std::map;
import std::map::hashmap;
import std::option;
import std::option::none;
import std::option::some;

import driver::session;
import front::ast;
import front::ast::mutability;
import front::creader;
import middle::metadata;
import util::common;

import util::common::ty_u8;
import util::common::ty_u16;
import util::common::ty_u32;
import util::common::ty_u64;

import util::common::ty_i8;
import util::common::ty_i16;
import util::common::ty_i32;
import util::common::ty_i64;

import util::common::ty_f32;
import util::common::ty_f64;

import util::common::new_def_hash;
import util::common::span;
35
import middle::tstate::ann::ts_ann;
36

37 38
import util::interner;

39 40
// Data types

41 42 43 44 45 46 47
tag mode {
    mo_val;
    mo_alias;
    mo_either;
}

type arg = rec(mode mode, t ty);
48 49 50
type field = rec(ast::ident ident, mt mt);
type method = rec(ast::proto proto,
                  ast::ident ident,
51
                  vec[arg] inputs,
52
                  t output);
53

54
type mt = rec(t ty, ast::mutability mut);
55

56 57
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
58
type creader_cache = hashmap[tup(int,uint,uint),ty::t];
59
type ctxt = rec(@type_store ts,
60 61
                session::session sess,
                resolve::def_map def_map,
62 63
                node_type_table node_types,
                type_cache tcache,
64 65
                creader_cache rcache,
                hashmap[t,str] short_names_cache);
66
type ty_ctxt = ctxt;    // Needed for disambiguation from unify::ctxt.
67

68 69
// Convert from method type to function type.  Pretty easy; we just drop
// 'ident'.
70
fn method_ty_to_fn_ty(&ctxt cx, method m) -> t {
71
    ret mk_fn(cx, m.proto, m.inputs, m.output);
72 73
}

74
// Never construct these manually. These are interned.
75 76
//
// TODO: It'd be really nice to be able to hide this definition from the
77
// outside world, to enforce the above invariants.
78
type raw_t = rec(sty struct,
79
                 option::t[str] cname,
80 81 82 83 84
                 uint hash,
                 bool has_params,
                 bool has_bound_params,
                 bool has_vars,
                 bool has_locals);
85 86

type t = uint;
87

88
// NB: If you change this, you'll probably want to change the corresponding
89
// AST structure in front/ast::rs as well.
90 91
tag sty {
    ty_nil;
92
    ty_bot;
93 94
    ty_bool;
    ty_int;
95
    ty_float;
96
    ty_uint;
97
    ty_machine(util::common::ty_mach);
98 99
    ty_char;
    ty_str;
100
    ty_tag(ast::def_id, vec[t]);
101 102
    ty_box(mt);
    ty_vec(mt);
103 104
    ty_port(t);
    ty_chan(t);
105
    ty_task;
106
    ty_tup(vec[mt]);
107
    ty_rec(vec[field]);
108 109
    ty_fn(ast::proto, vec[arg], t);
    ty_native_fn(ast::native_abi, vec[arg], t);
110 111
    ty_obj(vec[method]);
    ty_var(int);                                    // ephemeral type var
112
    ty_local(ast::def_id);                           // type of a local var
113
    ty_param(uint);                                 // fn/tag type param
114
    ty_bound_param(uint);                           // bound param, only paths
G
Graydon Hoare 已提交
115
    ty_type;
116
    ty_native;
117
    // TODO: ty_fn_arg(t), for a possibly-aliased function argument
118 119
}

120 121 122
// Data structures used in type unification

type unify_handler = obj {
123
    fn resolve_local(ast::def_id id) -> option::t[t];
124 125
    fn record_local(ast::def_id id, t ty);  // TODO: -> unify::result
    fn record_param(uint index, t binding) -> unify::result;
126 127 128 129
};

tag type_err {
    terr_mismatch;
130 131
    terr_box_mutability;
    terr_vec_mutability;
132 133 134 135
    terr_tuple_size(uint, uint);
    terr_tuple_mutability;
    terr_record_size(uint, uint);
    terr_record_mutability;
136
    terr_record_fields(ast::ident,ast::ident);
G
Graydon Hoare 已提交
137
    terr_meth_count;
138
    terr_obj_meths(ast::ident,ast::ident);
139 140 141
    terr_arg_count;
}

142

143
type ty_param_count_and_ty = tup(uint, t);
144
type type_cache = hashmap[ast::def_id,ty_param_count_and_ty];
145

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
const uint idx_nil      = 0u;
const uint idx_bool     = 1u;
const uint idx_int      = 2u;
const uint idx_float    = 3u;
const uint idx_uint     = 4u;
const uint idx_i8       = 5u;
const uint idx_i16      = 6u;
const uint idx_i32      = 7u;
const uint idx_i64      = 8u;
const uint idx_u8       = 9u;
const uint idx_u16      = 10u;
const uint idx_u32      = 11u;
const uint idx_u64      = 12u;
const uint idx_f32      = 13u;
const uint idx_f64      = 14u;
const uint idx_char     = 15u;
const uint idx_str      = 16u;
const uint idx_task     = 17u;
const uint idx_native   = 18u;
const uint idx_type     = 19u;
166 167
const uint idx_bot      = 20u;
const uint idx_first_others = 21u;
168

169
type type_store = interner::interner[raw_t];
170

171
type ty_param_substs_opt_and_ty = tup(option::t[vec[ty::t]], ty::t);
172 173
type node_type_table =
    @mutable vec[mutable option::t[ty::ty_param_substs_opt_and_ty]];
174

P
Patrick Walton 已提交
175
fn mk_type_store() -> @type_store {
176
    auto ts = @interner::mk_interner[raw_t](hash_raw_ty, eq_raw_ty);
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

    intern(ts, ty_nil, none[str]);
    intern(ts, ty_bool, none[str]);
    intern(ts, ty_int, none[str]);
    intern(ts, ty_float, none[str]);
    intern(ts, ty_uint, none[str]);
    intern(ts, ty_machine(ty_i8), none[str]);
    intern(ts, ty_machine(ty_i16), none[str]);
    intern(ts, ty_machine(ty_i32), none[str]);
    intern(ts, ty_machine(ty_i64), none[str]);
    intern(ts, ty_machine(ty_u8), none[str]);
    intern(ts, ty_machine(ty_u16), none[str]);
    intern(ts, ty_machine(ty_u32), none[str]);
    intern(ts, ty_machine(ty_u64), none[str]);
    intern(ts, ty_machine(ty_f32), none[str]);
    intern(ts, ty_machine(ty_f64), none[str]);
    intern(ts, ty_char, none[str]);
    intern(ts, ty_str, none[str]);
    intern(ts, ty_task, none[str]);
    intern(ts, ty_native, none[str]);
    intern(ts, ty_type, none[str]);
198
    intern(ts, ty_bot, none[str]);
199

200
    assert vec::len(ts.vect) == idx_first_others;
201 202

    ret ts;
203 204
}

205 206 207 208 209 210 211 212 213 214 215 216
fn mk_rcache() -> creader_cache {
    fn hash_cache_entry(&tup(int,uint,uint) k) -> uint {
        ret (k._0 as uint) + k._1 + k._2;
    }
    fn eq_cache_entries(&tup(int,uint,uint) a,
                        &tup(int,uint,uint) b) -> bool {
        ret a._0 == b._0 &&
            a._1 == b._1 &&
            a._2 == b._2;
    }
    auto h = hash_cache_entry;
    auto e = eq_cache_entries;
217
    ret map::mk_hashmap[tup(int,uint,uint),t](h, e);
218
}
219

220
fn mk_ctxt(session::session s, resolve::def_map dm) -> ctxt {
221 222 223 224 225 226 227 228

    let vec[mutable option::t[ty::ty_param_substs_opt_and_ty]] ntt_sub =
        [mutable];
    let node_type_table ntt = @mutable ntt_sub;

    auto tcache =
        common::new_def_hash[ty::ty_param_count_and_ty]();

229 230
    ret rec(ts = mk_type_store(),
            sess = s,
231
            def_map = dm,
232 233
            node_types = ntt,
            tcache = tcache,
234 235
            rcache = mk_rcache(),
            short_names_cache =
236
                map::mk_hashmap[ty::t,str](ty::hash_ty, ty::eq_ty));
237
}
238 239


240 241
// Type constructors

242
fn mk_raw_ty(&@type_store ts, &sty st, &option::t[str] cname) -> raw_t {
243
    auto h = hash_type_info(st, cname);
244 245 246 247 248 249

    let bool has_params = false;
    let bool has_bound_params = false;
    let bool has_vars = false;
    let bool has_locals = false;

250 251
    fn derive_flags_t(@type_store ts,
                      &mutable bool has_params,
252 253 254 255
                      &mutable bool has_bound_params,
                      &mutable bool has_vars,
                      &mutable bool has_locals,
                      &t tt) {
256
        auto rt = interner::get[raw_t](*ts, tt);
257 258 259 260
        has_params = has_params || rt.has_params;
        has_bound_params = has_bound_params || rt.has_bound_params;
        has_vars = has_vars || rt.has_vars;
        has_locals = has_locals || rt.has_locals;
261 262
    }

263 264
    fn derive_flags_mt(@type_store ts,
                       &mutable bool has_params,
265 266 267 268
                       &mutable bool has_bound_params,
                       &mutable bool has_vars,
                       &mutable bool has_locals,
                       &mt m) {
269
        derive_flags_t(ts, has_params, has_bound_params,
270 271 272 273
                       has_vars, has_locals, m.ty);
    }


274 275
    fn derive_flags_arg(@type_store ts,
                        &mutable bool has_params,
276 277 278 279
                        &mutable bool has_bound_params,
                        &mutable bool has_vars,
                        &mutable bool has_locals,
                        &arg a) {
280
        derive_flags_t(ts, has_params, has_bound_params,
281 282 283
                       has_vars, has_locals, a.ty);
    }

284 285
    fn derive_flags_sig(@type_store ts,
                        &mutable bool has_params,
286 287 288 289 290 291
                        &mutable bool has_bound_params,
                        &mutable bool has_vars,
                        &mutable bool has_locals,
                        &vec[arg] args,
                        &t tt) {
        for (arg a in args) {
292
            derive_flags_arg(ts, has_params, has_bound_params,
293 294
                             has_vars, has_locals, a);
        }
295
        derive_flags_t(ts, has_params, has_bound_params,
296 297 298 299 300 301 302 303 304 305
                       has_vars, has_locals, tt);
    }

    alt (st) {
        case (ty_param(_)) { has_params = true; }
        case (ty_bound_param(_)) { has_bound_params = true; }
        case (ty_var(_)) { has_vars = true; }
        case (ty_local(_)) { has_locals = true; }
        case (ty_tag(_, ?tys)) {
            for (t tt in tys) {
306
                derive_flags_t(ts, has_params, has_bound_params,
307 308 309 310
                               has_vars, has_locals, tt);
            }
        }
        case (ty_box(?m)) {
311
            derive_flags_mt(ts, has_params, has_bound_params,
312 313 314 315
                            has_vars, has_locals, m);
        }

        case (ty_vec(?m)) {
316
            derive_flags_mt(ts, has_params, has_bound_params,
317 318 319 320
                            has_vars, has_locals, m);
        }

        case (ty_port(?tt)) {
321
            derive_flags_t(ts, has_params, has_bound_params,
322 323 324 325
                           has_vars, has_locals, tt);
        }

        case (ty_chan(?tt)) {
326
            derive_flags_t(ts, has_params, has_bound_params,
327 328 329 330 331
                           has_vars, has_locals, tt);
        }

        case (ty_tup(?mts)) {
            for (mt m in mts) {
332
                derive_flags_mt(ts, has_params, has_bound_params,
333 334 335 336 337 338
                                has_vars, has_locals, m);
            }
        }

        case (ty_rec(?flds)) {
            for (field f in flds) {
339
                derive_flags_mt(ts, has_params, has_bound_params,
340 341 342 343 344
                                has_vars, has_locals, f.mt);
            }
        }

        case (ty_fn(_, ?args, ?tt)) {
345
            derive_flags_sig(ts, has_params, has_bound_params,
346 347 348 349
                             has_vars, has_locals, args, tt);
        }

        case (ty_native_fn(_, ?args, ?tt)) {
350
            derive_flags_sig(ts, has_params, has_bound_params,
351 352 353 354 355
                             has_vars, has_locals, args, tt);
        }

        case (ty_obj(?meths)) {
            for (method m in meths) {
356
                derive_flags_sig(ts, has_params, has_bound_params,
357 358 359 360 361 362 363
                                 has_vars, has_locals,
                                 m.inputs, m.output);
            }
        }
        case (_) { }
    }

364 365 366 367 368 369 370
    ret rec(struct=st, cname=cname, hash=h,
            has_params = has_params,
            has_bound_params = has_bound_params,
            has_vars = has_vars,
            has_locals = has_locals);
}

371
fn intern(&@type_store ts, &sty st, &option::t[str] cname) {
372
    interner::intern[raw_t](*ts, mk_raw_ty(ts, st, cname));
373
}
P
Patrick Walton 已提交
374

375
fn gen_ty_full(&ctxt cx, &sty st, &option::t[str] cname) -> t {
376
    auto raw_type = mk_raw_ty(cx.ts, st, cname);
377
    ret interner::intern[raw_t](*cx.ts, raw_type);
P
Patrick Walton 已提交
378 379
}

380 381
// These are private constructors to this module. External users should always
// use the mk_foo() functions below.
382
fn gen_ty(&ctxt cx, &sty st) -> t {
383 384 385
    ret gen_ty_full(cx, st, none[str]);
}

386
fn mk_nil(&ctxt cx) -> t          { ret idx_nil; }
387
fn mk_bot(&ctxt cx) -> t          { ret idx_bot; }
388 389 390 391
fn mk_bool(&ctxt cx) -> t         { ret idx_bool; }
fn mk_int(&ctxt cx) -> t          { ret idx_int; }
fn mk_float(&ctxt cx) -> t        { ret idx_float; }
fn mk_uint(&ctxt cx) -> t         { ret idx_uint; }
392

393
fn mk_mach(&ctxt cx, &util::common::ty_mach tm) -> t {
394
    alt (tm) {
395 396 397 398 399 400 401 402 403 404 405 406
        case (ty_u8)  { ret idx_u8; }
        case (ty_u16) { ret idx_u16; }
        case (ty_u32) { ret idx_u32; }
        case (ty_u64) { ret idx_u64; }

        case (ty_i8)  { ret idx_i8; }
        case (ty_i16) { ret idx_i16; }
        case (ty_i32) { ret idx_i32; }
        case (ty_i64) { ret idx_i64; }

        case (ty_f32) { ret idx_f32; }
        case (ty_f64) { ret idx_f64; }
407 408
    }
    fail;
409 410
}

411 412
fn mk_char(&ctxt cx) -> t    { ret idx_char; }
fn mk_str(&ctxt cx) -> t     { ret idx_str; }
413

414
fn mk_tag(&ctxt cx, &ast::def_id did, &vec[t] tys) -> t {
415
    ret gen_ty(cx, ty_tag(did, tys));
416
}
417

418
fn mk_box(&ctxt cx, &mt tm) -> t {
419
    ret gen_ty(cx, ty_box(tm));
420 421
}

422
fn mk_imm_box(&ctxt cx, &t ty) -> t {
423
    ret mk_box(cx, rec(ty=ty, mut=ast::imm));
424 425
}

426
fn mk_vec(&ctxt cx, &mt tm) -> t  { ret gen_ty(cx, ty_vec(tm)); }
427 428 429 430 431

fn mk_imm_vec(&ctxt cx, &t typ) -> t {
    ret gen_ty(cx, ty_vec(rec(ty=typ, mut=ast::imm)));
}

432 433 434
fn mk_port(&ctxt cx, &t ty) -> t  { ret gen_ty(cx, ty_port(ty)); }
fn mk_chan(&ctxt cx, &t ty) -> t  { ret gen_ty(cx, ty_chan(ty)); }
fn mk_task(&ctxt cx) -> t        { ret gen_ty(cx, ty_task); }
435

436
fn mk_tup(&ctxt cx, &vec[mt] tms) -> t { ret gen_ty(cx, ty_tup(tms)); }
437

438
fn mk_imm_tup(&ctxt cx, &vec[t] tys) -> t {
439
    // TODO: map
440
    let vec[ty::mt] mts = [];
441
    for (t typ in tys) {
442
        mts += [rec(ty=typ, mut=ast::imm)];
443
    }
444
    ret mk_tup(cx, mts);
445 446
}

447
fn mk_rec(&ctxt cx, &vec[field] fs) -> t { ret gen_ty(cx, ty_rec(fs)); }
448

449
fn mk_fn(&ctxt cx, &ast::proto proto, &vec[arg] args, &t ty) -> t {
450
    ret gen_ty(cx, ty_fn(proto, args, ty));
451 452
}

453
fn mk_native_fn(&ctxt cx, &ast::native_abi abi, &vec[arg] args, &t ty) -> t {
454
    ret gen_ty(cx, ty_native_fn(abi, args, ty));
455
}
456

457
fn mk_obj(&ctxt cx, &vec[method] meths) -> t {
458
    ret gen_ty(cx, ty_obj(meths));
459 460
}

461
fn mk_var(&ctxt cx, int v) -> t {
462
    ret gen_ty(cx, ty_var(v));
463
}
464

465
fn mk_local(&ctxt cx, ast::def_id did) -> t {
466
    ret gen_ty(cx, ty_local(did));
467 468
}

469
fn mk_param(&ctxt cx, uint n) -> t {
470
    ret gen_ty(cx, ty_param(n));
471 472
}

473
fn mk_bound_param(&ctxt cx, uint n) -> t {
474
    ret gen_ty(cx, ty_bound_param(n));
475 476
}

477 478
fn mk_type(&ctxt cx) -> t    { ret idx_type; }
fn mk_native(&ctxt cx) -> t  { ret idx_native; }
479 480


481
// Returns the one-level-deep type structure of the given type.
482 483 484
fn struct(&ctxt cx, &t typ) -> sty {
    ret interner::get[raw_t](*cx.ts, typ).struct;
}
485

486
// Returns the canonical name of the given type.
487 488 489
fn cname(&ctxt cx, &t typ) -> option::t[str] {
    ret interner::get[raw_t](*cx.ts, typ).cname;
}
490

491

492 493
// Stringification

494
fn path_to_str(&ast::path pth) -> str {
495 496
    auto result = str::connect(pth.node.idents,  "::");
    if (vec::len[@ast::ty](pth.node.types) > 0u) {
497
        auto f = pretty::pprust::ty_to_str;
498
        result += "[";
499
        result += str::connect(vec::map(f, pth.node.types), ",");
500 501 502 503 504
        result += "]";
    }
    ret result;
}

505
fn ty_to_str(&ctxt cx, &t typ) -> str {
506

507
    fn fn_input_to_str(&ctxt cx, &rec(mode mode, t ty) input) -> str {
508
        auto s;
509 510 511 512
        alt (input.mode) {
            case (mo_val) { s = ""; }
            case (mo_alias) { s = "&"; }
            case (mo_either) { s = "?"; }
513 514
        }

515
        ret s + ty_to_str(cx, input.ty);
516 517
    }

518
    fn fn_to_str(&ctxt cx,
519 520
                 ast::proto proto,
                 option::t[ast::ident] ident,
521
                 vec[arg] inputs, t output) -> str {
522
            auto f = bind fn_input_to_str(cx, _);
523 524 525

            auto s;
            alt (proto) {
526
                case (ast::proto_iter) {
527 528
                    s = "iter";
                }
529
                case (ast::proto_fn) {
530 531
                    s = "fn";
                }
532
            }
533

534
            alt (ident) {
535
                case (some[ast::ident](?i)) {
536 537 538 539 540 541 542
                    s += " ";
                    s += i;
                }
                case (_) { }
            }

            s += "(";
543
            s += str::connect(vec::map[arg,str](f, inputs), ", ");
544 545
            s += ")";

546 547
            if (struct(cx, output) != ty_nil) {
                s += " -> " + ty_to_str(cx, output);
548 549 550 551
            }
            ret s;
    }

552
    fn method_to_str(&ctxt cx, &method m) -> str {
553
        ret fn_to_str(cx, m.proto, some[ast::ident](m.ident),
554
                      m.inputs, m.output) + ";";
555 556
    }

557
    fn field_to_str(&ctxt cx, &field f) -> str {
558
        ret mt_to_str(cx, f.mt) + " " + f.ident;
559 560
    }

561
    fn mt_to_str(&ctxt cx, &mt m) -> str {
562 563
        auto mstr;
        alt (m.mut) {
564 565 566
            case (ast::mut)       { mstr = "mutable "; }
            case (ast::imm)       { mstr = "";         }
            case (ast::maybe_mut) { mstr = "mutable? "; }
567 568
        }

569
        ret mstr + ty_to_str(cx, m.ty);
570 571
    }

572 573 574 575 576 577 578
    alt (cname(cx, typ)) {
        case (some[str](?cs)) {
            ret cs;
        }
        case (_) { }
    }

579
    auto s = "";
580

581
    alt (struct(cx, typ)) {
582 583
        case (ty_native)       { s += "native";                         }
        case (ty_nil)          { s += "()";                             }
584
        case (ty_bot)          { s += "_|_";                            }
585 586 587 588
        case (ty_bool)         { s += "bool";                           }
        case (ty_int)          { s += "int";                            }
        case (ty_float)        { s += "float";                          }
        case (ty_uint)         { s += "uint";                           }
589
        case (ty_machine(?tm)) { s += common::ty_mach_to_str(tm);        }
590 591
        case (ty_char)         { s += "char";                           }
        case (ty_str)          { s += "str";                            }
592 593 594 595
        case (ty_box(?tm))     { s += "@" + mt_to_str(cx, tm);          }
        case (ty_vec(?tm))     { s += "vec[" + mt_to_str(cx, tm) + "]"; }
        case (ty_port(?t))     { s += "port[" + ty_to_str(cx, t) + "]"; }
        case (ty_chan(?t))     { s += "chan[" + ty_to_str(cx, t) + "]"; }
596
        case (ty_type)         { s += "type";                           }
597
        case (ty_task)         { s += "task";                           }
598 599

        case (ty_tup(?elems)) {
600
            auto f = bind mt_to_str(cx, _);
601 602
            auto strs = vec::map[mt,str](f, elems);
            s += "tup(" + str::connect(strs, ",") + ")";
603 604 605
        }

        case (ty_rec(?elems)) {
606
            auto f = bind field_to_str(cx, _);
607 608
            auto strs = vec::map[field,str](f, elems);
            s += "rec(" + str::connect(strs, ",") + ")";
609 610
        }

611
        case (ty_tag(?id, ?tps)) {
612
            // The user should never see this if the cname is set properly!
613 614
            s += "<tag#" + util::common::istr(id._0) + ":" +
                util::common::istr(id._1) + ">";
615
            if (vec::len[t](tps) > 0u) {
616
                auto f = bind ty_to_str(cx, _);
617 618
                auto strs = vec::map[t,str](f, tps);
                s += "[" + str::connect(strs, ",") + "]";
619
            }
620 621
        }

622
        case (ty_fn(?proto, ?inputs, ?output)) {
623
            s += fn_to_str(cx, proto, none[ast::ident], inputs, output);
624 625
        }

626
        case (ty_native_fn(_, ?inputs, ?output)) {
627 628
            s += fn_to_str(cx, ast::proto_fn, none[ast::ident],
                           inputs, output);
629 630
        }

631
        case (ty_obj(?meths)) {
632
            auto f = bind method_to_str(cx, _);
633 634
            auto m = vec::map[method,str](f, meths);
            s += "obj {\n\t" + str::connect(m, "\n\t") + "\n}";
635 636 637
        }

        case (ty_var(?v)) {
638
            s += "<T" + util::common::istr(v) + ">";
639 640
        }

G
Graydon Hoare 已提交
641
        case (ty_local(?id)) {
642 643
            s += "<L" + util::common::istr(id._0) + ":" +
                util::common::istr(id._1) + ">";
G
Graydon Hoare 已提交
644 645
        }

646
        case (ty_param(?id)) {
647
            s += "'" + str::unsafe_from_bytes([('a' as u8) + (id as u8)]);
648
        }
649 650

        case (ty_bound_param(?id)) {
651
            s += "''" + str::unsafe_from_bytes([('a' as u8) +
652
                                                    (id as u8)]);
653
        }
654 655 656 657 658

        case (_) {
            s += ty_to_short_str(cx, typ);
        }

659 660 661 662 663
    }

    ret s;
}

664
fn ty_to_short_str(&ctxt cx, t typ) -> str {
665
    auto f = def_to_str;
666 667
    auto ecx = @rec(ds=f, tcx=cx, abbrevs=metadata::ac_no_abbrevs);
    auto s = metadata::Encode::ty_str(ecx, typ);
668
    if (str::byte_len(s) >= 32u) { s = str::substr(s, 0u, 32u); }
669
    ret s;
670 671
}

672 673
// Type folds

674
type ty_walk = fn(t);
675

676
fn walk_ty(&ctxt cx, ty_walk walker, t ty) {
677
    alt (struct(cx, ty)) {
678
        case (ty_nil)           { /* no-op */ }
679
        case (ty_bot)           { /* no-op */ }
680 681 682 683 684 685 686 687 688
        case (ty_bool)          { /* no-op */ }
        case (ty_int)           { /* no-op */ }
        case (ty_uint)          { /* no-op */ }
        case (ty_float)         { /* no-op */ }
        case (ty_machine(_))    { /* no-op */ }
        case (ty_char)          { /* no-op */ }
        case (ty_str)           { /* no-op */ }
        case (ty_type)          { /* no-op */ }
        case (ty_native)        { /* no-op */ }
689 690 691 692
        case (ty_box(?tm))      { walk_ty(cx, walker, tm.ty); }
        case (ty_vec(?tm))      { walk_ty(cx, walker, tm.ty); }
        case (ty_port(?subty))  { walk_ty(cx, walker, subty); }
        case (ty_chan(?subty))  { walk_ty(cx, walker, subty); }
693
        case (ty_tag(?tid, ?subtys)) {
694
            for (t subty in subtys) {
695
                walk_ty(cx, walker, subty);
696 697 698 699
            }
        }
        case (ty_tup(?mts)) {
            for (mt tm in mts) {
700
                walk_ty(cx, walker, tm.ty);
701 702 703 704
            }
        }
        case (ty_rec(?fields)) {
            for (field fl in fields) {
705
                walk_ty(cx, walker, fl.mt.ty);
706 707 708 709
            }
        }
        case (ty_fn(?proto, ?args, ?ret_ty)) {
            for (arg a in args) {
710
                walk_ty(cx, walker, a.ty);
711
            }
712
            walk_ty(cx, walker, ret_ty);
713 714 715
        }
        case (ty_native_fn(?abi, ?args, ?ret_ty)) {
            for (arg a in args) {
716
                walk_ty(cx, walker, a.ty);
717
            }
718
            walk_ty(cx, walker, ret_ty);
719 720
        }
        case (ty_obj(?methods)) {
721
            let vec[method] new_methods = [];
722 723
            for (method m in methods) {
                for (arg a in m.inputs) {
724
                    walk_ty(cx, walker, a.ty);
725
                }
726
                walk_ty(cx, walker, m.output);
727 728 729 730 731 732 733
            }
        }
        case (ty_var(_))         { /* no-op */ }
        case (ty_local(_))       { /* no-op */ }
        case (ty_param(_))       { /* no-op */ }
        case (ty_bound_param(_)) { /* no-op */ }
    }
734

735 736 737
    walker(ty);
}

738
type ty_fold = fn(t) -> t;
739

740
fn fold_ty(&ctxt cx, ty_fold fld, t ty_0) -> t {
741
    auto ty = ty_0;
742
    alt (struct(cx, ty)) {
743
        case (ty_nil)           { /* no-op */ }
744
        case (ty_bot)           { /* no-op */ }
745 746 747 748 749 750 751 752 753
        case (ty_bool)          { /* no-op */ }
        case (ty_int)           { /* no-op */ }
        case (ty_uint)          { /* no-op */ }
        case (ty_float)         { /* no-op */ }
        case (ty_machine(_))    { /* no-op */ }
        case (ty_char)          { /* no-op */ }
        case (ty_str)           { /* no-op */ }
        case (ty_type)          { /* no-op */ }
        case (ty_native)        { /* no-op */ }
754
        case (ty_box(?tm)) {
755 756
            ty = copy_cname(cx, mk_box(cx, rec(ty=fold_ty(cx, fld, tm.ty),
                                               mut=tm.mut)), ty);
757
        }
758
        case (ty_vec(?tm)) {
759 760
            ty = copy_cname(cx, mk_vec(cx, rec(ty=fold_ty(cx, fld, tm.ty),
                                                          mut=tm.mut)), ty);
761
        }
762
        case (ty_port(?subty)) {
763
            ty = copy_cname(cx, mk_port(cx, fold_ty(cx, fld, subty)), ty);
764 765
        }
        case (ty_chan(?subty)) {
766
            ty = copy_cname(cx, mk_chan(cx, fold_ty(cx, fld, subty)), ty);
767
        }
768
        case (ty_tag(?tid, ?subtys)) {
769
            let vec[t] new_subtys = [];
770
            for (t subty in subtys) {
771
                new_subtys += [fold_ty(cx, fld, subty)];
772
            }
773
            ty = copy_cname(cx, mk_tag(cx, tid, new_subtys), ty);
774
        }
775
        case (ty_tup(?mts)) {
776
            let vec[mt] new_mts = [];
777
            for (mt tm in mts) {
778
                auto new_subty = fold_ty(cx, fld, tm.ty);
779
                new_mts += [rec(ty=new_subty, mut=tm.mut)];
780
            }
781
            ty = copy_cname(cx, mk_tup(cx, new_mts), ty);
782 783
        }
        case (ty_rec(?fields)) {
784
            let vec[field] new_fields = [];
785
            for (field fl in fields) {
786
                auto new_ty = fold_ty(cx, fld, fl.mt.ty);
787
                auto new_mt = rec(ty=new_ty, mut=fl.mt.mut);
788
                new_fields += [rec(ident=fl.ident, mt=new_mt)];
789
            }
790
            ty = copy_cname(cx, mk_rec(cx, new_fields), ty);
791
        }
792
        case (ty_fn(?proto, ?args, ?ret_ty)) {
793
            let vec[arg] new_args = [];
794
            for (arg a in args) {
795
                auto new_ty = fold_ty(cx, fld, a.ty);
796
                new_args += [rec(mode=a.mode, ty=new_ty)];
797
            }
798 799
            ty = copy_cname(cx, mk_fn(cx, proto, new_args,
                                      fold_ty(cx, fld, ret_ty)), ty);
800
        }
801
        case (ty_native_fn(?abi, ?args, ?ret_ty)) {
802
            let vec[arg] new_args = [];
803
            for (arg a in args) {
804
                auto new_ty = fold_ty(cx, fld, a.ty);
805
                new_args += [rec(mode=a.mode, ty=new_ty)];
806
            }
807 808
            ty = copy_cname(cx, mk_native_fn(cx, abi, new_args,
                                             fold_ty(cx, fld, ret_ty)), ty);
809
        }
810
        case (ty_obj(?methods)) {
811
            let vec[method] new_methods = [];
812
            for (method m in methods) {
813
                let vec[arg] new_args = [];
814
                for (arg a in m.inputs) {
815 816
                    new_args += [rec(mode=a.mode,
                                        ty=fold_ty(cx, fld, a.ty))];
817
                }
818
                new_methods += [rec(proto=m.proto, ident=m.ident,
819
                                       inputs=new_args,
820
                                       output=fold_ty(cx, fld, m.output))];
821
            }
822
            ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
823
        }
824 825 826 827
        case (ty_var(_))         { /* no-op */ }
        case (ty_local(_))       { /* no-op */ }
        case (ty_param(_))       { /* no-op */ }
        case (ty_bound_param(_)) { /* no-op */ }
828 829
    }

830
    ret fld(ty);
831 832 833 834
}

// Type utilities

835
fn rename(&ctxt cx, t typ, str new_cname) -> t {
836
    ret gen_ty_full(cx, struct(cx, typ), some[str](new_cname));
837 838 839 840
}

// Returns a type with the structural part taken from `struct_ty` and the
// canonical name from `cname_ty`.
841
fn copy_cname(&ctxt cx, t struct_ty, t cname_ty) -> t {
842
    ret gen_ty_full(cx, struct(cx, struct_ty), cname(cx, cname_ty));
843 844
}

845
fn type_is_nil(&ctxt cx, &t ty) -> bool {
846
    alt (struct(cx, ty)) {
847 848 849
        case (ty_nil) { ret true; }
        case (_) { ret false; }
    }
850 851 852 853 854 855 856
}

fn type_is_bot(&ctxt cx, &t ty) -> bool {
    alt (struct(cx, ty)) {
        case (ty_bot) { ret true; }
        case (_) { ret false; }
    }
857 858
}

859
fn type_is_bool(&ctxt cx, &t ty) -> bool {
860
    alt (struct(cx, ty)) {
861 862 863 864 865
        case (ty_bool) { ret true; }
        case (_) { ret false; }
    }
}

866

867
fn type_is_structural(&ctxt cx, &t ty) -> bool {
868
    alt (struct(cx, ty)) {
869 870 871
        case (ty_tup(_))    { ret true; }
        case (ty_rec(_))    { ret true; }
        case (ty_tag(_,_))  { ret true; }
872
        case (ty_fn(_,_,_)) { ret true; }
873 874
        case (ty_obj(_))    { ret true; }
        case (_)            { ret false; }
875 876 877 878
    }
    fail;
}

879
fn type_is_sequence(&ctxt cx, &t ty) -> bool {
880
    alt (struct(cx, ty)) {
881 882 883 884 885 886 887
        case (ty_str)    { ret true; }
        case (ty_vec(_))    { ret true; }
        case (_)            { ret false; }
    }
    fail;
}

888
fn sequence_element_type(&ctxt cx, &t ty) -> t {
889
    alt (struct(cx, ty)) {
890
        case (ty_str)      { ret mk_mach(cx, common::ty_u8); }
891
        case (ty_vec(?mt)) { ret mt.ty; }
892 893 894 895 896
    }
    fail;
}


897
fn type_is_tup_like(&ctxt cx, &t ty) -> bool {
898
    alt (struct(cx, ty)) {
899 900 901 902 903
        case (ty_box(_))    { ret true; }
        case (ty_tup(_))    { ret true; }
        case (ty_rec(_))    { ret true; }
        case (ty_tag(_,_))  { ret true; }
        case (_)            { ret false; }
904 905 906 907
    }
    fail;
}

908
fn get_element_type(&ctxt cx, &t ty, uint i) -> t {
909
    assert (type_is_tup_like(cx, ty));
910
    alt (struct(cx, ty)) {
911 912
        case (ty_tup(?mts)) {
            ret mts.(i).ty;
913 914
        }
        case (ty_rec(?flds)) {
915
            ret flds.(i).mt.ty;
916 917 918 919 920
        }
    }
    fail;
}

921
fn type_is_box(&ctxt cx, &t ty) -> bool {
922
    alt (struct(cx, ty)) {
923 924 925 926 927 928
        case (ty_box(_)) { ret true; }
        case (_) { ret false; }
    }
    fail;
}

929
fn type_is_boxed(&ctxt cx, &t ty) -> bool {
930
    alt (struct(cx, ty)) {
931 932 933
        case (ty_str) { ret true; }
        case (ty_vec(_)) { ret true; }
        case (ty_box(_)) { ret true; }
B
Brian Anderson 已提交
934 935
        case (ty_port(_)) { ret true; }
        case (ty_chan(_)) { ret true; }
936 937 938 939 940
        case (_) { ret false; }
    }
    fail;
}

941
fn type_is_scalar(&ctxt cx, &t ty) -> bool {
942
    alt (struct(cx, ty)) {
943 944 945
        case (ty_nil) { ret true; }
        case (ty_bool) { ret true; }
        case (ty_int) { ret true; }
946
        case (ty_float) { ret true; }
947 948 949
        case (ty_uint) { ret true; }
        case (ty_machine(_)) { ret true; }
        case (ty_char) { ret true; }
G
Graydon Hoare 已提交
950
        case (ty_type) { ret true; }
951
        case (ty_native) { ret true; }
952 953 954 955 956
        case (_) { ret false; }
    }
    fail;
}

957 958
// FIXME: should we just return true for native types in
// type_is_scalar?
959
fn type_is_native(&ctxt cx, &t ty) -> bool {
960
    alt (struct(cx, ty)) {
961 962 963 964 965 966
        case (ty_native) { ret true; }
        case (_) { ret false; }
    }
    fail;
}

967
fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
968
    alt (struct(cx, ty)) {
969
        case (ty_tup(?mts)) {
970
            auto i = 0u;
971
            while (i < vec::len[mt](mts)) {
972
                if (type_has_dynamic_size(cx, mts.(i).ty)) { ret true; }
973 974 975 976 977
                i += 1u;
            }
        }
        case (ty_rec(?fields)) {
            auto i = 0u;
978
            while (i < vec::len[field](fields)) {
979
                if (type_has_dynamic_size(cx, fields.(i).mt.ty)) {
980 981
                    ret true;
                }
982 983 984
                i += 1u;
            }
        }
985 986
        case (ty_tag(_, ?subtys)) {
            auto i = 0u;
987
            while (i < vec::len[t](subtys)) {
988
                if (type_has_dynamic_size(cx, subtys.(i))) { ret true; }
989 990 991
                i += 1u;
            }
        }
992 993 994 995 996
        case (ty_param(_)) { ret true; }
        case (_) { /* fall through */ }
    }
    ret false;
}
997

998
fn type_is_integral(&ctxt cx, &t ty) -> bool {
999
    alt (struct(cx, ty)) {
1000 1001 1002 1003
        case (ty_int) { ret true; }
        case (ty_uint) { ret true; }
        case (ty_machine(?m)) {
            alt (m) {
1004 1005 1006 1007 1008 1009 1010 1011 1012
                case (common::ty_i8) { ret true; }
                case (common::ty_i16) { ret true; }
                case (common::ty_i32) { ret true; }
                case (common::ty_i64) { ret true; }

                case (common::ty_u8) { ret true; }
                case (common::ty_u16) { ret true; }
                case (common::ty_u32) { ret true; }
                case (common::ty_u64) { ret true; }
1013 1014 1015 1016 1017 1018 1019 1020 1021
                case (_) { ret false; }
            }
        }
        case (ty_char) { ret true; }
        case (_) { ret false; }
    }
    fail;
}

1022
fn type_is_fp(&ctxt cx, &t ty) -> bool {
1023
    alt (struct(cx, ty)) {
1024 1025
        case (ty_machine(?tm)) {
            alt (tm) {
1026 1027
                case (common::ty_f32) { ret true; }
                case (common::ty_f64) { ret true; }
1028 1029 1030
                case (_) { ret false; }
            }
        }
1031 1032 1033
        case (ty_float) {
            ret true;
        }
1034 1035 1036 1037 1038
        case (_) { ret false; }
    }
    fail;
}

1039
fn type_is_signed(&ctxt cx, &t ty) -> bool {
1040
    alt (struct(cx, ty)) {
1041 1042 1043
        case (ty_int) { ret true; }
        case (ty_machine(?tm)) {
            alt (tm) {
1044 1045 1046 1047
                case (common::ty_i8) { ret true; }
                case (common::ty_i16) { ret true; }
                case (common::ty_i32) { ret true; }
                case (common::ty_i64) { ret true; }
1048 1049 1050 1051 1052 1053 1054 1055
                case (_) { ret false; }
            }
        }
        case (_) { ret false; }
    }
    fail;
}

1056
fn type_param(&ctxt cx, &t ty) -> option::t[uint] {
1057
    alt (struct(cx, ty)) {
1058 1059
        case (ty_param(?id)) { ret some[uint](id); }
        case (_)             { /* fall through */  }
1060
    }
1061
    ret none[uint];
1062 1063
}

1064
fn def_to_str(&ast::def_id did) -> str {
1065 1066 1067
    ret #fmt("%d:%d", did._0, did._1);
}

1068

P
Patrick Walton 已提交
1069 1070 1071
// Type hashing. This function is private to this module (and slow); external
// users should use `hash_ty()` instead.
fn hash_type_structure(&sty st) -> uint {
1072 1073 1074 1075 1076
    fn hash_uint(uint id, uint n) -> uint {
        auto h = id;
        h += h << 5u + n;
        ret h;
    }
P
Patrick Walton 已提交
1077

1078
    fn hash_def(uint id, ast::def_id did) -> uint {
1079 1080 1081 1082
        auto h = id;
        h += h << 5u + (did._0 as uint);
        h += h << 5u + (did._1 as uint);
        ret h;
1083
    }
P
Patrick Walton 已提交
1084

1085
    fn hash_subty(uint id, &t subty) -> uint {
1086 1087 1088 1089 1090
        auto h = id;
        h += h << 5u + hash_ty(subty);
        ret h;
    }

1091
    fn hash_fn(uint id, &vec[arg] args, &t rty) -> uint {
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
        auto h = id;
        for (arg a in args) {
            h += h << 5u + hash_ty(a.ty);
        }
        h += h << 5u + hash_ty(rty);
        ret h;
    }

    alt (st) {
        case (ty_nil) { ret 0u; }
        case (ty_bool) { ret 1u; }
        case (ty_int) { ret 2u; }
        case (ty_float) { ret 3u; }
        case (ty_uint) { ret 4u; }
        case (ty_machine(?tm)) {
            alt (tm) {
1108 1109 1110 1111
                case (common::ty_i8) { ret 5u; }
                case (common::ty_i16) { ret 6u; }
                case (common::ty_i32) { ret 7u; }
                case (common::ty_i64) { ret 8u; }
1112

1113 1114 1115 1116
                case (common::ty_u8) { ret 9u; }
                case (common::ty_u16) { ret 10u; }
                case (common::ty_u32) { ret 11u; }
                case (common::ty_u64) { ret 12u; }
1117

1118 1119
                case (common::ty_f32) { ret 13u; }
                case (common::ty_f64) { ret 14u; }
1120 1121 1122 1123 1124 1125
            }
        }
        case (ty_char) { ret 15u; }
        case (ty_str) { ret 16u; }
        case (ty_tag(?did, ?tys)) {
            auto h = hash_def(17u, did);
1126
            for (t typ in tys) {
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
                h += h << 5u + hash_ty(typ);
            }
            ret h;
        }
        case (ty_box(?mt)) { ret hash_subty(18u, mt.ty); }
        case (ty_vec(?mt)) { ret hash_subty(19u, mt.ty); }
        case (ty_port(?typ)) { ret hash_subty(20u, typ); }
        case (ty_chan(?typ)) { ret hash_subty(21u, typ); }
        case (ty_task) { ret 22u; }
        case (ty_tup(?mts)) {
            auto h = 23u;
            for (mt tm in mts) {
                h += h << 5u + hash_ty(tm.ty);
            }
            ret h;
        }
        case (ty_rec(?fields)) {
            auto h = 24u;
            for (field f in fields) {
                h += h << 5u + hash_ty(f.mt.ty);
            }
            ret h;
        }
        case (ty_fn(_, ?args, ?rty)) { ret hash_fn(25u, args, rty); }
        case (ty_native_fn(_, ?args, ?rty)) { ret hash_fn(26u, args, rty); }
        case (ty_obj(?methods)) {
            auto h = 27u;
            for (method m in methods) {
1155
                h += h << 5u + str::hash(m.ident);
1156 1157 1158 1159 1160 1161 1162 1163 1164
            }
            ret h;
        }
        case (ty_var(?v)) { ret hash_uint(28u, v as uint); }
        case (ty_local(?did)) { ret hash_def(29u, did); }
        case (ty_param(?pid)) { ret hash_uint(30u, pid); }
        case (ty_bound_param(?pid)) { ret hash_uint(31u, pid); }
        case (ty_type) { ret 32u; }
        case (ty_native) { ret 33u; }
1165
        case (ty_bot) { ret 34u; }
1166
    }
1167 1168
}

1169
fn hash_type_info(&sty st, &option::t[str] cname_opt) -> uint {
1170 1171 1172
    auto h = hash_type_structure(st);
    alt (cname_opt) {
        case (none[str]) { /* no-op */ }
1173
        case (some[str](?s)) { h += h << 5u + str::hash(s); }
1174 1175 1176 1177
    }
    ret h;
}

1178 1179 1180
fn hash_raw_ty(&raw_t rt) -> uint { ret rt.hash; }

fn hash_ty(&t typ) -> uint { ret typ; }
P
Patrick Walton 已提交
1181

1182

1183 1184 1185 1186
// Type equality. This function is private to this module (and slow); external
// users should use `eq_ty()` instead.
fn equal_type_structures(&sty a, &sty b) -> bool {
    fn equal_mt(&mt a, &mt b) -> bool {
1187
        ret a.mut == b.mut && eq_ty(a.ty, b.ty);
1188 1189
    }

1190 1191
    fn equal_fn(&vec[arg] args_a, &t rty_a,
                &vec[arg] args_b, &t rty_b) -> bool {
1192
        if (!eq_ty(rty_a, rty_b)) { ret false; }
1193

1194 1195
        auto len = vec::len[arg](args_a);
        if (len != vec::len[arg](args_b)) { ret false; }
1196

1197 1198 1199
        auto i = 0u;
        while (i < len) {
            auto arg_a = args_a.(i); auto arg_b = args_b.(i);
1200
            if (arg_a.mode != arg_b.mode) { ret false; }
1201
            if (!eq_ty(arg_a.ty, arg_b.ty)) { ret false; }
1202 1203 1204 1205 1206
            i += 1u;
        }
        ret true;
    }

1207
    fn equal_def(&ast::def_id did_a, &ast::def_id did_b) -> bool {
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
        ret did_a._0 == did_b._0 && did_a._1 == did_b._1;
    }

    alt (a) {
        case (ty_nil) {
            alt (b) {
                case (ty_nil) { ret true; }
                case (_) { ret false; }
            }
        }
1218 1219 1220 1221 1222 1223
        case (ty_bot) {
            alt(b) {
                case (ty_bot) { ret true; }
                case (_)      { ret false; }
            }
        }
1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270
        case (ty_bool) {
            alt (b) {
                case (ty_bool) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_int) {
            alt (b) {
                case (ty_int) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_float) {
            alt (b) {
                case (ty_float) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_uint) {
            alt (b) {
                case (ty_uint) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_machine(?tm_a)) {
            alt (b) {
                case (ty_machine(?tm_b)) {
                    ret hash_type_structure(a) == hash_type_structure(b);
                }
                case (_) { ret false; }
            }
        }
        case (ty_char) {
            alt (b) {
                case (ty_char) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_str) {
            alt (b) {
                case (ty_str) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_tag(?id_a, ?tys_a)) {
            alt (b) {
                case (ty_tag(?id_b, ?tys_b)) {
P
Patrick Walton 已提交
1271
                    if (!equal_def(id_a, id_b)) { ret false; }
1272

1273 1274
                    auto len = vec::len[t](tys_a);
                    if (len != vec::len[t](tys_b)) { ret false; }
1275 1276
                    auto i = 0u;
                    while (i < len) {
1277
                        if (!eq_ty(tys_a.(i), tys_b.(i))) { ret false; }
1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
                        i += 1u;
                    }
                    ret true;
                }
                case (_) { ret false; }
            }
        }
        case (ty_box(?mt_a)) {
            alt (b) {
                case (ty_box(?mt_b)) { ret equal_mt(mt_a, mt_b); }
                case (_) { ret false; }
            }
        }
        case (ty_vec(?mt_a)) {
            alt (b) {
                case (ty_vec(?mt_b)) { ret equal_mt(mt_a, mt_b); }
                case (_) { ret false; }
            }
        }
        case (ty_port(?t_a)) {
            alt (b) {
1299
                case (ty_port(?t_b)) { ret eq_ty(t_a, t_b); }
1300 1301 1302 1303 1304
                case (_) { ret false; }
            }
        }
        case (ty_chan(?t_a)) {
            alt (b) {
1305
                case (ty_chan(?t_b)) { ret eq_ty(t_a, t_b); }
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
                case (_) { ret false; }
            }
        }
        case (ty_task) {
            alt (b) {
                case (ty_task) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_tup(?mts_a)) {
            alt (b) {
                case (ty_tup(?mts_b)) {
1318 1319
                    auto len = vec::len[mt](mts_a);
                    if (len != vec::len[mt](mts_b)) { ret false; }
1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332
                    auto i = 0u;
                    while (i < len) {
                        if (!equal_mt(mts_a.(i), mts_b.(i))) { ret false; }
                        i += 1u;
                    }
                    ret true;
                }
                case (_) { ret false; }
            }
        }
        case (ty_rec(?flds_a)) {
            alt (b) {
                case (ty_rec(?flds_b)) {
1333 1334
                    auto len = vec::len[field](flds_a);
                    if (len != vec::len[field](flds_b)) { ret false; }
1335 1336 1337
                    auto i = 0u;
                    while (i < len) {
                        auto fld_a = flds_a.(i); auto fld_b = flds_b.(i);
1338
                        if (!str::eq(fld_a.ident, fld_b.ident) ||
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
                                !equal_mt(fld_a.mt, fld_b.mt)) {
                            ret false;
                        }
                        i += 1u;
                    }
                    ret true;
                }
                case (_) { ret false; }
            }
        }
        case (ty_fn(?p_a, ?args_a, ?rty_a)) {
            alt (b) {
                case (ty_fn(?p_b, ?args_b, ?rty_b)) {
1352
                    ret p_a == p_b &&
1353 1354 1355 1356 1357 1358 1359 1360
                        equal_fn(args_a, rty_a, args_b, rty_b);
                }
                case (_) { ret false; }
            }
        }
        case (ty_native_fn(?abi_a, ?args_a, ?rty_a)) {
            alt (b) {
                case (ty_native_fn(?abi_b, ?args_b, ?rty_b)) {
1361
                    ret abi_a == abi_b &&
1362 1363 1364 1365 1366 1367 1368 1369
                        equal_fn(args_a, rty_a, args_b, rty_b);
                }
                case (_) { ret false; }
            }
        }
        case (ty_obj(?methods_a)) {
            alt (b) {
                case (ty_obj(?methods_b)) {
1370 1371
                    auto len = vec::len[method](methods_a);
                    if (len != vec::len[method](methods_b)) { ret false; }
1372 1373 1374
                    auto i = 0u;
                    while (i < len) {
                        auto m_a = methods_a.(i); auto m_b = methods_b.(i);
1375
                        if (m_a.proto != m_b.proto ||
1376
                                !str::eq(m_a.ident, m_b.ident) ||
P
Patrick Walton 已提交
1377 1378
                                !equal_fn(m_a.inputs, m_a.output,
                                          m_b.inputs, m_b.output)) {
1379 1380
                            ret false;
                        }
P
Patrick Walton 已提交
1381
                        i += 1u;
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426
                    }
                    ret true;
                }
                case (_) { ret false; }
            }
        }
        case (ty_var(?v_a)) {
            alt (b) {
                case (ty_var(?v_b)) { ret v_a == v_b; }
                case (_) { ret false; }
            }
        }
        case (ty_local(?did_a)) {
            alt (b) {
                case (ty_local(?did_b)) { ret equal_def(did_a, did_b); }
                case (_) { ret false; }
            }
        }
        case (ty_param(?pid_a)) {
            alt (b) {
                case (ty_param(?pid_b)) { ret pid_a == pid_b; }
                case (_) { ret false; }
            }
        }
        case (ty_bound_param(?pid_a)) {
            alt (b) {
                case (ty_bound_param(?pid_b)) { ret pid_a == pid_b; }
                case (_) { ret false; }
            }
        }
        case (ty_type) {
            alt (b) {
                case (ty_type) { ret true; }
                case (_) { ret false; }
            }
        }
        case (ty_native) {
            alt (b) {
                case (ty_native) { ret true; }
                case (_) { ret false; }
            }
        }
    }
}

P
Patrick Walton 已提交
1427 1428
// An expensive type equality function. This function is private to this
// module.
1429 1430
//
// FIXME: Use structural comparison, but this loops forever and segfaults.
1431
fn eq_raw_ty(&raw_t a, &raw_t b) -> bool {
P
Patrick Walton 已提交
1432
    // Check hashes (fast path).
1433 1434 1435 1436
    if (a.hash != b.hash) {
        ret false;
    }

P
Patrick Walton 已提交
1437
    // Check canonical names.
1438
    alt (a.cname) {
P
Patrick Walton 已提交
1439
        case (none[str]) {
1440
            alt (b.cname) {
P
Patrick Walton 已提交
1441
                case (none[str]) { /* ok */ }
1442 1443 1444
                case (_) { ret false; }
            }
        }
P
Patrick Walton 已提交
1445
        case (some[str](?s_a)) {
1446
            alt (b.cname) {
P
Patrick Walton 已提交
1447
                case (some[str](?s_b)) {
1448
                    if (!str::eq(s_a, s_b)) { ret false; }
1449 1450 1451 1452
                }
                case (_) { ret false; }
            }
        }
P
Patrick Walton 已提交
1453
    }
1454

P
Patrick Walton 已提交
1455
    // Check structures.
1456
    ret equal_type_structures(a.struct, b.struct);
P
Patrick Walton 已提交
1457
}
1458

P
Patrick Walton 已提交
1459 1460
// This is the equality function the public should use. It works as long as
// the types are interned.
1461
fn eq_ty(&t a, &t b) -> bool { ret a == b; }
1462

1463

1464
// Type lookups
1465

1466 1467
fn ann_to_ty_param_substs_opt_and_ty(&node_type_table ntt, &ast::ann ann)
        -> ty_param_substs_opt_and_ty {
P
Patrick Walton 已提交
1468
    alt (ntt.(ann.id)) {
1469 1470 1471
        case (none[ty::ty_param_substs_opt_and_ty]) {
            log_err "ann_to_ty_param_substs_opt_and_ty() called on an " +
                "untyped node";
1472 1473
            fail;
        }
1474
        case (some[ty::ty_param_substs_opt_and_ty](?tpot)) { ret tpot; }
1475 1476 1477
    }
}

1478 1479 1480 1481 1482 1483 1484
fn ann_to_type(&node_type_table ntt, &ast::ann ann) -> t {
    ret ann_to_ty_param_substs_opt_and_ty(ntt, ann)._1;
}

fn ann_to_type_params(&node_type_table ntt, &ast::ann ann) -> vec[t] {
    alt (ann_to_ty_param_substs_opt_and_ty(ntt, ann)._0) {
        case (none[vec[t]]) {
1485
            let vec[t] result = [];
1486 1487 1488 1489 1490 1491
            ret result;
        }
        case (some[vec[t]](?tps)) { ret tps; }
    }
}

1492 1493 1494 1495 1496 1497
fn ann_has_type_params(&node_type_table ntt, &ast::ann ann) -> bool {
    auto tpt = ann_to_ty_param_substs_opt_and_ty(ntt, ann);
    ret !option::is_none[vec[t]](tpt._0);
}


1498 1499
// Returns the type of an annotation, with type parameter substitutions
// performed if applicable.
1500 1501
fn ann_to_monotype(&ctxt cx, ast::ann a) -> t {
    auto tpot = ann_to_ty_param_substs_opt_and_ty(cx.node_types, a);
1502 1503 1504 1505
    alt (tpot._0) {
        case (none[vec[t]]) { ret tpot._1; }
        case (some[vec[t]](?tps)) {
            ret substitute_type_params(cx, tps, tpot._1);
1506 1507 1508 1509
        }
    }
}

1510

P
Patrick Walton 已提交
1511 1512 1513
// Turns a type and optional type parameters into an annotation, using
// defaults for other fields.
fn mk_ann_type(uint node_id, t typ, option::t[vec[t]] tps) -> ast::ann {
1514
    ret rec(id=node_id, ty=typ, tps=tps);
P
Patrick Walton 已提交
1515 1516 1517
}

// Turns a type into an annotation, using defaults for other fields.
1518
fn triv_ann(uint node_id, t typ) -> ast::ann {
P
Patrick Walton 已提交
1519
    ret mk_ann_type(node_id, typ, none[vec[t]]);
1520 1521
}

1522 1523
// Creates a nil type annotation.
fn plain_ann(uint node_id, ctxt tcx) -> ast::ann {
P
Patrick Walton 已提交
1524
    ret triv_ann(node_id, mk_nil(tcx));
1525 1526 1527 1528
}

// Creates a _|_ type annotation.
fn bot_ann(uint node_id, ctxt tcx) -> ast::ann {
P
Patrick Walton 已提交
1529
    ret triv_ann(node_id, mk_bot(tcx));
1530 1531 1532
}


1533
// Returns the number of distinct type parameters in the given type.
1534 1535
fn count_ty_params(&ctxt cx, t ty) -> uint {
    fn counter(&ctxt cx, @mutable vec[uint] param_indices, t ty) {
1536
        alt (struct(cx, ty)) {
1537 1538 1539 1540 1541
            case (ty_param(?param_idx)) {
                auto seen = false;
                for (uint other_param_idx in *param_indices) {
                    if (param_idx == other_param_idx) {
                        seen = true;
1542
                    }
1543
                }
1544
                if (!seen) {
1545
                    *param_indices += [param_idx];
1546
                }
1547
            }
1548
            case (_) { /* fall through */ }
1549 1550 1551
        }
    }

1552
    let vec[uint] v = [];    // FIXME: typechecker botch
1553
    let @mutable vec[uint] param_indices = @mutable v;
1554 1555
    auto f = bind counter(cx, param_indices, _);
    walk_ty(cx, f, ty);
1556
    ret vec::len[uint](*param_indices);
1557 1558
}

1559
fn type_contains_vars(&ctxt cx, &t typ) -> bool {
1560
    ret interner::get[raw_t](*cx.ts, typ).has_vars;
1561 1562
}

1563
fn type_contains_locals(&ctxt cx, &t typ) -> bool {
1564
    ret interner::get[raw_t](*cx.ts, typ).has_locals;
1565 1566
}

1567
fn type_contains_params(&ctxt cx, &t typ) -> bool {
1568
    ret interner::get[raw_t](*cx.ts, typ).has_params;
1569 1570
}

1571
fn type_contains_bound_params(&ctxt cx, &t typ) -> bool {
1572
    ret interner::get[raw_t](*cx.ts, typ).has_bound_params;
1573 1574
}

G
Graydon Hoare 已提交
1575 1576
// Type accessors for substructures of types

1577
fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
1578
    alt (struct(cx, fty)) {
1579 1580
        case (ty::ty_fn(_, ?a, _)) { ret a; }
        case (ty::ty_native_fn(_, ?a, _)) { ret a; }
1581
    }
1582
    fail;
1583 1584
}

1585
fn ty_fn_proto(&ctxt cx, &t fty) -> ast::proto {
1586
    alt (struct(cx, fty)) {
1587
        case (ty::ty_fn(?p, _, _)) { ret p; }
1588
    }
1589
    fail;
G
Graydon Hoare 已提交
1590 1591
}

1592
fn ty_fn_abi(&ctxt cx, &t fty) -> ast::native_abi {
1593
    alt (struct(cx, fty)) {
1594
        case (ty::ty_native_fn(?a, _, _)) { ret a; }
1595 1596 1597 1598
    }
    fail;
}

1599
fn ty_fn_ret(&ctxt cx, &t fty) -> t {
1600
    alt (struct(cx, fty)) {
1601 1602
        case (ty::ty_fn(_, _, ?r)) { ret r; }
        case (ty::ty_native_fn(_, _, ?r)) { ret r; }
1603
    }
1604
    fail;
G
Graydon Hoare 已提交
1605 1606
}

1607
fn is_fn_ty(&ctxt cx, &t fty) -> bool {
1608
    alt (struct(cx, fty)) {
1609 1610
        case (ty::ty_fn(_, _, _)) { ret true; }
        case (ty::ty_native_fn(_, _, _)) { ret true; }
1611 1612 1613
        case (_) { ret false; }
    }
    ret false;
G
Graydon Hoare 已提交
1614 1615 1616
}


1617 1618
// Type accessors for AST nodes

1619 1620
// Given an item, returns the associated type as well as the number of type
// parameters it has.
1621 1622
fn native_item_ty(&node_type_table ntt, &@ast::native_item it)
        -> ty_param_count_and_ty {
1623
    auto ty_param_count;
1624 1625
    auto result_ty;
    alt (it.node) {
1626
        case (ast::native_item_fn(_, _, _, ?tps, _, ?ann)) {
1627
            ty_param_count = vec::len[ast::ty_param](tps);
1628
            result_ty = ann_to_type(ntt, ann);
1629 1630
        }
    }
1631
    ret tup(ty_param_count, result_ty);
1632 1633
}

1634
fn item_ty(&node_type_table ntt, &@ast::item it) -> ty_param_count_and_ty {
1635
    auto ty_param_count;
1636 1637
    auto result_ty;
    alt (it.node) {
1638
        case (ast::item_const(_, _, _, _, ?ann)) {
1639
            ty_param_count = 0u;
1640
            result_ty = ann_to_type(ntt, ann);
1641
        }
1642
        case (ast::item_fn(_, _, ?tps, _, ?ann)) {
1643
            ty_param_count = vec::len[ast::ty_param](tps);
1644
            result_ty = ann_to_type(ntt, ann);
1645
        }
1646
        case (ast::item_mod(_, _, _)) {
1647 1648
            fail;   // modules are typeless
        }
1649
        case (ast::item_ty(_, _, ?tps, _, ?ann)) {
1650
            ty_param_count = vec::len[ast::ty_param](tps);
1651
            result_ty = ann_to_type(ntt, ann);
1652
        }
1653
        case (ast::item_tag(_, _, ?tps, ?did, ?ann)) {
1654
            ty_param_count = vec::len[ast::ty_param](tps);
1655
            result_ty = ann_to_type(ntt, ann);
1656
        }
1657
        case (ast::item_obj(_, _, ?tps, _, ?ann)) {
1658
            ty_param_count = vec::len[ast::ty_param](tps);
1659
            result_ty = ann_to_type(ntt, ann);
1660 1661 1662
        }
    }

1663
    ret tup(ty_param_count, result_ty);
1664 1665
}

1666
fn stmt_ty(&ctxt cx, &@ast::stmt s) -> t {
1667
    alt (s.node) {
1668
        case (ast::stmt_expr(?e,_)) {
1669
            ret expr_ty(cx, e);
1670 1671
        }
        case (_) {
1672
            ret mk_nil(cx);
1673 1674 1675 1676
        }
    }
}

1677
fn block_ty(&ctxt cx, &ast::block b) -> t {
1678
    alt (b.node.expr) {
1679
        case (some[@ast::expr](?e)) { ret expr_ty(cx, e); }
1680
        case (none[@ast::expr])     { ret mk_nil(cx); }
1681 1682 1683
    }
}

1684 1685
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
1686 1687
fn pat_ty(&ctxt cx, &@ast::pat pat) -> t {
    ret ann_to_monotype(cx, pat_ann(pat));
1688 1689
}

1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709
fn item_ann(&@ast::item it) -> ast::ann {
    alt (it.node) {
        case (ast::item_const(_,_,_,_,?a)) { ret a; }
        case (ast::item_fn(_,_,_,_,?a)) { ret a; }
        case (ast::item_mod(_,_,_)) {
            log_err "a module was passed to item_ann(), " +
                "but modules haven't annotations";
            fail;
        }
        case (ast::item_native_mod(_,_,_)) {
            log_err "a native module was passed to item_ann(), " +
                "but native modules haven't annotations";
            fail;
        }
        case (ast::item_ty(_,_,_,_,?a)) { ret a; }
        case (ast::item_tag(_,_,_,_,?a)) { ret a; }
        case (ast::item_obj(_,_,_,_,?a)) { ret a; }
    }
}

1710
fn expr_ann(&@ast::expr e) -> ast::ann {
1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
    alt (e.node) {
        case (ast::expr_vec(_,_,?a)) { ret a; }
        case (ast::expr_tup(_,?a)) { ret a; }
        case (ast::expr_rec(_,_,?a)) { ret a; }
        case (ast::expr_call(_,_,?a)) { ret a; }
        case (ast::expr_bind(_,_,?a)) { ret a; }
        case (ast::expr_binary(_,_,_,?a)) { ret a; }
        case (ast::expr_unary(_,_,?a)) { ret a; }
        case (ast::expr_lit(_,?a)) { ret a; }
        case (ast::expr_cast(_,_,?a)) { ret a; }
        case (ast::expr_if(_,_,_,?a)) { ret a; }
        case (ast::expr_while(_,_,?a)) { ret a; }
        case (ast::expr_for(_,_,_,?a)) { ret a; }
        case (ast::expr_for_each(_,_,_,?a)) { ret a; }
        case (ast::expr_do_while(_,_,?a)) { ret a; }
        case (ast::expr_alt(_,_,?a)) { ret a; }
        case (ast::expr_block(_,?a)) { ret a; }
        case (ast::expr_assign(_,_,?a)) { ret a; }
        case (ast::expr_assign_op(_,_,_,?a)) { ret a; }
        case (ast::expr_send(_,_,?a)) { ret a; }
        case (ast::expr_recv(_,_,?a)) { ret a; }
        case (ast::expr_field(_,_,?a)) { ret a; }
        case (ast::expr_index(_,_,?a)) { ret a; }
        case (ast::expr_path(_,?a)) { ret a; }
        case (ast::expr_ext(_,_,_,_,?a)) { ret a; }
        case (ast::expr_fail(?a)) { ret a; }
        case (ast::expr_ret(_,?a)) { ret a; }
        case (ast::expr_put(_,?a)) { ret a; }
        case (ast::expr_be(_,?a)) { ret a; }
        case (ast::expr_log(_,_,?a)) { ret a; }
        case (ast::expr_assert(_,?a)) { ret a; }
        case (ast::expr_check(_,?a)) { ret a; }
        case (ast::expr_port(?a)) { ret a; }
        case (ast::expr_chan(_,?a)) { ret a; }
1745
        case (ast::expr_anon_obj(_,_,_,?a)) { ret a; }
1746 1747 1748
        case (ast::expr_break(?a)) { ret a; }
        case (ast::expr_cont(?a)) { ret a; }
        case (ast::expr_self_method(_, ?a)) { ret a; }
1749
        case (ast::expr_spawn(_, _, _, _, ?a)) { ret a; }
1750 1751 1752
    }
}

1753 1754 1755 1756 1757 1758
// 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"
// instead of "fn(&T) -> T with T = int". If this isn't what you want, see
// expr_ty_params_and_ty() below.
1759 1760
fn expr_ty(&ctxt cx, &@ast::expr expr) -> t {
    ret ann_to_monotype(cx, expr_ann(expr));
1761 1762
}

1763
fn expr_ty_params_and_ty(&ctxt cx, &@ast::expr expr)
1764
        -> tup(vec[t], t) {
1765 1766
    auto a = expr_ann(expr);

1767 1768
    ret tup(ann_to_type_params(cx.node_types, a),
            ann_to_type(cx.node_types, a));
1769 1770
}

1771
fn expr_has_ty_params(&node_type_table ntt, &@ast::expr expr) -> bool {
1772
    ret ann_has_type_params(ntt, expr_ann(expr));
1773 1774
}

1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794
fn stmt_ann(&@ast::stmt s) -> ast::ann {
    alt (s.node) {
        case (ast::stmt_decl(_, ?a)) { ret a; }
        case (ast::stmt_expr(_, ?a)) { ret a; }
        case (ast::stmt_crate_directive(_)) {
            log_err "ty::stmt_ann(): crate directive found";
            fail;
        }
    }
}

fn pat_ann(&@ast::pat p) -> ast::ann {
    alt (p.node) {
        case (ast::pat_wild(?a))        { ret a; }
        case (ast::pat_bind(_, _, ?a))  { ret a; }
        case (ast::pat_lit(_, ?a))      { ret a; }
        case (ast::pat_tag(_, _, ?a))   { ret a; }
    }
}

1795

1796 1797
// Expression utilities

1798 1799
fn field_num(&session::session sess, &span sp,
             &ast::ident id) -> uint {
1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
    let uint accum = 0u;
    let uint i = 0u;
    for (u8 c in id) {
        if (i == 0u) {
            if (c != ('_' as u8)) {
                sess.span_err(sp,
                              "bad numeric field on tuple: "
                              + "missing leading underscore");
            }
        } else {
            if (('0' as u8) <= c && c <= ('9' as u8)) {
                accum *= 10u;
                accum += (c as uint) - ('0' as uint);
            } else {
                auto s = "";
1815
                s += str::unsafe_from_byte(c);
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826
                sess.span_err(sp,
                              "bad numeric field on tuple: "
                              + " non-digit character: "
                              + s);
            }
        }
        i += 1u;
    }
    ret accum;
}

1827 1828
fn field_idx(&session::session sess, &span sp,
             &ast::ident id, &vec[field] fields) -> uint {
1829 1830
    let uint i = 0u;
    for (field f in fields) {
1831
        if (str::eq(f.ident, id)) {
1832 1833 1834 1835 1836 1837 1838 1839
            ret i;
        }
        i += 1u;
    }
    sess.span_err(sp, "unknown field '" + id + "' of record");
    fail;
}

1840 1841
fn method_idx(&session::session sess, &span sp,
              &ast::ident id, &vec[method] meths) -> uint {
1842 1843
    let uint i = 0u;
    for (method m in meths) {
1844
        if (str::eq(m.ident, id)) {
1845 1846 1847 1848 1849 1850 1851 1852
            ret i;
        }
        i += 1u;
    }
    sess.span_err(sp, "unknown method '" + id + "' of obj");
    fail;
}

1853
fn sort_methods(&vec[method] meths) -> vec[method] {
1854
    fn method_lteq(&method a, &method b) -> bool {
1855
        ret str::lteq(a.ident, b.ident);
1856 1857
    }

1858
    ret std::sort::merge_sort[method](bind method_lteq(_,_), meths);
1859 1860
}

1861
fn is_lval(&@ast::expr expr) -> bool {
1862
    alt (expr.node) {
1863 1864 1865 1866
        case (ast::expr_field(_,_,_))    { ret true;  }
        case (ast::expr_index(_,_,_))    { ret true;  }
        case (ast::expr_path(_,_))       { ret true;  }
        case (ast::expr_unary(ast::deref,_,_))  { ret true; }
1867 1868 1869 1870
        case (_)                        { ret false; }
    }
}

1871 1872 1873 1874
// Type unification via Robinson's algorithm (Robinson 1965). Implemented as
// described in Hoder and Voronkov:
//
//     http://www.cs.man.ac.uk/~hoderk/ubench/unification_full.pdf
1875

1876
mod unify {
1877
    tag result {
1878 1879
        ures_ok(t);
        ures_err(type_err, t, t);
1880 1881
    }

1882 1883 1884 1885 1886
    tag set_result {
        usr_ok(vec[t]);
        usr_err(type_err, t, t);
    }

1887 1888
    type bindings[T] = rec(ufind::ufind sets,
                           hashmap[T,uint] ids,
1889
                           mutable vec[mutable option::t[t]] types);
1890

1891 1892
    fn mk_bindings[T](map::hashfn[T] hasher, map::eqfn[T] eqer)
            -> @bindings[T] {
1893
        let vec[mutable option::t[t]] types = [mutable];
1894
        ret @rec(sets=ufind::make(),
1895
                 ids=map::mk_hashmap[T,uint](hasher, eqer),
1896
                 mutable types=types);
1897 1898
    }

1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923
    fn record_binding[T](&@ctxt cx, &@bindings[T] bindings, &T key, t typ)
            -> result {
        auto n = get_or_create_set[T](bindings, key);

        auto result_type = typ;
        if (n < vec::len[option::t[t]](bindings.types)) {
            alt (bindings.types.(n)) {
                case (some[t](?old_type)) {
                    alt (unify_step(cx, old_type, typ)) {
                        case (ures_ok(?unified_type)) {
                            result_type = unified_type;
                        }
                        case (?res) { ret res; }
                    }
                }
                case (none[t]) { /* fall through */ }
            }
        }

        vec::grow_set[option::t[t]](bindings.types, n, none[t],
                                    some[t](result_type));

        ret ures_ok(typ);
    }

1924
    type ctxt = rec(@bindings[int] bindings,
1925
                    unify_handler handler,
1926
                    ty_ctxt tcx);
1927

1928 1929 1930 1931 1932 1933 1934 1935
    // Wraps the given type in an appropriate cname.
    //
    // TODO: This doesn't do anything yet. We should carry the cname up from
    // the expected and/or actual types when unification results in a type
    // identical to one or both of the two. The precise algorithm for this is
    // something we'll probably need to develop over time.

    // Simple structural type comparison.
1936
    fn struct_cmp(@ctxt cx, t expected, t actual) -> result {
1937
        if (struct(cx.tcx, expected) == struct(cx.tcx, actual)) {
1938 1939 1940 1941 1942 1943
            ret ures_ok(expected);
        }

        ret ures_err(terr_mismatch, expected, actual);
    }

1944
    // Unifies two mutability flags.
1945 1946
    fn unify_mut(ast::mutability expected, ast::mutability actual)
            -> option::t[ast::mutability] {
1947
        if (expected == actual) {
1948
            ret some[ast::mutability](expected);
1949
        }
1950 1951
        if (expected == ast::maybe_mut) {
            ret some[ast::mutability](actual);
1952
        }
1953 1954
        if (actual == ast::maybe_mut) {
            ret some[ast::mutability](expected);
1955
        }
1956
        ret none[ast::mutability];
1957 1958
    }

1959
    tag fn_common_res {
1960
        fn_common_res_err(result);
1961
        fn_common_res_ok(vec[arg], t);
1962
    }
G
Graydon Hoare 已提交
1963

1964 1965 1966 1967 1968
    fn unify_fn_common(&@ctxt cx,
                       &t expected,
                       &t actual,
                       &vec[arg] expected_inputs, &t expected_output,
                       &vec[arg] actual_inputs, &t actual_output)
1969
        -> fn_common_res {
1970 1971
        auto expected_len = vec::len[arg](expected_inputs);
        auto actual_len = vec::len[arg](actual_inputs);
1972
        if (expected_len != actual_len) {
1973 1974
            ret fn_common_res_err(ures_err(terr_arg_count,
                                           expected, actual));
1975
        }
G
Graydon Hoare 已提交
1976

1977
        // TODO: as above, we should have an iter2 iterator.
1978
        let vec[arg] result_ins = [];
1979 1980 1981 1982 1983
        auto i = 0u;
        while (i < expected_len) {
            auto expected_input = expected_inputs.(i);
            auto actual_input = actual_inputs.(i);

1984
            // Unify the result modes. "mo_either" unifies with both modes.
1985
            auto result_mode;
1986 1987 1988 1989 1990
            if (expected_input.mode == mo_either) {
                result_mode = actual_input.mode;
            } else if (actual_input.mode == mo_either) {
                result_mode = expected_input.mode;
            } else if (expected_input.mode != actual_input.mode) {
1991
                // FIXME this is the wrong error
1992 1993
                ret fn_common_res_err(ures_err(terr_arg_count,
                                               expected, actual));
1994
            } else {
1995
                result_mode = expected_input.mode;
1996
            }
G
Graydon Hoare 已提交
1997

1998
            auto result = unify_step(cx, actual_input.ty, expected_input.ty);
G
Graydon Hoare 已提交
1999

2000 2001
            alt (result) {
                case (ures_ok(?rty)) {
2002
                    result_ins += [rec(mode=result_mode, ty=rty)];
2003 2004 2005
                }

                case (_) {
2006
                    ret fn_common_res_err(result);
2007 2008
                }
            }
G
Graydon Hoare 已提交
2009

2010
            i += 1u;
G
Graydon Hoare 已提交
2011 2012
        }

2013
        // Check the output.
2014
        auto result = unify_step(cx, expected_output, actual_output);
2015 2016
        alt (result) {
            case (ures_ok(?rty)) {
2017
                ret fn_common_res_ok(result_ins, rty);
2018 2019 2020
            }

            case (_) {
2021
                ret fn_common_res_err(result);
2022
            }
G
Graydon Hoare 已提交
2023
        }
2024
    }
G
Graydon Hoare 已提交
2025

2026
    fn unify_fn(&@ctxt cx,
2027 2028
                &ast::proto e_proto,
                &ast::proto a_proto,
2029 2030 2031 2032
                &t expected,
                &t actual,
                &vec[arg] expected_inputs, &t expected_output,
                &vec[arg] actual_inputs, &t actual_output)
2033
        -> result {
G
Graydon Hoare 已提交
2034

2035 2036 2037
        if (e_proto != a_proto) {
            ret ures_err(terr_mismatch, expected, actual);
        }
2038 2039
        auto t = unify_fn_common(cx, expected, actual,
                                 expected_inputs, expected_output,
2040 2041 2042 2043 2044 2045
                                 actual_inputs, actual_output);
        alt (t) {
            case (fn_common_res_err(?r)) {
                ret r;
            }
            case (fn_common_res_ok(?result_ins, ?result_out)) {
2046
                auto t2 = mk_fn(cx.tcx, e_proto, result_ins, result_out);
2047 2048 2049 2050 2051
                ret ures_ok(t2);
            }
        }
    }

2052
    fn unify_native_fn(&@ctxt cx,
2053 2054
                       &ast::native_abi e_abi,
                       &ast::native_abi a_abi,
2055 2056 2057 2058
                       &t expected,
                       &t actual,
                       &vec[arg] expected_inputs, &t expected_output,
                       &vec[arg] actual_inputs, &t actual_output)
2059
        -> result {
2060 2061 2062 2063
        if (e_abi != a_abi) {
            ret ures_err(terr_mismatch, expected, actual);
        }

2064 2065
        auto t = unify_fn_common(cx, expected, actual,
                                 expected_inputs, expected_output,
2066 2067 2068 2069 2070 2071
                                 actual_inputs, actual_output);
        alt (t) {
            case (fn_common_res_err(?r)) {
                ret r;
            }
            case (fn_common_res_ok(?result_ins, ?result_out)) {
2072
                auto t2 = mk_native_fn(cx.tcx, e_abi, result_ins,
2073
                                       result_out);
2074 2075 2076
                ret ures_ok(t2);
            }
        }
G
Graydon Hoare 已提交
2077 2078
    }

2079 2080 2081 2082 2083
    fn unify_obj(&@ctxt cx,
                 &t expected,
                 &t actual,
                 &vec[method] expected_meths,
                 &vec[method] actual_meths) -> result {
2084
      let vec[method] result_meths = [];
G
Graydon Hoare 已提交
2085
      let uint i = 0u;
2086 2087
      let uint expected_len = vec::len[method](expected_meths);
      let uint actual_len = vec::len[method](actual_meths);
G
Graydon Hoare 已提交
2088 2089 2090 2091 2092 2093 2094 2095

      if (expected_len != actual_len) {
        ret ures_err(terr_meth_count, expected, actual);
      }

      while (i < expected_len) {
        auto e_meth = expected_meths.(i);
        auto a_meth = actual_meths.(i);
2096
        if (! str::eq(e_meth.ident, a_meth.ident)) {
G
Graydon Hoare 已提交
2097 2098 2099
          ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident),
                       expected, actual);
        }
2100
        auto r = unify_fn(cx,
2101
                          e_meth.proto, a_meth.proto,
2102
                          expected, actual,
G
Graydon Hoare 已提交
2103 2104
                          e_meth.inputs, e_meth.output,
                          a_meth.inputs, a_meth.output);
B
Brian Anderson 已提交
2105 2106
        alt (r) {
            case (ures_ok(?tfn)) {
2107
                alt (struct(cx.tcx, tfn)) {
B
Brian Anderson 已提交
2108
                    case (ty_fn(?proto, ?ins, ?out)) {
2109
                        result_meths += [rec(inputs = ins,
B
Brian Anderson 已提交
2110
                                                output = out
2111
                                                with e_meth)];
B
Brian Anderson 已提交
2112 2113 2114 2115 2116 2117
                    }
                }
            }
            case (_) {
                ret r;
            }
G
Graydon Hoare 已提交
2118 2119 2120
        }
        i += 1u;
      }
2121
      auto t = mk_obj(cx.tcx, result_meths);
G
Graydon Hoare 已提交
2122 2123 2124
      ret ures_ok(t);
    }

2125
    fn get_or_create_set[T](&@bindings[T] bindings, &T key) -> uint {
2126
        auto set_num;
2127
        alt (bindings.ids.find(key)) {
2128
            case (none[uint]) {
2129 2130
                set_num = ufind::make_set(bindings.sets);
                bindings.ids.insert(key, set_num);
2131 2132
            }
            case (some[uint](?n)) { set_num = n; }
2133
        }
2134
        ret set_num;
2135 2136
    }

2137
    fn unify_step(&@ctxt cx, &t expected, &t actual) -> result {
2138 2139 2140
        // TODO: rewrite this using tuple pattern matching when available, to
        // avoid all this rightward drift and spikiness.

2141 2142 2143
        // TODO: occurs check, to make sure we don't loop forever when
        // unifying e.g. 'a and option['a]

2144 2145 2146
        // Fast path.
        if (eq_ty(expected, actual)) { ret ures_ok(expected); }

2147
        alt (struct(cx.tcx, actual)) {
2148 2149
            // If the RHS is a variable type, then just do the appropriate
            // binding.
2150
            case (ty::ty_var(?actual_id)) {
2151 2152
                auto actual_n = get_or_create_set[int](cx.bindings,
                                                       actual_id);
2153
                alt (struct(cx.tcx, expected)) {
2154
                    case (ty::ty_var(?expected_id)) {
2155 2156
                        auto expected_n = get_or_create_set[int](cx.bindings,
                                                                 expected_id);
2157
                        ufind::union(cx.bindings.sets, expected_n, actual_n);
2158 2159 2160 2161
                    }

                    case (_) {
                        // Just bind the type variable to the expected type.
2162 2163 2164 2165
                        alt (record_binding[int](cx, cx.bindings, actual_id,
                                                 expected)) {
                            case (ures_ok(_)) { /* fall through */ }
                            case (?res) { ret res; }
2166 2167 2168 2169
                        }
                    }
                }
                ret ures_ok(actual);
2170
            }
2171
            case (ty::ty_local(?actual_id)) {
2172
                auto result_ty;
2173
                alt (cx.handler.resolve_local(actual_id)) {
2174 2175
                    case (none[t]) { result_ty = expected; }
                    case (some[t](?actual_ty)) {
2176
                        auto result = unify_step(cx, expected, actual_ty);
2177 2178 2179 2180
                        alt (result) {
                            case (ures_ok(?rty)) { result_ty = rty; }
                            case (_) { ret result; }
                        }
2181 2182
                    }
                }
2183

2184
                cx.handler.record_local(actual_id, result_ty);
2185
                ret ures_ok(result_ty);
2186
            }
2187
            case (ty::ty_bound_param(?actual_id)) {
2188
                alt (struct(cx.tcx, expected)) {
2189
                    case (ty::ty_local(_)) {
2190
                        log_err "TODO: bound param unifying with local";
2191 2192
                        fail;
                    }
2193 2194

                    case (_) {
2195
                        ret cx.handler.record_param(actual_id, expected);
2196 2197
                    }
                }
2198
            }
2199 2200 2201
            case (_) { /* empty */ }
        }

2202
        alt (struct(cx.tcx, expected)) {
2203
            case (ty::ty_nil)        { ret struct_cmp(cx, expected, actual); }
2204
            case (ty::ty_bot)        { ret struct_cmp(cx, expected, actual); }
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216
            case (ty::ty_bool)       { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_int)        { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_uint)       { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_machine(_)) { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_float)      { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_char)       { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_str)        { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_type)       { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_native)     { ret struct_cmp(cx, expected, actual); }
            case (ty::ty_param(_))   { ret struct_cmp(cx, expected, actual); }

            case (ty::ty_tag(?expected_id, ?expected_tps)) {
2217
                alt (struct(cx.tcx, actual)) {
2218
                    case (ty::ty_tag(?actual_id, ?actual_tps)) {
2219 2220 2221
                        if (expected_id._0 != actual_id._0 ||
                                expected_id._1 != actual_id._1) {
                            ret ures_err(terr_mismatch, expected, actual);
2222
                        }
2223 2224

                        // TODO: factor this cruft out, see the TODO in the
2225
                        // ty::ty_tup case
2226
                        let vec[t] result_tps = [];
2227
                        auto i = 0u;
2228
                        auto expected_len = vec::len[t](expected_tps);
2229 2230 2231 2232
                        while (i < expected_len) {
                            auto expected_tp = expected_tps.(i);
                            auto actual_tp = actual_tps.(i);

2233
                            auto result = unify_step(cx,
2234
                                                     expected_tp,
2235
                                                     actual_tp);
2236 2237 2238

                            alt (result) {
                                case (ures_ok(?rty)) {
2239
                                    vec::push[t](result_tps, rty);
2240 2241 2242 2243 2244 2245 2246 2247 2248
                                }
                                case (_) {
                                    ret result;
                                }
                            }

                            i += 1u;
                        }

2249
                        ret ures_ok(mk_tag(cx.tcx, expected_id, result_tps));
2250 2251 2252 2253 2254 2255 2256
                    }
                    case (_) { /* fall through */ }
                }

                ret ures_err(terr_mismatch, expected, actual);
            }

2257
            case (ty::ty_box(?expected_mt)) {
2258
                alt (struct(cx.tcx, actual)) {
2259
                    case (ty::ty_box(?actual_mt)) {
2260 2261
                        auto mut;
                        alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
2262
                            case (none[ast::mutability]) {
2263 2264 2265
                                ret ures_err(terr_box_mutability, expected,
                                             actual);
                            }
2266
                            case (some[ast::mutability](?m)) { mut = m; }
2267 2268
                        }

2269
                        auto result = unify_step(cx,
2270
                                                 expected_mt.ty,
2271
                                                 actual_mt.ty);
2272 2273
                        alt (result) {
                            case (ures_ok(?result_sub)) {
2274
                                auto mt = rec(ty=result_sub, mut=mut);
2275
                                ret ures_ok(mk_box(cx.tcx, mt));
2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288
                            }
                            case (_) {
                                ret result;
                            }
                        }
                    }

                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

2289
            case (ty::ty_vec(?expected_mt)) {
2290
                alt (struct(cx.tcx, actual)) {
2291
                    case (ty::ty_vec(?actual_mt)) {
2292 2293
                        auto mut;
                        alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
2294
                            case (none[ast::mutability]) {
2295 2296 2297
                                ret ures_err(terr_vec_mutability, expected,
                                             actual);
                            }
2298
                            case (some[ast::mutability](?m)) { mut = m; }
2299 2300
                        }

2301
                        auto result = unify_step(cx,
2302
                                                 expected_mt.ty,
2303
                                                 actual_mt.ty);
2304 2305
                        alt (result) {
                            case (ures_ok(?result_sub)) {
2306
                                auto mt = rec(ty=result_sub, mut=mut);
2307
                                ret ures_ok(mk_vec(cx.tcx, mt));
2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320
                            }
                            case (_) {
                                ret result;
                            }
                        }
                    }

                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                   }
                }
            }

2321
            case (ty::ty_port(?expected_sub)) {
2322
                alt (struct(cx.tcx, actual)) {
2323
                    case (ty::ty_port(?actual_sub)) {
2324
                        auto result = unify_step(cx,
2325
                                                 expected_sub,
2326
                                                 actual_sub);
2327 2328
                        alt (result) {
                            case (ures_ok(?result_sub)) {
2329
                                ret ures_ok(mk_port(cx.tcx, result_sub));
2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342
                            }
                            case (_) {
                                ret result;
                            }
                        }
                    }

                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

2343
            case (ty::ty_chan(?expected_sub)) {
2344
                alt (struct(cx.tcx, actual)) {
2345
                    case (ty::ty_chan(?actual_sub)) {
2346
                        auto result = unify_step(cx,
2347
                                                 expected_sub,
2348
                                                 actual_sub);
2349 2350
                        alt (result) {
                            case (ures_ok(?result_sub)) {
2351
                                ret ures_ok(mk_chan(cx.tcx, result_sub));
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364
                            }
                            case (_) {
                                ret result;
                            }
                        }
                    }

                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

2365
            case (ty::ty_tup(?expected_elems)) {
2366
                alt (struct(cx.tcx, actual)) {
2367
                    case (ty::ty_tup(?actual_elems)) {
2368 2369
                        auto expected_len = vec::len[ty::mt](expected_elems);
                        auto actual_len = vec::len[ty::mt](actual_elems);
2370 2371 2372 2373 2374 2375 2376 2377
                        if (expected_len != actual_len) {
                            auto err = terr_tuple_size(expected_len,
                                                       actual_len);
                            ret ures_err(err, expected, actual);
                        }

                        // TODO: implement an iterator that can iterate over
                        // two arrays simultaneously.
2378
                        let vec[ty::mt] result_elems = [];
2379 2380 2381 2382
                        auto i = 0u;
                        while (i < expected_len) {
                            auto expected_elem = expected_elems.(i);
                            auto actual_elem = actual_elems.(i);
2383 2384 2385 2386

                            auto mut;
                            alt (unify_mut(expected_elem.mut,
                                           actual_elem.mut)) {
2387
                                case (none[ast::mutability]) {
2388 2389 2390
                                    auto err = terr_tuple_mutability;
                                    ret ures_err(err, expected, actual);
                                }
2391
                                case (some[ast::mutability](?m)) { mut = m; }
2392 2393
                            }

2394
                            auto result = unify_step(cx,
2395
                                                     expected_elem.ty,
2396
                                                     actual_elem.ty);
2397 2398
                            alt (result) {
                                case (ures_ok(?rty)) {
2399
                                    auto mt = rec(ty=rty, mut=mut);
2400
                                    result_elems += [mt];
2401 2402 2403 2404 2405 2406 2407 2408 2409
                                }
                                case (_) {
                                    ret result;
                                }
                            }

                            i += 1u;
                        }

2410
                        ret ures_ok(mk_tup(cx.tcx, result_elems));
2411 2412 2413 2414 2415 2416 2417 2418
                    }

                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

2419
            case (ty::ty_rec(?expected_fields)) {
2420
                alt (struct(cx.tcx, actual)) {
2421
                    case (ty::ty_rec(?actual_fields)) {
2422 2423
                        auto expected_len = vec::len[field](expected_fields);
                        auto actual_len = vec::len[field](actual_fields);
2424 2425 2426 2427 2428 2429 2430 2431
                        if (expected_len != actual_len) {
                            auto err = terr_record_size(expected_len,
                                                        actual_len);
                            ret ures_err(err, expected, actual);
                        }

                        // TODO: implement an iterator that can iterate over
                        // two arrays simultaneously.
2432
                        let vec[field] result_fields = [];
2433 2434 2435 2436
                        auto i = 0u;
                        while (i < expected_len) {
                            auto expected_field = expected_fields.(i);
                            auto actual_field = actual_fields.(i);
2437 2438 2439 2440

                            auto mut;
                            alt (unify_mut(expected_field.mt.mut,
                                           actual_field.mt.mut)) {
2441
                                case (none[ast::mutability]) {
2442 2443 2444
                                    ret ures_err(terr_record_mutability,
                                                 expected, actual);
                                }
2445
                                case (some[ast::mutability](?m)) { mut = m; }
2446 2447
                            }

2448
                            if (!str::eq(expected_field.ident,
2449
                                         actual_field.ident)) {
2450 2451 2452 2453 2454 2455
                                auto err =
                                    terr_record_fields(expected_field.ident,
                                                       actual_field.ident);
                                ret ures_err(err, expected, actual);
                            }

2456
                            auto result = unify_step(cx,
2457
                                                     expected_field.mt.ty,
2458
                                                     actual_field.mt.ty);
2459 2460
                            alt (result) {
                                case (ures_ok(?rty)) {
2461
                                    auto mt = rec(ty=rty, mut=mut);
2462
                                    vec::push[field]
2463
                                        (result_fields,
2464
                                         rec(mt=mt with expected_field));
2465 2466 2467 2468 2469 2470 2471 2472 2473
                                }
                                case (_) {
                                    ret result;
                                }
                            }

                            i += 1u;
                        }

2474
                        ret ures_ok(mk_rec(cx.tcx, result_fields));
2475 2476 2477 2478 2479 2480 2481 2482
                    }

                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

2483
            case (ty::ty_fn(?ep, ?expected_inputs, ?expected_output)) {
2484
                alt (struct(cx.tcx, actual)) {
2485
                    case (ty::ty_fn(?ap, ?actual_inputs, ?actual_output)) {
2486 2487
                        ret unify_fn(cx, ep, ap,
                                     expected, actual,
2488 2489
                                     expected_inputs, expected_output,
                                     actual_inputs, actual_output);
2490 2491 2492 2493 2494 2495 2496 2497
                    }

                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

2498
            case (ty::ty_native_fn(?e_abi, ?expected_inputs,
2499
                                  ?expected_output)) {
2500
                alt (struct(cx.tcx, actual)) {
2501
                    case (ty::ty_native_fn(?a_abi, ?actual_inputs,
2502
                                          ?actual_output)) {
2503 2504
                        ret unify_native_fn(cx, e_abi, a_abi,
                                            expected, actual,
2505 2506 2507 2508 2509 2510 2511 2512 2513
                                            expected_inputs, expected_output,
                                            actual_inputs, actual_output);
                    }
                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

2514
            case (ty::ty_obj(?expected_meths)) {
2515
                alt (struct(cx.tcx, actual)) {
2516
                    case (ty::ty_obj(?actual_meths)) {
2517
                        ret unify_obj(cx, expected, actual,
2518 2519 2520 2521 2522
                                      expected_meths, actual_meths);
                    }
                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
G
Graydon Hoare 已提交
2523 2524 2525
                }
            }

2526
            case (ty::ty_var(?expected_id)) {
2527 2528 2529 2530 2531
                // Add a binding. (`actual` can't actually be a var here.)
                alt (record_binding[int](cx, cx.bindings, expected_id,
                                         actual)) {
                    case (ures_ok(_)) { /* fall through */ }
                    case (?res) { ret res; }
2532 2533
                }
                ret ures_ok(expected);
2534 2535
            }

2536
            case (ty::ty_local(?expected_id)) {
2537
                auto result_ty;
2538
                alt (cx.handler.resolve_local(expected_id)) {
2539 2540
                    case (none[t]) { result_ty = actual; }
                    case (some[t](?expected_ty)) {
2541
                        auto result = unify_step(cx, expected_ty, actual);
2542 2543 2544 2545
                        alt (result) {
                            case (ures_ok(?rty)) { result_ty = rty; }
                            case (_) { ret result; }
                        }
2546 2547
                    }
                }
2548

2549
                cx.handler.record_local(expected_id, result_ty);
2550
                ret ures_ok(result_ty);
2551 2552
            }

2553
            case (ty::ty_bound_param(?expected_id)) {
2554
                ret cx.handler.record_param(expected_id, actual);
2555 2556 2557 2558 2559 2560 2561
            }
        }

        // TODO: remove me once match-exhaustiveness checking works
        fail;
    }

2562
    // Performs type binding substitution.
2563 2564 2565 2566
    fn substitute(&ty_ctxt tcx,
                  &@bindings[int] bindings,
                  &vec[t] set_types,
                  &t typ) -> t {
2567
        if (!type_contains_vars(tcx, typ)) {
2568 2569 2570
            ret typ;
        }

2571 2572 2573
        fn substituter(ty_ctxt tcx,
                       @bindings[int] bindings,
                       vec[t] types,
2574 2575
                       t typ) -> t {
            alt (struct(tcx, typ)) {
2576
                case (ty_var(?id)) {
2577
                    alt (bindings.ids.find(id)) {
2578
                        case (some[uint](?n)) {
2579
                            auto root = ufind::find(bindings.sets, n);
2580 2581 2582
                            ret types.(root);
                        }
                        case (none[uint]) { ret typ; }
2583 2584
                    }
                }
2585 2586 2587 2588
                case (_) { ret typ; }
            }
        }

2589
        auto f = bind substituter(tcx, bindings, set_types, _);
2590
        ret fold_ty(tcx, f, typ);
2591 2592
    }

2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606
    fn unify_sets[T](&ty_ctxt tcx, &@bindings[T] bindings) -> set_result {
        obj handler() {
            fn resolve_local(ast::def_id id) -> option::t[t] {
                log_err "resolve_local in unify_sets";
                fail;
            }
            fn record_local(ast::def_id id, t ty) {
                log_err "record_local in unify_sets";
                fail;
            }
            fn record_param(uint index, t binding) -> unify::result {
                log_err "record_param in unify_sets";
                fail;
            }
2607 2608
        }

2609 2610 2611 2612 2613
        auto node_count = vec::len[option::t[t]](bindings.types);

        let vec[option::t[t]] results =
            vec::init_elt[option::t[t]](none[t], node_count);

2614
        auto i = 0u;
2615
        while (i < node_count) {
2616
            auto root = ufind::find(bindings.sets, i);
2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638
            alt (bindings.types.(i)) {
                case (none[t]) { /* nothing to do */ }
                case (some[t](?actual)) {
                    alt (results.(root)) {
                        case (none[t]) { results.(root) = some[t](actual); }
                        case (some[t](?expected)) {
                            // FIXME: Is this right?
                            auto bindings = mk_bindings[int](int::hash,
                                                             int::eq_alias);
                            alt (unify(expected, actual, handler(), bindings,
                                    tcx)) {
                                case (ures_ok(?result_ty)) {
                                    results.(i) = some[t](result_ty);
                                }
                                case (ures_err(?e, ?t_a, ?t_b)) {
                                    ret usr_err(e, t_a, t_b);
                                }
                            }
                        }
                    }
                }
            }
2639 2640 2641
            i += 1u;
        }

2642 2643 2644 2645 2646
        // FIXME: This is equivalent to map(option::get, results) but it
        // causes an assertion in typeck at the moment.
        let vec[t] real_results = [];
        for (option::t[t] typ in results) {
            real_results += [option::get[t](typ)];
2647 2648
        }

2649
        ret usr_ok(real_results);
2650 2651
    }

2652 2653
    fn unify(&t expected,
             &t actual,
2654
             &unify_handler handler,
2655
             &@bindings[int] bindings,
2656
             &ty_ctxt tcx) -> result {
2657
        auto cx = @rec(bindings=bindings, handler=handler, tcx=tcx);
2658 2659
        ret unify_step(cx, expected, actual);
    }
2660

2661 2662 2663 2664 2665 2666 2667
    fn fixup(&ty_ctxt tcx, &@bindings[int] bindings, t typ) -> result {
        alt (unify_sets[int](tcx, bindings)) {
            case (usr_ok(?set_types)) {
                ret ures_ok(substitute(tcx, bindings, set_types, typ));
            }
            case (usr_err(?terr, ?t0, ?t1)) { ret ures_err(terr, t0, t1); }
        }
2668
    }
2669 2670
}

2671
fn type_err_to_str(&ty::type_err err) -> str {
2672 2673 2674 2675
    alt (err) {
        case (terr_mismatch) {
            ret "types differ";
        }
2676 2677 2678 2679 2680 2681
        case (terr_box_mutability) {
            ret "boxed values differ in mutability";
        }
        case (terr_vec_mutability) {
            ret "vectors differ in mutability";
        }
2682
        case (terr_tuple_size(?e_sz, ?a_sz)) {
2683 2684
            ret "expected a tuple with " + uint::to_str(e_sz, 10u) +
                " elements but found one with " + uint::to_str(a_sz, 10u) +
2685 2686 2687 2688 2689 2690
                " elements";
        }
        case (terr_tuple_mutability) {
            ret "tuple elements differ in mutability";
        }
        case (terr_record_size(?e_sz, ?a_sz)) {
2691 2692
            ret "expected a record with " + uint::to_str(e_sz, 10u) +
                " fields but found one with " + uint::to_str(a_sz, 10u) +
2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705
                " fields";
        }
        case (terr_record_mutability) {
            ret "record elements differ in mutability";
        }
        case (terr_record_fields(?e_fld, ?a_fld)) {
            ret "expected a record with field '" + e_fld +
                "' but found one with field '" + a_fld +
                "'";
        }
        case (terr_arg_count) {
            ret "incorrect number of function parameters";
        }
G
Graydon Hoare 已提交
2706 2707 2708 2709 2710 2711 2712 2713
        case (terr_meth_count) {
            ret "incorrect number of object methods";
        }
        case (terr_obj_meths(?e_meth, ?a_meth)) {
            ret "expected an obj with method '" + e_meth +
                "' but found one with method '" + a_meth +
                "'";
        }
2714 2715 2716
    }
}

2717
// Performs bound type parameter replacement using the supplied mapping from
2718
// parameter IDs to types.
2719
fn substitute_type_params(&ctxt cx, &vec[t] bindings, &t typ) -> t {
2720
    if (!type_contains_bound_params(cx, typ)) {
2721 2722
        ret typ;
    }
2723
    fn replacer(&ctxt cx, vec[t] bindings, t typ) -> t {
2724
        alt (struct(cx, typ)) {
2725 2726
            case (ty_bound_param(?param_index)) {
                ret bindings.(param_index);
2727
            }
2728
            case (_) { ret typ; }
2729 2730
        }
    }
2731

2732 2733
    auto f = bind replacer(cx, bindings, _);
    ret fold_ty(cx, f, typ);
2734 2735
}

2736
// Converts type parameters in a type to bound type parameters.
2737
fn bind_params_in_type(&ctxt cx, &t typ) -> t {
2738 2739 2740
    if (!type_contains_params(cx, typ)) {
        ret typ;
    }
2741
    fn binder(&ctxt cx, t typ) -> t {
2742
        alt (struct(cx, typ)) {
2743
            case (ty_bound_param(?index)) {
2744
                log_err "bind_params_in_type() called on type that already " +
2745 2746
                    "has bound params in it";
                fail;
2747
            }
2748
            case (ty_param(?index)) { ret mk_bound_param(cx, index); }
2749
            case (_) { ret typ; }
2750 2751 2752
        }
    }

2753 2754
    auto f = bind binder(cx, _);
    ret fold_ty(cx, f, typ);
2755 2756
}

2757

2758
fn def_has_ty_params(&ast::def def) -> bool {
2759
    alt (def) {
2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773
        case (ast::def_fn(_))            { ret true;  }
        case (ast::def_obj(_))           { ret true;  }
        case (ast::def_obj_field(_))     { ret false; }
        case (ast::def_mod(_))           { ret false; }
        case (ast::def_const(_))         { ret false; }
        case (ast::def_arg(_))           { ret false; }
        case (ast::def_local(_))         { ret false; }
        case (ast::def_variant(_, _))    { ret true;  }
        case (ast::def_ty(_))            { ret false; }
        case (ast::def_ty_arg(_))        { ret false; }
        case (ast::def_binding(_))       { ret false; }
        case (ast::def_use(_))           { ret false; }
        case (ast::def_native_ty(_))     { ret false; }
        case (ast::def_native_fn(_))     { ret true;  }
2774 2775 2776 2777 2778
    }
}

// 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.
2779
fn lookup_item_type(session::session sess,
2780
                    ctxt cx, ast::def_id did) -> ty_param_count_and_ty {
2781 2782 2783
    if (did._0 == sess.get_targ_crate_num()) {
        // The item is in this crate. The caller should have added it to the
        // type cache already; we simply return it.
2784
        ret cx.tcache.get(did);
2785 2786
    }

2787
    alt (cx.tcache.find(did)) {
2788 2789
        case (some[ty_param_count_and_ty](?tpt)) { ret tpt; }
        case (none[ty_param_count_and_ty]) {
2790
            auto tyt = creader::get_type(sess, cx, did);
2791
            cx.tcache.insert(did, tyt);
2792 2793
            ret tyt;
        }
2794 2795 2796
    }
}

2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807
fn ret_ty_of_fn_ty(ty_ctxt tcx, t a_ty) -> t {
    alt (ty::struct(tcx, a_ty)) {
        case (ty::ty_fn(_, _, ?ret_ty)) {
            ret ret_ty;
        }
        case (_) { 
            fail;
        }
    }
}

2808 2809
fn ret_ty_of_fn(ty_ctxt tcx, ast::ann ann) -> t {
    ret ret_ty_of_fn_ty(tcx, ann_to_type(tcx.node_types, ann));
2810
}
2811

2812 2813 2814 2815 2816 2817
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2818
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2819
// End: