ty.rs 88.4 KB
Newer Older
1 2 3
import std.Str;
import std.UInt;
import std.Vec;
4
import std.Box;
5
import std.UFind;
6 7 8 9 10
import std.Map;
import std.Map.hashmap;
import std.Option;
import std.Option.none;
import std.Option.some;
11 12 13 14

import driver.session;
import front.ast;
import front.ast.mutability;
15
import front.creader;
16
import middle.metadata;
17
import util.common;
18 19 20 21 22 23 24 25 26 27 28 29 30 31

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;

32
import util.common.new_def_hash;
33
import util.common.span;
34
import util.typestate_ann.ts_ann;
35 36 37

// Data types

38 39 40 41 42 43 44
tag mode {
    mo_val;
    mo_alias;
    mo_either;
}

type arg = rec(mode mode, t ty);
45
type field = rec(ast.ident ident, mt mt);
46 47 48
type method = rec(ast.proto proto,
                  ast.ident ident,
                  vec[arg] inputs,
49
                  t output);
50

51
type mt = rec(t ty, ast.mutability mut);
52

53 54
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
55 56 57
type creader_cache = hashmap[tup(int,uint,uint),ty.t];
type ctxt = rec(@type_store ts,
                session.session sess,
58
                resolve.def_map def_map,
59 60
                creader_cache rcache,
                hashmap[t,str] short_names_cache);
61 62
type ty_ctxt = ctxt;    // Needed for disambiguation from Unify.ctxt.

63 64
// Convert from method type to function type.  Pretty easy; we just drop
// 'ident'.
65 66
fn method_ty_to_fn_ty(ctxt cx, method m) -> t {
    ret mk_fn(cx, m.proto, m.inputs, m.output);
67 68
}

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

type t = uint;
82

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

114 115 116
// Data structures used in type unification

type unify_handler = obj {
117
    fn resolve_local(ast.def_id id) -> Option.t[t];
118 119
    fn record_local(ast.def_id id, t ty);  // TODO: -> Unify.result
    fn record_param(uint index, t binding) -> Unify.result;
120 121 122 123
};

tag type_err {
    terr_mismatch;
124 125
    terr_box_mutability;
    terr_vec_mutability;
126 127 128 129 130
    terr_tuple_size(uint, uint);
    terr_tuple_mutability;
    terr_record_size(uint, uint);
    terr_record_mutability;
    terr_record_fields(ast.ident,ast.ident);
G
Graydon Hoare 已提交
131 132
    terr_meth_count;
    terr_obj_meths(ast.ident,ast.ident);
133 134 135
    terr_arg_count;
}

136

137
type ty_param_count_and_ty = tup(uint, t);
138
type type_cache = hashmap[ast.def_id,ty_param_count_and_ty];
139

140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
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;
const uint idx_first_others = 20u;

type type_store = rec(mutable vec[raw_t] others,
                      hashmap[raw_t,uint] other_structural);
164

P
Patrick Walton 已提交
165
fn mk_type_store() -> @type_store {
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
    let vec[raw_t] others = vec();
    let hashmap[raw_t,uint] ost =
        Map.mk_hashmap[raw_t,uint](hash_raw_ty, eq_raw_ty);

    auto ts = @rec(mutable others=others, other_structural=ost);

    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]);

    assert Vec.len(ts.others) == idx_first_others;

    ret ts;
196 197
}

198 199 200 201 202 203 204 205 206 207 208 209
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;
210
    ret Map.mk_hashmap[tup(int,uint,uint),t](h, e);
211
}
212

213
fn mk_ctxt(session.session s, resolve.def_map dm) -> ctxt {
214 215
    ret rec(ts = mk_type_store(),
            sess = s,
216
            def_map = dm,
217 218 219
            rcache = mk_rcache(),
            short_names_cache =
                Map.mk_hashmap[ty.t,str](ty.hash_ty, ty.eq_ty));
220
}
221 222


223 224
// Type constructors

225
fn mk_raw_ty(&@type_store ts, &sty st, &Option.t[str] cname) -> raw_t {
226
    auto h = hash_type_info(st, cname);
227 228 229 230 231 232

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

233 234
    fn derive_flags_t(@type_store ts,
                      &mutable bool has_params,
235 236 237 238
                      &mutable bool has_bound_params,
                      &mutable bool has_vars,
                      &mutable bool has_locals,
                      &t tt) {
239 240 241 242 243
        auto rt = ts.others.(tt);
        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;
244 245
    }

246 247
    fn derive_flags_mt(@type_store ts,
                       &mutable bool has_params,
248 249 250 251
                       &mutable bool has_bound_params,
                       &mutable bool has_vars,
                       &mutable bool has_locals,
                       &mt m) {
252
        derive_flags_t(ts, has_params, has_bound_params,
253 254 255 256
                       has_vars, has_locals, m.ty);
    }


257 258
    fn derive_flags_arg(@type_store ts,
                        &mutable bool has_params,
259 260 261 262
                        &mutable bool has_bound_params,
                        &mutable bool has_vars,
                        &mutable bool has_locals,
                        &arg a) {
263
        derive_flags_t(ts, has_params, has_bound_params,
264 265 266
                       has_vars, has_locals, a.ty);
    }

267 268
    fn derive_flags_sig(@type_store ts,
                        &mutable bool has_params,
269 270 271 272 273 274
                        &mutable bool has_bound_params,
                        &mutable bool has_vars,
                        &mutable bool has_locals,
                        &vec[arg] args,
                        &t tt) {
        for (arg a in args) {
275
            derive_flags_arg(ts, has_params, has_bound_params,
276 277
                             has_vars, has_locals, a);
        }
278
        derive_flags_t(ts, has_params, has_bound_params,
279 280 281 282 283 284 285 286 287 288
                       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) {
289
                derive_flags_t(ts, has_params, has_bound_params,
290 291 292 293
                               has_vars, has_locals, tt);
            }
        }
        case (ty_box(?m)) {
294
            derive_flags_mt(ts, has_params, has_bound_params,
295 296 297 298
                            has_vars, has_locals, m);
        }

        case (ty_vec(?m)) {
299
            derive_flags_mt(ts, has_params, has_bound_params,
300 301 302 303
                            has_vars, has_locals, m);
        }

        case (ty_port(?tt)) {
304
            derive_flags_t(ts, has_params, has_bound_params,
305 306 307 308
                           has_vars, has_locals, tt);
        }

        case (ty_chan(?tt)) {
309
            derive_flags_t(ts, has_params, has_bound_params,
310 311 312 313 314
                           has_vars, has_locals, tt);
        }

        case (ty_tup(?mts)) {
            for (mt m in mts) {
315
                derive_flags_mt(ts, has_params, has_bound_params,
316 317 318 319 320 321
                                has_vars, has_locals, m);
            }
        }

        case (ty_rec(?flds)) {
            for (field f in flds) {
322
                derive_flags_mt(ts, has_params, has_bound_params,
323 324 325 326 327
                                has_vars, has_locals, f.mt);
            }
        }

        case (ty_fn(_, ?args, ?tt)) {
328
            derive_flags_sig(ts, has_params, has_bound_params,
329 330 331 332
                             has_vars, has_locals, args, tt);
        }

        case (ty_native_fn(_, ?args, ?tt)) {
333
            derive_flags_sig(ts, has_params, has_bound_params,
334 335 336 337 338
                             has_vars, has_locals, args, tt);
        }

        case (ty_obj(?meths)) {
            for (method m in meths) {
339
                derive_flags_sig(ts, has_params, has_bound_params,
340 341 342 343 344 345 346
                                 has_vars, has_locals,
                                 m.inputs, m.output);
            }
        }
        case (_) { }
    }

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
    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);
}

fn intern_raw_ty(&@type_store ts, &raw_t rt) {
    auto type_num = Vec.len[raw_t](ts.others);
    ts.others += vec(rt);
    ts.other_structural.insert(rt, type_num);
}

fn intern(&@type_store ts, &sty st, &Option.t[str] cname) {
    intern_raw_ty(ts, mk_raw_ty(ts, st, cname));
362
}
P
Patrick Walton 已提交
363

364
fn gen_ty_full(&ctxt cx, &sty st, &Option.t[str] cname) -> t {
365
    auto raw_type = mk_raw_ty(cx.ts, st, cname);
366

P
Patrick Walton 已提交
367
    // Is it interned?
368
    alt (cx.ts.other_structural.find(raw_type)) {
369
        case (some[t](?typ)) {
P
Patrick Walton 已提交
370 371
            ret typ;
        }
372
        case (none[t]) {
P
Patrick Walton 已提交
373
            // Nope. Insert it and return.
374 375 376 377
            auto type_num = Vec.len[raw_t](cx.ts.others);
            intern_raw_ty(cx.ts, raw_type);
            // log_err "added: " + ty_to_str(tystore, raw_type);
            ret type_num;
P
Patrick Walton 已提交
378 379
        }
    }
P
Patrick Walton 已提交
380 381
}

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

388 389 390 391 392
fn mk_nil(&ctxt cx) -> t          { ret idx_nil; }
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; }
393

394
fn mk_mach(&ctxt cx, &util.common.ty_mach tm) -> t {
395
    alt (tm) {
396 397 398 399 400 401 402 403 404 405 406 407
        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; }
408 409
    }
    fail;
410 411
}

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

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

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

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

427 428 429 430
fn mk_vec(&ctxt cx, &mt tm) -> t  { ret gen_ty(cx, ty_vec(tm)); }
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); }
431

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

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

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

445
fn mk_fn(&ctxt cx, &ast.proto proto, &vec[arg] args, &t ty) -> t {
446
    ret gen_ty(cx, ty_fn(proto, args, ty));
447 448
}

449
fn mk_native_fn(&ctxt cx, &ast.native_abi abi, &vec[arg] args, &t ty) -> t {
450
    ret gen_ty(cx, ty_native_fn(abi, args, ty));
451
}
452

453
fn mk_obj(&ctxt cx, &vec[method] meths) -> t {
454
    ret gen_ty(cx, ty_obj(meths));
455 456
}

457
fn mk_var(&ctxt cx, int v) -> t {
458
    ret gen_ty(cx, ty_var(v));
459
}
460

461
fn mk_local(&ctxt cx, ast.def_id did) -> t {
462
    ret gen_ty(cx, ty_local(did));
463 464
}

465
fn mk_param(&ctxt cx, uint n) -> t {
466
    ret gen_ty(cx, ty_param(n));
467 468
}

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

473 474
fn mk_type(&ctxt cx) -> t    { ret idx_type; }
fn mk_native(&ctxt cx) -> t  { ret idx_native; }
475 476


477
// Returns the one-level-deep type structure of the given type.
478
fn struct(&ctxt cx, &t typ) -> sty { ret cx.ts.others.(typ).struct; }
479

480
// Returns the canonical name of the given type.
481
fn cname(&ctxt cx, &t typ) -> Option.t[str] { ret cx.ts.others.(typ).cname; }
482

483

484 485
// Stringification

486
fn path_to_str(&ast.path pth) -> str {
487 488
    auto result = Str.connect(pth.node.idents,  ".");
    if (Vec.len[@ast.ty](pth.node.types) > 0u) {
489
        auto f = pretty.pprust.ty_to_str;
490
        result += "[";
491
        result += Str.connect(Vec.map[@ast.ty,str](f, pth.node.types), ",");
492 493 494 495 496
        result += "]";
    }
    ret result;
}

497
fn ty_to_str(ctxt cx, &t typ) -> str {
498

499
    fn fn_input_to_str(ctxt cx, &rec(mode mode, t ty) input) -> str {
500
        auto s;
501 502 503 504
        alt (input.mode) {
            case (mo_val) { s = ""; }
            case (mo_alias) { s = "&"; }
            case (mo_either) { s = "?"; }
505 506
        }

507
        ret s + ty_to_str(cx, input.ty);
508 509
    }

510
    fn fn_to_str(ctxt cx,
511
                 ast.proto proto,
512
                 Option.t[ast.ident] ident,
513
                 vec[arg] inputs, t output) -> str {
514
            auto f = bind fn_input_to_str(cx, _);
515 516 517 518 519 520 521 522 523

            auto s;
            alt (proto) {
                case (ast.proto_iter) {
                    s = "iter";
                }
                case (ast.proto_fn) {
                    s = "fn";
                }
524
            }
525

526 527 528 529 530 531 532 533 534
            alt (ident) {
                case (some[ast.ident](?i)) {
                    s += " ";
                    s += i;
                }
                case (_) { }
            }

            s += "(";
535
            s += Str.connect(Vec.map[arg,str](f, inputs), ", ");
536 537
            s += ")";

538 539
            if (struct(cx, output) != ty_nil) {
                s += " -> " + ty_to_str(cx, output);
540 541 542 543
            }
            ret s;
    }

544 545
    fn method_to_str(ctxt cx, &method m) -> str {
        ret fn_to_str(cx, m.proto, some[ast.ident](m.ident),
546
                      m.inputs, m.output) + ";";
547 548
    }

549 550
    fn field_to_str(ctxt cx, &field f) -> str {
        ret mt_to_str(cx, f.mt) + " " + f.ident;
551 552
    }

553
    fn mt_to_str(ctxt cx, &mt m) -> str {
554 555
        auto mstr;
        alt (m.mut) {
556 557 558
            case (ast.mut)       { mstr = "mutable "; }
            case (ast.imm)       { mstr = "";         }
            case (ast.maybe_mut) { mstr = "mutable? "; }
559 560
        }

561
        ret mstr + ty_to_str(cx, m.ty);
562 563
    }

564 565 566 567 568 569 570
    alt (cname(cx, typ)) {
        case (some[str](?cs)) {
            ret cs;
        }
        case (_) { }
    }

571
    auto s = "";
572

573
    alt (struct(cx, typ)) {
574 575 576 577 578 579 580 581 582
        case (ty_native)       { s += "native";                         }
        case (ty_nil)          { s += "()";                             }
        case (ty_bool)         { s += "bool";                           }
        case (ty_int)          { s += "int";                            }
        case (ty_float)        { s += "float";                          }
        case (ty_uint)         { s += "uint";                           }
        case (ty_machine(?tm)) { s += common.ty_mach_to_str(tm);        }
        case (ty_char)         { s += "char";                           }
        case (ty_str)          { s += "str";                            }
583 584 585 586
        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) + "]"; }
587
        case (ty_type)         { s += "type";                           }
588 589

        case (ty_tup(?elems)) {
590
            auto f = bind mt_to_str(cx, _);
591 592
            auto strs = Vec.map[mt,str](f, elems);
            s += "tup(" + Str.connect(strs, ",") + ")";
593 594 595
        }

        case (ty_rec(?elems)) {
596
            auto f = bind field_to_str(cx, _);
597 598
            auto strs = Vec.map[field,str](f, elems);
            s += "rec(" + Str.connect(strs, ",") + ")";
599 600
        }

601
        case (ty_tag(?id, ?tps)) {
602
            // The user should never see this if the cname is set properly!
603
            s += "<tag#" + util.common.istr(id._0) + ":" +
604
                util.common.istr(id._1) + ">";
605
            if (Vec.len[t](tps) > 0u) {
606
                auto f = bind ty_to_str(cx, _);
607 608
                auto strs = Vec.map[t,str](f, tps);
                s += "[" + Str.connect(strs, ",") + "]";
609
            }
610 611
        }

612
        case (ty_fn(?proto, ?inputs, ?output)) {
613
            s += fn_to_str(cx, proto, none[ast.ident], inputs, output);
614 615
        }

616
        case (ty_native_fn(_, ?inputs, ?output)) {
617
            s += fn_to_str(cx, ast.proto_fn, none[ast.ident], inputs, output);
618 619
        }

620
        case (ty_obj(?meths)) {
621
            auto f = bind method_to_str(cx, _);
622 623
            auto m = Vec.map[method,str](f, meths);
            s += "obj {\n\t" + Str.connect(m, "\n\t") + "\n}";
624 625 626
        }

        case (ty_var(?v)) {
627
            s += "<T" + util.common.istr(v) + ">";
628 629
        }

G
Graydon Hoare 已提交
630
        case (ty_local(?id)) {
631 632
            s += "<L" + util.common.istr(id._0) + ":" +
                util.common.istr(id._1) + ">";
G
Graydon Hoare 已提交
633 634
        }

635
        case (ty_param(?id)) {
636
            s += "'" + Str.unsafe_from_bytes(vec(('a' as u8) + (id as u8)));
637
        }
638 639

        case (ty_bound_param(?id)) {
640
            s += "''" + Str.unsafe_from_bytes(vec(('a' as u8) + (id as u8)));
641
        }
642 643 644 645 646
    }

    ret s;
}

647
fn ty_to_short_str(ctxt cx, t typ) -> str {
648
    auto f = def_to_str;
649
    auto ecx = @rec(ds=f, tcx=cx, abbrevs=metadata.ac_no_abbrevs);
650
    auto s = metadata.Encode.ty_str(ecx, typ);
651
    if (Str.byte_len(s) >= 32u) { s = Str.substr(s, 0u, 32u); }
652
    ret s;
653 654
}

655 656
// Type folds

657
type ty_walk = fn(t);
658

659 660
fn walk_ty(ctxt cx, ty_walk walker, t ty) {
    alt (struct(cx, ty)) {
661 662 663 664 665 666 667 668 669 670
        case (ty_nil)           { /* no-op */ }
        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 */ }
671 672 673 674
        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); }
675
        case (ty_tag(?tid, ?subtys)) {
676
            for (t subty in subtys) {
677
                walk_ty(cx, walker, subty);
678 679 680 681
            }
        }
        case (ty_tup(?mts)) {
            for (mt tm in mts) {
682
                walk_ty(cx, walker, tm.ty);
683 684 685 686
            }
        }
        case (ty_rec(?fields)) {
            for (field fl in fields) {
687
                walk_ty(cx, walker, fl.mt.ty);
688 689 690 691
            }
        }
        case (ty_fn(?proto, ?args, ?ret_ty)) {
            for (arg a in args) {
692
                walk_ty(cx, walker, a.ty);
693
            }
694
            walk_ty(cx, walker, ret_ty);
695 696 697
        }
        case (ty_native_fn(?abi, ?args, ?ret_ty)) {
            for (arg a in args) {
698
                walk_ty(cx, walker, a.ty);
699
            }
700
            walk_ty(cx, walker, ret_ty);
701 702 703 704 705
        }
        case (ty_obj(?methods)) {
            let vec[method] new_methods = vec();
            for (method m in methods) {
                for (arg a in m.inputs) {
706
                    walk_ty(cx, walker, a.ty);
707
                }
708
                walk_ty(cx, walker, m.output);
709 710 711 712 713 714 715
            }
        }
        case (ty_var(_))         { /* no-op */ }
        case (ty_local(_))       { /* no-op */ }
        case (ty_param(_))       { /* no-op */ }
        case (ty_bound_param(_)) { /* no-op */ }
    }
716

717 718 719
    walker(ty);
}

720
type ty_fold = fn(t) -> t;
721

722
fn fold_ty(ctxt cx, ty_fold fld, t ty_0) -> t {
723
    auto ty = ty_0;
724
    alt (struct(cx, ty)) {
725 726 727 728 729 730 731 732 733 734
        case (ty_nil)           { /* no-op */ }
        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 */ }
735
        case (ty_box(?tm)) {
736 737
            ty = copy_cname(cx, mk_box(cx, rec(ty=fold_ty(cx, fld, tm.ty),
                                               mut=tm.mut)), ty);
738
        }
739
        case (ty_vec(?tm)) {
740 741
            ty = copy_cname(cx, mk_vec(cx, rec(ty=fold_ty(cx, fld, tm.ty),
                                                          mut=tm.mut)), ty);
742
        }
743
        case (ty_port(?subty)) {
744
            ty = copy_cname(cx, mk_port(cx, fold_ty(cx, fld, subty)), ty);
745 746
        }
        case (ty_chan(?subty)) {
747
            ty = copy_cname(cx, mk_chan(cx, fold_ty(cx, fld, subty)), ty);
748
        }
749
        case (ty_tag(?tid, ?subtys)) {
750 751
            let vec[t] new_subtys = vec();
            for (t subty in subtys) {
752
                new_subtys += vec(fold_ty(cx, fld, subty));
753
            }
754
            ty = copy_cname(cx, mk_tag(cx, tid, new_subtys), ty);
755
        }
756 757 758
        case (ty_tup(?mts)) {
            let vec[mt] new_mts = vec();
            for (mt tm in mts) {
759
                auto new_subty = fold_ty(cx, fld, tm.ty);
760
                new_mts += vec(rec(ty=new_subty, mut=tm.mut));
761
            }
762
            ty = copy_cname(cx, mk_tup(cx, new_mts), ty);
763 764 765 766
        }
        case (ty_rec(?fields)) {
            let vec[field] new_fields = vec();
            for (field fl in fields) {
767
                auto new_ty = fold_ty(cx, fld, fl.mt.ty);
768 769
                auto new_mt = rec(ty=new_ty, mut=fl.mt.mut);
                new_fields += vec(rec(ident=fl.ident, mt=new_mt));
770
            }
771
            ty = copy_cname(cx, mk_rec(cx, new_fields), ty);
772
        }
773
        case (ty_fn(?proto, ?args, ?ret_ty)) {
774 775
            let vec[arg] new_args = vec();
            for (arg a in args) {
776
                auto new_ty = fold_ty(cx, fld, a.ty);
777 778
                new_args += vec(rec(mode=a.mode, ty=new_ty));
            }
779 780
            ty = copy_cname(cx, mk_fn(cx, proto, new_args,
                                      fold_ty(cx, fld, ret_ty)), ty);
781
        }
782
        case (ty_native_fn(?abi, ?args, ?ret_ty)) {
783 784
            let vec[arg] new_args = vec();
            for (arg a in args) {
785
                auto new_ty = fold_ty(cx, fld, a.ty);
786 787
                new_args += vec(rec(mode=a.mode, ty=new_ty));
            }
788 789
            ty = copy_cname(cx, mk_native_fn(cx, abi, new_args,
                                             fold_ty(cx, fld, ret_ty)), ty);
790
        }
791 792 793 794 795
        case (ty_obj(?methods)) {
            let vec[method] new_methods = vec();
            for (method m in methods) {
                let vec[arg] new_args = vec();
                for (arg a in m.inputs) {
796
                    new_args += vec(rec(mode=a.mode,
797
                                        ty=fold_ty(cx, fld, a.ty)));
798
                }
799 800
                new_methods += vec(rec(proto=m.proto, ident=m.ident,
                                       inputs=new_args,
801
                                       output=fold_ty(cx, fld, m.output)));
802
            }
803
            ty = copy_cname(cx, mk_obj(cx, new_methods), ty);
804
        }
805 806 807 808
        case (ty_var(_))         { /* no-op */ }
        case (ty_local(_))       { /* no-op */ }
        case (ty_param(_))       { /* no-op */ }
        case (ty_bound_param(_)) { /* no-op */ }
809 810
    }

811
    ret fld(ty);
812 813 814 815
}

// Type utilities

816 817
fn rename(ctxt cx, t typ, str new_cname) -> t {
    ret gen_ty_full(cx, struct(cx, typ), some[str](new_cname));
818 819 820 821
}

// Returns a type with the structural part taken from `struct_ty` and the
// canonical name from `cname_ty`.
822
fn copy_cname(ctxt cx, t struct_ty, t cname_ty) -> t {
823
    ret gen_ty_full(cx, struct(cx, struct_ty), cname(cx, cname_ty));
824 825
}

826
fn type_is_nil(&ctxt cx, &t ty) -> bool {
827
    alt (struct(cx, ty)) {
828 829 830 831 832 833
        case (ty_nil) { ret true; }
        case (_) { ret false; }
    }
    fail;
}

834
fn type_is_bool(&ctxt cx, &t ty) -> bool {
835
    alt (struct(cx, ty)) {
836 837 838 839 840
        case (ty_bool) { ret true; }
        case (_) { ret false; }
    }
}

841

842
fn type_is_structural(&ctxt cx, &t ty) -> bool {
843
    alt (struct(cx, ty)) {
844 845 846
        case (ty_tup(_))    { ret true; }
        case (ty_rec(_))    { ret true; }
        case (ty_tag(_,_))  { ret true; }
847
        case (ty_fn(_,_,_)) { ret true; }
848 849
        case (ty_obj(_))    { ret true; }
        case (_)            { ret false; }
850 851 852 853
    }
    fail;
}

854
fn type_is_sequence(&ctxt cx, &t ty) -> bool {
855
    alt (struct(cx, ty)) {
856 857 858 859 860 861 862
        case (ty_str)    { ret true; }
        case (ty_vec(_))    { ret true; }
        case (_)            { ret false; }
    }
    fail;
}

863
fn sequence_element_type(&ctxt cx, &t ty) -> t {
864 865
    alt (struct(cx, ty)) {
        case (ty_str)      { ret mk_mach(cx, common.ty_u8); }
866
        case (ty_vec(?mt)) { ret mt.ty; }
867 868 869 870 871
    }
    fail;
}


872
fn type_is_tup_like(&ctxt cx, &t ty) -> bool {
873
    alt (struct(cx, ty)) {
874 875 876 877 878
        case (ty_box(_))    { ret true; }
        case (ty_tup(_))    { ret true; }
        case (ty_rec(_))    { ret true; }
        case (ty_tag(_,_))  { ret true; }
        case (_)            { ret false; }
879 880 881 882
    }
    fail;
}

883
fn get_element_type(&ctxt cx, &t ty, uint i) -> t {
884
    assert (type_is_tup_like(cx, ty));
885
    alt (struct(cx, ty)) {
886 887
        case (ty_tup(?mts)) {
            ret mts.(i).ty;
888 889
        }
        case (ty_rec(?flds)) {
890
            ret flds.(i).mt.ty;
891 892 893 894 895
        }
    }
    fail;
}

896
fn type_is_box(&ctxt cx, &t ty) -> bool {
897
    alt (struct(cx, ty)) {
898 899 900 901 902 903
        case (ty_box(_)) { ret true; }
        case (_) { ret false; }
    }
    fail;
}

904
fn type_is_boxed(&ctxt cx, &t ty) -> bool {
905
    alt (struct(cx, ty)) {
906 907 908
        case (ty_str) { ret true; }
        case (ty_vec(_)) { ret true; }
        case (ty_box(_)) { ret true; }
B
Brian Anderson 已提交
909 910
        case (ty_port(_)) { ret true; }
        case (ty_chan(_)) { ret true; }
911 912 913 914 915
        case (_) { ret false; }
    }
    fail;
}

916
fn type_is_scalar(&ctxt cx, &t ty) -> bool {
917
    alt (struct(cx, ty)) {
918 919 920
        case (ty_nil) { ret true; }
        case (ty_bool) { ret true; }
        case (ty_int) { ret true; }
921
        case (ty_float) { ret true; }
922 923 924
        case (ty_uint) { ret true; }
        case (ty_machine(_)) { ret true; }
        case (ty_char) { ret true; }
G
Graydon Hoare 已提交
925
        case (ty_type) { ret true; }
926
        case (ty_native) { ret true; }
927 928 929 930 931
        case (_) { ret false; }
    }
    fail;
}

932 933
// FIXME: should we just return true for native types in
// type_is_scalar?
934
fn type_is_native(&ctxt cx, &t ty) -> bool {
935
    alt (struct(cx, ty)) {
936 937 938 939 940 941
        case (ty_native) { ret true; }
        case (_) { ret false; }
    }
    fail;
}

942
fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
943
    alt (struct(cx, ty)) {
944
        case (ty_tup(?mts)) {
945
            auto i = 0u;
946
            while (i < Vec.len[mt](mts)) {
947
                if (type_has_dynamic_size(cx, mts.(i).ty)) { ret true; }
948 949 950 951 952
                i += 1u;
            }
        }
        case (ty_rec(?fields)) {
            auto i = 0u;
953
            while (i < Vec.len[field](fields)) {
954
                if (type_has_dynamic_size(cx, fields.(i).mt.ty)) {
955 956
                    ret true;
                }
957 958 959
                i += 1u;
            }
        }
960 961
        case (ty_tag(_, ?subtys)) {
            auto i = 0u;
962
            while (i < Vec.len[t](subtys)) {
963
                if (type_has_dynamic_size(cx, subtys.(i))) { ret true; }
964 965 966
                i += 1u;
            }
        }
967 968 969 970 971
        case (ty_param(_)) { ret true; }
        case (_) { /* fall through */ }
    }
    ret false;
}
972

973
fn type_is_integral(&ctxt cx, &t ty) -> bool {
974
    alt (struct(cx, ty)) {
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996
        case (ty_int) { ret true; }
        case (ty_uint) { ret true; }
        case (ty_machine(?m)) {
            alt (m) {
                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; }
                case (_) { ret false; }
            }
        }
        case (ty_char) { ret true; }
        case (_) { ret false; }
    }
    fail;
}

997
fn type_is_fp(&ctxt cx, &t ty) -> bool {
998
    alt (struct(cx, ty)) {
999 1000 1001 1002 1003 1004 1005
        case (ty_machine(?tm)) {
            alt (tm) {
                case (common.ty_f32) { ret true; }
                case (common.ty_f64) { ret true; }
                case (_) { ret false; }
            }
        }
1006 1007 1008
        case (ty_float) {
            ret true;
        }
1009 1010 1011 1012 1013
        case (_) { ret false; }
    }
    fail;
}

1014
fn type_is_signed(&ctxt cx, &t ty) -> bool {
1015
    alt (struct(cx, ty)) {
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
        case (ty_int) { ret true; }
        case (ty_machine(?tm)) {
            alt (tm) {
                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 (_) { ret false; }
            }
        }
        case (_) { ret false; }
    }
    fail;
}

1031
fn type_param(&ctxt cx, &t ty) -> Option.t[uint] {
1032
    alt (struct(cx, ty)) {
1033 1034
        case (ty_param(?id)) { ret some[uint](id); }
        case (_)             { /* fall through */  }
1035
    }
1036
    ret none[uint];
1037 1038
}

1039
fn def_to_str(&ast.def_id did) -> str {
1040 1041 1042
    ret #fmt("%d:%d", did._0, did._1);
}

1043

P
Patrick Walton 已提交
1044 1045 1046
// 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 {
1047 1048 1049 1050 1051
    fn hash_uint(uint id, uint n) -> uint {
        auto h = id;
        h += h << 5u + n;
        ret h;
    }
P
Patrick Walton 已提交
1052

1053 1054 1055 1056 1057
    fn hash_def(uint id, ast.def_id did) -> uint {
        auto h = id;
        h += h << 5u + (did._0 as uint);
        h += h << 5u + (did._1 as uint);
        ret h;
1058
    }
P
Patrick Walton 已提交
1059

1060
    fn hash_subty(uint id, &t subty) -> uint {
1061 1062 1063 1064 1065
        auto h = id;
        h += h << 5u + hash_ty(subty);
        ret h;
    }

1066
    fn hash_fn(uint id, &vec[arg] args, &t rty) -> uint {
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
        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) {
                case (common.ty_i8) { ret 5u; }
                case (common.ty_i16) { ret 6u; }
                case (common.ty_i32) { ret 7u; }
                case (common.ty_i64) { ret 8u; }

                case (common.ty_u8) { ret 9u; }
                case (common.ty_u16) { ret 10u; }
                case (common.ty_u32) { ret 11u; }
                case (common.ty_u64) { ret 12u; }

                case (common.ty_f32) { ret 13u; }
                case (common.ty_f64) { ret 14u; }
            }
        }
        case (ty_char) { ret 15u; }
        case (ty_str) { ret 16u; }
        case (ty_tag(?did, ?tys)) {
            auto h = hash_def(17u, did);
1101
            for (t typ in tys) {
1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129
                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) {
1130
                h += h << 5u + Str.hash(m.ident);
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
            }
            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; }
    }
1141 1142
}

1143
fn hash_type_info(&sty st, &Option.t[str] cname_opt) -> uint {
1144 1145 1146
    auto h = hash_type_structure(st);
    alt (cname_opt) {
        case (none[str]) { /* no-op */ }
1147
        case (some[str](?s)) { h += h << 5u + Str.hash(s); }
1148 1149 1150 1151
    }
    ret h;
}

1152 1153 1154
fn hash_raw_ty(&raw_t rt) -> uint { ret rt.hash; }

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

1156

1157 1158 1159 1160
// 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 {
1161
        ret a.mut == b.mut && eq_ty(a.ty, b.ty);
1162 1163
    }

1164 1165
    fn equal_fn(&vec[arg] args_a, &t rty_a,
                &vec[arg] args_b, &t rty_b) -> bool {
1166
        if (!eq_ty(rty_a, rty_b)) { ret false; }
1167

1168 1169
        auto len = Vec.len[arg](args_a);
        if (len != Vec.len[arg](args_b)) { ret false; }
1170

1171 1172 1173
        auto i = 0u;
        while (i < len) {
            auto arg_a = args_a.(i); auto arg_b = args_b.(i);
1174
            if (arg_a.mode != arg_b.mode) { ret false; }
1175
            if (!eq_ty(arg_a.ty, arg_b.ty)) { ret false; }
1176 1177 1178 1179 1180
            i += 1u;
        }
        ret true;
    }

1181
    fn equal_def(&ast.def_id did_a, &ast.def_id did_b) -> bool {
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
        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; }
            }
        }
        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 已提交
1239
                    if (!equal_def(id_a, id_b)) { ret false; }
1240

1241 1242
                    auto len = Vec.len[t](tys_a);
                    if (len != Vec.len[t](tys_b)) { ret false; }
1243 1244
                    auto i = 0u;
                    while (i < len) {
1245
                        if (!eq_ty(tys_a.(i), tys_b.(i))) { ret false; }
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
                        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) {
1267
                case (ty_port(?t_b)) { ret eq_ty(t_a, t_b); }
1268 1269 1270 1271 1272
                case (_) { ret false; }
            }
        }
        case (ty_chan(?t_a)) {
            alt (b) {
1273
                case (ty_chan(?t_b)) { ret eq_ty(t_a, t_b); }
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
                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)) {
1286 1287
                    auto len = Vec.len[mt](mts_a);
                    if (len != Vec.len[mt](mts_b)) { ret false; }
1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
                    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)) {
1301 1302
                    auto len = Vec.len[field](flds_a);
                    if (len != Vec.len[field](flds_b)) { ret false; }
1303 1304 1305
                    auto i = 0u;
                    while (i < len) {
                        auto fld_a = flds_a.(i); auto fld_b = flds_b.(i);
1306
                        if (!Str.eq(fld_a.ident, fld_b.ident) ||
1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319
                                !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)) {
1320
                    ret p_a == p_b &&
1321 1322 1323 1324 1325 1326 1327 1328
                        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)) {
1329
                    ret abi_a == abi_b &&
1330 1331 1332 1333 1334 1335 1336 1337
                        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)) {
1338 1339
                    auto len = Vec.len[method](methods_a);
                    if (len != Vec.len[method](methods_b)) { ret false; }
1340 1341 1342
                    auto i = 0u;
                    while (i < len) {
                        auto m_a = methods_a.(i); auto m_b = methods_b.(i);
1343
                        if (m_a.proto != m_b.proto ||
1344
                                !Str.eq(m_a.ident, m_b.ident) ||
P
Patrick Walton 已提交
1345 1346
                                !equal_fn(m_a.inputs, m_a.output,
                                          m_b.inputs, m_b.output)) {
1347 1348
                            ret false;
                        }
P
Patrick Walton 已提交
1349
                        i += 1u;
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
                    }
                    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 已提交
1395 1396
// An expensive type equality function. This function is private to this
// module.
1397 1398
//
// FIXME: Use structural comparison, but this loops forever and segfaults.
1399
fn eq_raw_ty(&raw_t a, &raw_t b) -> bool {
P
Patrick Walton 已提交
1400
    // Check hashes (fast path).
1401 1402 1403 1404
    if (a.hash != b.hash) {
        ret false;
    }

P
Patrick Walton 已提交
1405
    // Check canonical names.
1406
    alt (a.cname) {
P
Patrick Walton 已提交
1407
        case (none[str]) {
1408
            alt (b.cname) {
P
Patrick Walton 已提交
1409
                case (none[str]) { /* ok */ }
1410 1411 1412
                case (_) { ret false; }
            }
        }
P
Patrick Walton 已提交
1413
        case (some[str](?s_a)) {
1414
            alt (b.cname) {
P
Patrick Walton 已提交
1415
                case (some[str](?s_b)) {
1416
                    if (!Str.eq(s_a, s_b)) { ret false; }
1417 1418 1419 1420
                }
                case (_) { ret false; }
            }
        }
P
Patrick Walton 已提交
1421
    }
1422

P
Patrick Walton 已提交
1423
    // Check structures.
1424
    ret equal_type_structures(a.struct, b.struct);
P
Patrick Walton 已提交
1425
}
1426

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

1431

1432
fn ann_to_type(&ast.ann ann) -> t {
1433
    alt (ann) {
1434
        case (ast.ann_none(_)) {
1435
            log_err "ann_to_type() called on node with no type";
1436
            fail;
1437
        }
1438
        case (ast.ann_type(_, ?ty, _, _)) {
1439 1440 1441 1442 1443
            ret ty;
        }
    }
}

1444
fn ann_to_type_params(&ast.ann ann) -> vec[t] {
1445
    alt (ann) {
1446
        case (ast.ann_none(_)) {
1447
            log_err "ann_to_type_params() called on node with no type params";
1448 1449
            fail;
        }
1450
        case (ast.ann_type(_, _, ?tps, _)) {
1451
            alt (tps) {
1452 1453
                case (none[vec[t]]) {
                    let vec[t] result = vec();
1454 1455
                    ret result;
                }
1456
                case (some[vec[t]](?tps)) { ret tps; }
1457 1458 1459 1460 1461 1462 1463
            }
        }
    }
}

// Returns the type of an annotation, with type parameter substitutions
// performed if applicable.
1464
fn ann_to_monotype(ctxt cx, ast.ann a) -> t {
1465 1466 1467
    // TODO: Refactor to use recursive pattern matching when we're more
    // confident that it works.
    alt (a) {
1468
        case (ast.ann_none(_)) {
1469
            log_err "ann_to_monotype() called on expression with no type!";
1470 1471
            fail;
        }
1472
        case (ast.ann_type(_, ?typ, ?tps_opt, _)) {
1473
            alt (tps_opt) {
1474 1475
                case (none[vec[t]]) { ret typ; }
                case (some[vec[t]](?tps)) {
1476
                    ret substitute_type_params(cx, tps, typ);
1477 1478 1479 1480 1481 1482 1483
                }
            }
        }
    }
}

// Turns a type into an ann_type, using defaults for other fields.
1484 1485
fn triv_ann(&ast.ann old, t typ) -> ast.ann {
    ret ast.ann_type(ast.ann_tag(old), typ, none[vec[t]], none[@ts_ann]);
1486 1487
}

1488
// Returns the number of distinct type parameters in the given type.
1489 1490 1491
fn count_ty_params(ctxt cx, t ty) -> uint {
    fn counter(ctxt cx, @mutable vec[uint] param_indices, t ty) {
        alt (struct(cx, ty)) {
1492 1493 1494 1495 1496
            case (ty_param(?param_idx)) {
                auto seen = false;
                for (uint other_param_idx in *param_indices) {
                    if (param_idx == other_param_idx) {
                        seen = true;
1497
                    }
1498
                }
1499 1500 1501
                if (!seen) {
                    *param_indices += vec(param_idx);
                }
1502
            }
1503
            case (_) { /* fall through */ }
1504 1505 1506
        }
    }

1507 1508
    let vec[uint] v = vec();    // FIXME: typechecker botch
    let @mutable vec[uint] param_indices = @mutable v;
1509 1510
    auto f = bind counter(cx, param_indices, _);
    walk_ty(cx, f, ty);
1511
    ret Vec.len[uint](*param_indices);
1512 1513
}

1514
fn type_contains_vars(&ctxt cx, &t typ) -> bool {
1515
    ret cx.ts.others.(typ).has_vars;
1516 1517
}

1518
fn type_contains_locals(&ctxt cx, &t typ) -> bool {
1519
    ret cx.ts.others.(typ).has_locals;
1520 1521
}

1522
fn type_contains_params(&ctxt cx, &t typ) -> bool {
1523
    ret cx.ts.others.(typ).has_params;
1524 1525
}

1526
fn type_contains_bound_params(&ctxt cx, &t typ) -> bool {
1527
    ret cx.ts.others.(typ).has_bound_params;
1528 1529
}

G
Graydon Hoare 已提交
1530 1531
// Type accessors for substructures of types

1532
fn ty_fn_args(&ctxt cx, &t fty) -> vec[arg] {
1533
    alt (struct(cx, fty)) {
1534
        case (ty.ty_fn(_, ?a, _)) { ret a; }
1535
        case (ty.ty_native_fn(_, ?a, _)) { ret a; }
1536
    }
1537
    fail;
1538 1539
}

1540
fn ty_fn_proto(&ctxt cx, &t fty) -> ast.proto {
1541
    alt (struct(cx, fty)) {
1542 1543
        case (ty.ty_fn(?p, _, _)) { ret p; }
    }
1544
    fail;
G
Graydon Hoare 已提交
1545 1546
}

1547
fn ty_fn_abi(&ctxt cx, &t fty) -> ast.native_abi {
1548
    alt (struct(cx, fty)) {
1549 1550 1551 1552 1553
        case (ty.ty_native_fn(?a, _, _)) { ret a; }
    }
    fail;
}

1554
fn ty_fn_ret(&ctxt cx, &t fty) -> t {
1555
    alt (struct(cx, fty)) {
1556
        case (ty.ty_fn(_, _, ?r)) { ret r; }
1557
        case (ty.ty_native_fn(_, _, ?r)) { ret r; }
1558
    }
1559
    fail;
G
Graydon Hoare 已提交
1560 1561
}

1562
fn is_fn_ty(&ctxt cx, &t fty) -> bool {
1563
    alt (struct(cx, fty)) {
1564
        case (ty.ty_fn(_, _, _)) { ret true; }
1565
        case (ty.ty_native_fn(_, _, _)) { ret true; }
1566 1567 1568
        case (_) { ret false; }
    }
    ret false;
G
Graydon Hoare 已提交
1569 1570 1571
}


1572 1573
// Type accessors for AST nodes

1574 1575
// Given an item, returns the associated type as well as the number of type
// parameters it has.
1576
fn native_item_ty(&@ast.native_item it) -> ty_param_count_and_ty {
1577
    auto ty_param_count;
1578 1579
    auto result_ty;
    alt (it.node) {
1580
        case (ast.native_item_fn(_, _, _, ?tps, _, ?ann)) {
1581
            ty_param_count = Vec.len[ast.ty_param](tps);
1582 1583 1584
            result_ty = ann_to_type(ann);
        }
    }
1585
    ret tup(ty_param_count, result_ty);
1586 1587
}

1588
fn item_ty(&@ast.item it) -> ty_param_count_and_ty {
1589
    auto ty_param_count;
1590 1591 1592
    auto result_ty;
    alt (it.node) {
        case (ast.item_const(_, _, _, _, ?ann)) {
1593
            ty_param_count = 0u;
1594 1595 1596
            result_ty = ann_to_type(ann);
        }
        case (ast.item_fn(_, _, ?tps, _, ?ann)) {
1597
            ty_param_count = Vec.len[ast.ty_param](tps);
1598 1599 1600 1601 1602 1603
            result_ty = ann_to_type(ann);
        }
        case (ast.item_mod(_, _, _)) {
            fail;   // modules are typeless
        }
        case (ast.item_ty(_, _, ?tps, _, ?ann)) {
1604
            ty_param_count = Vec.len[ast.ty_param](tps);
1605 1606
            result_ty = ann_to_type(ann);
        }
1607
        case (ast.item_tag(_, _, ?tps, ?did, ?ann)) {
1608
            ty_param_count = Vec.len[ast.ty_param](tps);
1609
            result_ty = ann_to_type(ann);
1610 1611
        }
        case (ast.item_obj(_, _, ?tps, _, ?ann)) {
1612
            ty_param_count = Vec.len[ast.ty_param](tps);
1613 1614 1615 1616
            result_ty = ann_to_type(ann);
        }
    }

1617
    ret tup(ty_param_count, result_ty);
1618 1619
}

1620
fn stmt_ty(&ctxt cx, &@ast.stmt s) -> t {
1621
    alt (s.node) {
1622
        case (ast.stmt_expr(?e,_)) {
1623
            ret expr_ty(cx, e);
1624 1625
        }
        case (_) {
1626
            ret mk_nil(cx);
1627 1628 1629 1630
        }
    }
}

1631
fn block_ty(&ctxt cx, &ast.block b) -> t {
1632
    alt (b.node.expr) {
1633 1634
        case (some[@ast.expr](?e)) { ret expr_ty(cx, e); }
        case (none[@ast.expr])     { ret mk_nil(cx); }
1635 1636 1637
    }
}

1638 1639
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
1640
fn pat_ty(&ctxt cx, &@ast.pat pat) -> t {
1641
    alt (pat.node) {
1642 1643 1644
        case (ast.pat_wild(?ann))           { ret ann_to_monotype(cx, ann); }
        case (ast.pat_lit(_, ?ann))         { ret ann_to_monotype(cx, ann); }
        case (ast.pat_bind(_, _, ?ann))     { ret ann_to_monotype(cx, ann); }
1645
        case (ast.pat_tag(_, _, ?ann))      { ret ann_to_monotype(cx, ann); }
1646 1647 1648 1649
    }
    fail;   // not reached
}

1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717
fn expr_ann(&@ast.expr e) -> ast.ann {
    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;
        }
1718
        case (ast.expr_path(_,?a)) {
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 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
            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;
        }
        case (ast.expr_break(?a)) {
            ret a;
        }
        case (ast.expr_cont(?a)) {
            ret a;
        }
        case (ast.expr_self_method(_, ?a)) {
            ret a;
        }
1760 1761 1762
    }
}

1763 1764 1765 1766 1767 1768
// 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.
1769
fn expr_ty(&ctxt cx, &@ast.expr expr) -> t {
1770
    ret ann_to_monotype(cx, expr_ann(expr));
1771 1772
}

1773
fn expr_ty_params_and_ty(&ctxt cx, &@ast.expr expr) -> tup(vec[t], t) {
1774 1775 1776
    auto a = expr_ann(expr);

    ret tup(ann_to_type_params(a), ann_to_type(a));
1777 1778
}

1779
fn expr_has_ty_params(&@ast.expr expr) -> bool {
1780 1781
    // FIXME: Rewrite using complex patterns when they're trustworthy.
    alt (expr_ann(expr)) {
1782
        case (ast.ann_none(_)) { fail; }
1783
        case (ast.ann_type(_, _, ?tps_opt, _)) {
1784
            ret !Option.is_none[vec[t]](tps_opt);
1785 1786 1787 1788 1789
        }
    }
}

// FIXME: At the moment this works only for call, bind, and path expressions.
1790 1791
fn replace_expr_type(&@ast.expr expr,
                     &tup(vec[t], t) new_tyt) -> @ast.expr {
1792 1793
    auto new_tps;
    if (expr_has_ty_params(expr)) {
1794
        new_tps = some[vec[t]](new_tyt._0);
1795
    } else {
1796
        new_tps = none[vec[t]];
1797 1798
    }

1799 1800 1801 1802
    fn mkann_fn(t tyt, Option.t[vec[t]] tps, &ast.ann old_ann) -> ast.ann {
        ret ast.ann_type(ast.ann_tag(old_ann), tyt, tps, none[@ts_ann]);
    }
    auto mkann = bind mkann_fn(new_tyt._1, new_tps, _);
1803 1804

    alt (expr.node) {
1805 1806 1807
        case (ast.expr_call(?callee, ?args, ?a)) {
            ret @fold.respan(expr.span,
                             ast.expr_call(callee, args, mkann(a)));
1808
        }
1809 1810 1811
        case (ast.expr_self_method(?ident, ?a)) {
            ret @fold.respan(expr.span,
                             ast.expr_self_method(ident, mkann(a)));
1812
        }
1813 1814 1815
        case (ast.expr_bind(?callee, ?args, ?a)) {
            ret @fold.respan(expr.span,
                             ast.expr_bind(callee, args, mkann(a)));
1816
        }
1817 1818 1819
        case (ast.expr_field(?e, ?i, ?a)) {
            ret @fold.respan(expr.span,
                             ast.expr_field(e, i, mkann(a)));
1820
        }
1821
        case (ast.expr_path(?p, ?a)) {
1822
            ret @fold.respan(expr.span,
1823
                             ast.expr_path(p, mkann(a)));
1824 1825
        }
        case (_) {
1826
            log_err "unhandled expr type in replace_expr_type(): " +
1827
                util.common.expr_to_str(expr);
1828 1829
            fail;
        }
1830 1831 1832
    }
}

1833 1834
// Expression utilities

1835 1836
fn field_num(&session.session sess, &span sp,
             &ast.ident id) -> uint {
1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
    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 = "";
1852
                s += Str.unsafe_from_byte(c);
1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863
                sess.span_err(sp,
                              "bad numeric field on tuple: "
                              + " non-digit character: "
                              + s);
            }
        }
        i += 1u;
    }
    ret accum;
}

1864 1865
fn field_idx(&session.session sess, &span sp,
             &ast.ident id, &vec[field] fields) -> uint {
1866 1867
    let uint i = 0u;
    for (field f in fields) {
1868
        if (Str.eq(f.ident, id)) {
1869 1870 1871 1872 1873 1874 1875 1876
            ret i;
        }
        i += 1u;
    }
    sess.span_err(sp, "unknown field '" + id + "' of record");
    fail;
}

1877 1878
fn method_idx(&session.session sess, &span sp,
              &ast.ident id, &vec[method] meths) -> uint {
1879 1880
    let uint i = 0u;
    for (method m in meths) {
1881
        if (Str.eq(m.ident, id)) {
1882 1883 1884 1885 1886 1887 1888 1889
            ret i;
        }
        i += 1u;
    }
    sess.span_err(sp, "unknown method '" + id + "' of obj");
    fail;
}

1890
fn sort_methods(&vec[method] meths) -> vec[method] {
1891
    fn method_lteq(&method a, &method b) -> bool {
1892
        ret Str.lteq(a.ident, b.ident);
1893 1894
    }

1895
    ret std.Sort.merge_sort[method](bind method_lteq(_,_), meths);
1896 1897
}

1898
fn is_lval(&@ast.expr expr) -> bool {
1899 1900 1901
    alt (expr.node) {
        case (ast.expr_field(_,_,_))    { ret true;  }
        case (ast.expr_index(_,_,_))    { ret true;  }
1902
        case (ast.expr_path(_,_))       { ret true;  }
1903
        case (ast.expr_unary(ast.deref,_,_))  { ret true; }
1904 1905 1906 1907
        case (_)                        { ret false; }
    }
}

1908 1909 1910 1911
// 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
1912

1913 1914
mod Unify {
    tag result {
1915 1916
        ures_ok(t);
        ures_err(type_err, t, t);
1917 1918
    }

1919 1920
    type ctxt = rec(UFind.ufind sets,
                    hashmap[int,uint] var_ids,
1921
                    mutable vec[mutable vec[t]] types,
1922
                    unify_handler handler,
1923
                    ty_ctxt tcx);
1924

1925 1926 1927 1928 1929 1930 1931 1932
    // 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.
1933
    fn struct_cmp(@ctxt cx, t expected, t actual) -> result {
1934
        if (struct(cx.tcx, expected) == struct(cx.tcx, actual)) {
1935 1936 1937 1938 1939 1940
            ret ures_ok(expected);
        }

        ret ures_err(terr_mismatch, expected, actual);
    }

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

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

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

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

1981
            // Unify the result modes. "mo_either" unifies with both modes.
1982
            auto result_mode;
1983 1984 1985 1986 1987 1988 1989
            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) {
                ret fn_common_res_err(ures_err(terr_arg_count,
                                               expected, actual));
1990
            } else {
1991
                result_mode = expected_input.mode;
1992
            }
G
Graydon Hoare 已提交
1993

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

1996 1997
            alt (result) {
                case (ures_ok(?rty)) {
1998
                    result_ins += vec(rec(mode=result_mode, ty=rty));
1999 2000 2001
                }

                case (_) {
2002
                    ret fn_common_res_err(result);
2003 2004
                }
            }
G
Graydon Hoare 已提交
2005

2006
            i += 1u;
G
Graydon Hoare 已提交
2007 2008
        }

2009
        // Check the output.
2010
        auto result = unify_step(cx, expected_output, actual_output);
2011 2012
        alt (result) {
            case (ures_ok(?rty)) {
2013
                ret fn_common_res_ok(result_ins, rty);
2014 2015 2016
            }

            case (_) {
2017
                ret fn_common_res_err(result);
2018
            }
G
Graydon Hoare 已提交
2019
        }
2020
    }
G
Graydon Hoare 已提交
2021

2022 2023 2024 2025 2026 2027 2028
    fn unify_fn(&@ctxt cx,
                &ast.proto e_proto,
                &ast.proto a_proto,
                &t expected,
                &t actual,
                &vec[arg] expected_inputs, &t expected_output,
                &vec[arg] actual_inputs, &t actual_output)
2029
        -> result {
G
Graydon Hoare 已提交
2030

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

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

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

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

      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);
2092
        if (! Str.eq(e_meth.ident, a_meth.ident)) {
G
Graydon Hoare 已提交
2093 2094 2095
          ret ures_err(terr_obj_meths(e_meth.ident, a_meth.ident),
                       expected, actual);
        }
2096
        auto r = unify_fn(cx,
2097
                          e_meth.proto, a_meth.proto,
2098
                          expected, actual,
G
Graydon Hoare 已提交
2099 2100
                          e_meth.inputs, e_meth.output,
                          a_meth.inputs, a_meth.output);
B
Brian Anderson 已提交
2101 2102
        alt (r) {
            case (ures_ok(?tfn)) {
2103
                alt (struct(cx.tcx, tfn)) {
B
Brian Anderson 已提交
2104 2105 2106 2107 2108 2109 2110 2111 2112 2113
                    case (ty_fn(?proto, ?ins, ?out)) {
                        result_meths += vec(rec(inputs = ins,
                                                output = out
                                                with e_meth));
                    }
                }
            }
            case (_) {
                ret r;
            }
G
Graydon Hoare 已提交
2114 2115 2116
        }
        i += 1u;
      }
2117
      auto t = mk_obj(cx.tcx, result_meths);
G
Graydon Hoare 已提交
2118 2119 2120
      ret ures_ok(t);
    }

2121
    fn get_or_create_set(&@ctxt cx, int id) -> uint {
2122
        auto set_num;
2123
        alt (cx.var_ids.find(id)) {
2124
        case (none[uint]) {
2125 2126
            set_num = UFind.make_set(cx.sets);
            cx.var_ids.insert(id, set_num);
2127 2128
        }
        case (some[uint](?n)) { set_num = n; }
2129
        }
2130
        ret set_num;
2131 2132
    }

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

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

2140 2141 2142
        // Fast path.
        if (eq_ty(expected, actual)) { ret ures_ok(expected); }

2143
        alt (struct(cx.tcx, actual)) {
2144 2145
            // If the RHS is a variable type, then just do the appropriate
            // binding.
2146
            case (ty.ty_var(?actual_id)) {
2147
                auto actual_n = get_or_create_set(cx, actual_id);
2148
                alt (struct(cx.tcx, expected)) {
2149
                    case (ty.ty_var(?expected_id)) {
2150 2151
                        auto expected_n = get_or_create_set(cx, expected_id);
                        UFind.union(cx.sets, expected_n, actual_n);
2152 2153 2154 2155
                    }

                    case (_) {
                        // Just bind the type variable to the expected type.
2156
                        auto vlen = Vec.len[vec[t]](cx.types);
2157
                        if (actual_n < vlen) {
2158
                            cx.types.(actual_n) += vec(expected);
2159
                        } else {
2160
                            assert (actual_n == vlen);
2161
                            cx.types += vec(mutable vec(expected));
2162 2163 2164 2165
                        }
                    }
                }
                ret ures_ok(actual);
2166 2167
            }
            case (ty.ty_local(?actual_id)) {
2168
                auto result_ty;
2169
                alt (cx.handler.resolve_local(actual_id)) {
2170 2171
                    case (none[t]) { result_ty = expected; }
                    case (some[t](?actual_ty)) {
2172
                        auto result = unify_step(cx, expected, actual_ty);
2173 2174 2175 2176
                        alt (result) {
                            case (ures_ok(?rty)) { result_ty = rty; }
                            case (_) { ret result; }
                        }
2177 2178
                    }
                }
2179

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

                    case (_) {
2191
                        ret cx.handler.record_param(actual_id, expected);
2192 2193
                    }
                }
2194
            }
2195 2196 2197
            case (_) { /* empty */ }
        }

2198
        alt (struct(cx.tcx, expected)) {
2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209
            case (ty.ty_nil)        { ret struct_cmp(cx, expected, actual); }
            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); }
2210

2211
            case (ty.ty_tag(?expected_id, ?expected_tps)) {
2212
                alt (struct(cx.tcx, actual)) {
2213 2214 2215 2216
                    case (ty.ty_tag(?actual_id, ?actual_tps)) {
                        if (expected_id._0 != actual_id._0 ||
                                expected_id._1 != actual_id._1) {
                            ret ures_err(terr_mismatch, expected, actual);
2217
                        }
2218 2219 2220

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

2228
                            auto result = unify_step(cx,
2229
                                                     expected_tp,
2230
                                                     actual_tp);
2231 2232 2233

                            alt (result) {
                                case (ures_ok(?rty)) {
2234
                                    Vec.push[t](result_tps, rty);
2235 2236 2237 2238 2239 2240 2241 2242 2243
                                }
                                case (_) {
                                    ret result;
                                }
                            }

                            i += 1u;
                        }

2244
                        ret ures_ok(mk_tag(cx.tcx, expected_id, result_tps));
2245 2246 2247 2248 2249 2250 2251
                    }
                    case (_) { /* fall through */ }
                }

                ret ures_err(terr_mismatch, expected, actual);
            }

2252
            case (ty.ty_box(?expected_mt)) {
2253
                alt (struct(cx.tcx, actual)) {
2254
                    case (ty.ty_box(?actual_mt)) {
2255 2256 2257 2258 2259 2260 2261
                        auto mut;
                        alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
                            case (none[ast.mutability]) {
                                ret ures_err(terr_box_mutability, expected,
                                             actual);
                            }
                            case (some[ast.mutability](?m)) { mut = m; }
2262 2263
                        }

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

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

2284
            case (ty.ty_vec(?expected_mt)) {
2285
                alt (struct(cx.tcx, actual)) {
2286
                    case (ty.ty_vec(?actual_mt)) {
2287 2288 2289 2290 2291 2292 2293
                        auto mut;
                        alt (unify_mut(expected_mt.mut, actual_mt.mut)) {
                            case (none[ast.mutability]) {
                                ret ures_err(terr_vec_mutability, expected,
                                             actual);
                            }
                            case (some[ast.mutability](?m)) { mut = m; }
2294 2295
                        }

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

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

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

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

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

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

2360
            case (ty.ty_tup(?expected_elems)) {
2361
                alt (struct(cx.tcx, actual)) {
2362
                    case (ty.ty_tup(?actual_elems)) {
2363 2364
                        auto expected_len = Vec.len[ty.mt](expected_elems);
                        auto actual_len = Vec.len[ty.mt](actual_elems);
2365 2366 2367 2368 2369 2370 2371 2372
                        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.
2373
                        let vec[ty.mt] result_elems = vec();
2374 2375 2376 2377
                        auto i = 0u;
                        while (i < expected_len) {
                            auto expected_elem = expected_elems.(i);
                            auto actual_elem = actual_elems.(i);
2378 2379 2380 2381 2382 2383 2384 2385 2386

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

2389
                            auto result = unify_step(cx,
2390
                                                     expected_elem.ty,
2391
                                                     actual_elem.ty);
2392 2393
                            alt (result) {
                                case (ures_ok(?rty)) {
2394
                                    auto mt = rec(ty=rty, mut=mut);
2395
                                    result_elems += vec(mt);
2396 2397 2398 2399 2400 2401 2402 2403 2404
                                }
                                case (_) {
                                    ret result;
                                }
                            }

                            i += 1u;
                        }

2405
                        ret ures_ok(mk_tup(cx.tcx, result_elems));
2406 2407 2408 2409 2410 2411 2412 2413 2414
                    }

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

            case (ty.ty_rec(?expected_fields)) {
2415
                alt (struct(cx.tcx, actual)) {
2416
                    case (ty.ty_rec(?actual_fields)) {
2417 2418
                        auto expected_len = Vec.len[field](expected_fields);
                        auto actual_len = Vec.len[field](actual_fields);
2419 2420 2421 2422 2423 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.
                        let vec[field] result_fields = vec();
                        auto i = 0u;
                        while (i < expected_len) {
                            auto expected_field = expected_fields.(i);
                            auto actual_field = actual_fields.(i);
2432 2433 2434 2435 2436 2437 2438 2439 2440

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

2443
                            if (!Str.eq(expected_field.ident,
2444
                                         actual_field.ident)) {
2445 2446 2447 2448 2449 2450
                                auto err =
                                    terr_record_fields(expected_field.ident,
                                                       actual_field.ident);
                                ret ures_err(err, expected, actual);
                            }

2451
                            auto result = unify_step(cx,
2452
                                                     expected_field.mt.ty,
2453
                                                     actual_field.mt.ty);
2454 2455
                            alt (result) {
                                case (ures_ok(?rty)) {
2456
                                    auto mt = rec(ty=rty, mut=mut);
2457
                                    Vec.push[field]
2458
                                        (result_fields,
2459
                                         rec(mt=mt with expected_field));
2460 2461 2462 2463 2464 2465 2466 2467 2468
                                }
                                case (_) {
                                    ret result;
                                }
                            }

                            i += 1u;
                        }

2469
                        ret ures_ok(mk_rec(cx.tcx, result_fields));
2470 2471 2472 2473 2474 2475 2476 2477
                    }

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

2478
            case (ty.ty_fn(?ep, ?expected_inputs, ?expected_output)) {
2479
                alt (struct(cx.tcx, actual)) {
2480
                    case (ty.ty_fn(?ap, ?actual_inputs, ?actual_output)) {
2481 2482
                        ret unify_fn(cx, ep, ap,
                                     expected, actual,
2483 2484
                                     expected_inputs, expected_output,
                                     actual_inputs, actual_output);
2485 2486 2487 2488 2489 2490 2491 2492
                    }

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

2493 2494
            case (ty.ty_native_fn(?e_abi, ?expected_inputs,
                                  ?expected_output)) {
2495
                alt (struct(cx.tcx, actual)) {
2496 2497
                    case (ty.ty_native_fn(?a_abi, ?actual_inputs,
                                          ?actual_output)) {
2498 2499
                        ret unify_native_fn(cx, e_abi, a_abi,
                                            expected, actual,
2500 2501 2502 2503 2504 2505 2506 2507 2508
                                            expected_inputs, expected_output,
                                            actual_inputs, actual_output);
                    }
                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
                }
            }

G
Graydon Hoare 已提交
2509
            case (ty.ty_obj(?expected_meths)) {
2510
                alt (struct(cx.tcx, actual)) {
2511
                    case (ty.ty_obj(?actual_meths)) {
2512
                        ret unify_obj(cx, expected, actual,
2513 2514 2515 2516 2517
                                      expected_meths, actual_meths);
                    }
                    case (_) {
                        ret ures_err(terr_mismatch, expected, actual);
                    }
G
Graydon Hoare 已提交
2518 2519 2520
                }
            }

2521
            case (ty.ty_var(?expected_id)) {
2522
                // Add a binding.
2523
                auto expected_n = get_or_create_set(cx, expected_id);
2524
                auto vlen = Vec.len[vec[t]](cx.types);
2525
                if (expected_n < vlen) {
2526
                    cx.types.(expected_n) += vec(actual);
2527
                } else {
2528
                    assert (expected_n == vlen);
2529
                    cx.types += vec(mutable vec(actual));
2530 2531
                }
                ret ures_ok(expected);
2532 2533 2534
            }

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

2547
                cx.handler.record_local(expected_id, result_ty);
2548
                ret ures_ok(result_ty);
2549 2550
            }

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

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

2560
    // Performs type binding substitution.
2561
    fn substitute(&@ctxt cx, &vec[t] set_types, &t typ) -> t {
2562 2563 2564 2565
        if (!type_contains_vars(cx.tcx, typ)) {
            ret typ;
        }

2566
        fn substituter(@ctxt cx, vec[t] types, t typ) -> t {
2567
            alt (struct(cx.tcx, typ)) {
2568
                case (ty_var(?id)) {
2569
                    alt (cx.var_ids.find(id)) {
2570
                        case (some[uint](?n)) {
2571
                            auto root = UFind.find(cx.sets, n);
2572 2573 2574
                            ret types.(root);
                        }
                        case (none[uint]) { ret typ; }
2575 2576
                    }
                }
2577 2578 2579 2580
                case (_) { ret typ; }
            }
        }

2581
        auto f = bind substituter(cx, set_types, _);
2582
        ret fold_ty(cx.tcx, f, typ);
2583 2584
    }

2585
    fn unify_sets(&@ctxt cx) -> vec[t] {
2586 2587
        let vec[t] throwaway = vec();
        let vec[mutable vec[t]] set_types = vec(mutable throwaway);
2588
        Vec.pop[vec[t]](set_types);   // FIXME: botch
2589

2590
        for (UFind.node node in cx.sets.nodes) {
2591
            let vec[t] v = vec();
2592 2593 2594 2595
            set_types += vec(mutable v);
        }

        auto i = 0u;
2596
        while (i < Vec.len[vec[t]](set_types)) {
2597 2598
            auto root = UFind.find(cx.sets, i);
            set_types.(root) += cx.types.(i);
2599 2600 2601
            i += 1u;
        }

2602 2603
        let vec[t] result = vec();
        for (vec[t] types in set_types) {
2604
            if (Vec.len[t](types) > 1u) {
2605 2606
                log_err "unification of > 1 types in a type set is " +
                    "unimplemented";
2607
                fail;
2608
            }
2609
            result += vec(types.(0));
2610 2611
        }

2612
        ret result;
2613 2614
    }

2615 2616
    fn unify(&t expected,
             &t actual,
2617
             &unify_handler handler,
2618
             &ty_ctxt tcx) -> result {
2619 2620
        let vec[t] throwaway = vec();
        let vec[mutable vec[t]] types = vec(mutable throwaway);
2621
        Vec.pop[vec[t]](types);   // FIXME: botch
2622

2623 2624 2625
        auto cx = @rec(sets=UFind.make(),
                       var_ids=common.new_int_hash[uint](),
                       mutable types=types,
2626
                       handler=handler,
2627
                       tcx=tcx);
G
Graydon Hoare 已提交
2628

2629
        auto ures = unify_step(cx, expected, actual);
2630
        alt (ures) {
2631 2632 2633
        case (ures_ok(?typ)) {
            // Fast path: if there are no local variables, don't perform
            // substitutions.
2634
            if (Vec.len(cx.sets.nodes) == 0u) {
2635 2636 2637
                ret ures_ok(typ);
            }

2638
            auto set_types = unify_sets(cx);
2639
            auto t2 = substitute(cx, set_types, typ);
2640 2641 2642 2643 2644
            ret ures_ok(t2);
        }
        case (_) { ret ures; }
        }
        fail;   // not reached
2645
    }
2646 2647 2648 2649 2650 2651 2652
}

fn type_err_to_str(&ty.type_err err) -> str {
    alt (err) {
        case (terr_mismatch) {
            ret "types differ";
        }
2653 2654 2655 2656 2657 2658
        case (terr_box_mutability) {
            ret "boxed values differ in mutability";
        }
        case (terr_vec_mutability) {
            ret "vectors differ in mutability";
        }
2659
        case (terr_tuple_size(?e_sz, ?a_sz)) {
2660 2661
            ret "expected a tuple with " + UInt.to_str(e_sz, 10u) +
                " elements but found one with " + UInt.to_str(a_sz, 10u) +
2662 2663 2664 2665 2666 2667
                " elements";
        }
        case (terr_tuple_mutability) {
            ret "tuple elements differ in mutability";
        }
        case (terr_record_size(?e_sz, ?a_sz)) {
2668 2669
            ret "expected a record with " + UInt.to_str(e_sz, 10u) +
                " fields but found one with " + UInt.to_str(a_sz, 10u) +
2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682
                " 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 已提交
2683 2684 2685 2686 2687 2688 2689 2690
        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 +
                "'";
        }
2691 2692 2693
    }
}

2694
// Performs bound type parameter replacement using the supplied mapping from
2695
// parameter IDs to types.
2696
fn substitute_type_params(&ctxt cx, &vec[t] bindings, &t typ) -> t {
2697
    if (!type_contains_bound_params(cx, typ)) {
2698 2699
        ret typ;
    }
2700 2701
    fn replacer(ctxt cx, vec[t] bindings, t typ) -> t {
        alt (struct(cx, typ)) {
2702 2703
            case (ty_bound_param(?param_index)) {
                ret bindings.(param_index);
2704
            }
2705
            case (_) { ret typ; }
2706 2707
        }
    }
2708

2709 2710
    auto f = bind replacer(cx, bindings, _);
    ret fold_ty(cx, f, typ);
2711 2712
}

2713
// Converts type parameters in a type to bound type parameters.
2714
fn bind_params_in_type(&ctxt cx, &t typ) -> t {
2715 2716 2717
    if (!type_contains_params(cx, typ)) {
        ret typ;
    }
2718 2719
    fn binder(ctxt cx, t typ) -> t {
        alt (struct(cx, typ)) {
2720
            case (ty_bound_param(?index)) {
2721
                log_err "bind_params_in_type() called on type that already " +
2722 2723
                    "has bound params in it";
                fail;
2724
            }
2725
            case (ty_param(?index)) { ret mk_bound_param(cx, index); }
2726
            case (_) { ret typ; }
2727 2728 2729
        }
    }

2730 2731
    auto f = bind binder(cx, _);
    ret fold_ty(cx, f, typ);
2732 2733
}

2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755

fn def_has_ty_params(&ast.def def) -> bool {
    alt (def) {
        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;  }
    }
}

// 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.
2756
fn lookup_item_type(session.session sess,
2757
                    ctxt cx,
2758
                    &type_cache cache,
2759
                    ast.def_id did) -> ty_param_count_and_ty {
2760 2761 2762 2763 2764 2765
    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.
        ret cache.get(did);
    }

2766 2767 2768
    alt (cache.find(did)) {
        case (some[ty_param_count_and_ty](?tpt)) { ret tpt; }
        case (none[ty_param_count_and_ty]) {
2769
            auto tyt = creader.get_type(sess, cx, did);
2770 2771 2772
            cache.insert(did, tyt);
            ret tyt;
        }
2773 2774 2775 2776
    }
}


2777 2778 2779 2780 2781 2782
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
2783
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
2784
// End: