Revert "break out type checking of alts/patterns"
This reverts commit 8d1c1720e3
.
This commit is contained in:
parent
8d1c1720e3
commit
da98e14c94
@ -559,6 +559,15 @@ fn valid_range_bounds(ccx: @crate_ctxt, from: @ast::expr, to: @ast::expr)
|
||||
const_eval::compare_lit_exprs(ccx.tcx, from, to) <= 0
|
||||
}
|
||||
|
||||
type pat_ctxt = {
|
||||
fcx: @fn_ctxt,
|
||||
map: pat_id_map,
|
||||
alt_region: ty::region,
|
||||
block_region: ty::region,
|
||||
/* Equal to either alt_region or block_region. */
|
||||
pat_region: ty::region
|
||||
};
|
||||
|
||||
// Helper for the other universally_quantify_*() routines. Extracts the bound
|
||||
// regions from bound_tys and then replaces those same regions with fresh
|
||||
// variables in `sty`, returning the resulting type.
|
||||
@ -664,6 +673,223 @@ fn replace_bound_regions(
|
||||
}
|
||||
}
|
||||
|
||||
fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
||||
subpats: option<[@ast::pat]>, expected: ty::t) {
|
||||
|
||||
// Typecheck the path.
|
||||
let fcx = pcx.fcx;
|
||||
let tcx = pcx.fcx.ccx.tcx;
|
||||
|
||||
// Lookup the enum and variant def ids:
|
||||
let v_def = lookup_def(pcx.fcx, path.span, pat.id);
|
||||
let v_def_ids = ast_util::variant_def_ids(v_def);
|
||||
|
||||
// Assign the pattern the type of the *enum*, not the variant.
|
||||
let enum_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
|
||||
instantiate_path(pcx.fcx, path, enum_tpt, pat.span, pat.id);
|
||||
|
||||
// Take the enum type params out of `expected`.
|
||||
alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_enum(_, expected_substs) {
|
||||
// check that the type of the value being matched is a subtype
|
||||
// of the type of the pattern:
|
||||
let pat_ty = fcx.node_ty(pat.id);
|
||||
demand::suptype(fcx, pat.span, pat_ty, expected);
|
||||
|
||||
// Get the expected types of the arguments.
|
||||
let arg_types = {
|
||||
let vinfo =
|
||||
ty::enum_variant_with_id(
|
||||
tcx, v_def_ids.enm, v_def_ids.var);
|
||||
vinfo.args.map { |t| ty::subst(tcx, expected_substs, t) }
|
||||
};
|
||||
let arg_len = arg_types.len(), subpats_len = alt subpats {
|
||||
none { arg_len }
|
||||
some(ps) { ps.len() }};
|
||||
if arg_len > 0u {
|
||||
// N-ary variant.
|
||||
if arg_len != subpats_len {
|
||||
let s = #fmt["this pattern has %u field%s, but the \
|
||||
corresponding variant has %u field%s",
|
||||
subpats_len,
|
||||
if subpats_len == 1u { "" } else { "s" },
|
||||
arg_len,
|
||||
if arg_len == 1u { "" } else { "s" }];
|
||||
tcx.sess.span_fatal(pat.span, s);
|
||||
}
|
||||
|
||||
option::iter(subpats) {|pats|
|
||||
vec::iter2(pats, arg_types) {|subpat, arg_ty|
|
||||
check_pat(pcx, subpat, arg_ty);
|
||||
}
|
||||
};
|
||||
} else if subpats_len > 0u {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, #fmt["this pattern has %u field%s, \
|
||||
but the corresponding variant has no fields",
|
||||
subpats_len,
|
||||
if subpats_len == 1u { "" }
|
||||
else { "s" }]);
|
||||
}
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span,
|
||||
#fmt["mismatched types: expected enum but found `%s`",
|
||||
fcx.ty_to_str(expected)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pattern checking is top-down rather than bottom-up so that bindings get
|
||||
// their types immediately.
|
||||
fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
|
||||
let fcx = pcx.fcx;
|
||||
let tcx = pcx.fcx.ccx.tcx;
|
||||
alt pat.node {
|
||||
ast::pat_wild {
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
ast::pat_lit(lt) {
|
||||
check_expr_with(pcx.fcx, lt, expected);
|
||||
fcx.write_ty(pat.id, fcx.expr_ty(lt));
|
||||
}
|
||||
ast::pat_range(begin, end) {
|
||||
check_expr_with(pcx.fcx, begin, expected);
|
||||
check_expr_with(pcx.fcx, end, expected);
|
||||
let b_ty = resolve_type_vars_if_possible(pcx.fcx,
|
||||
fcx.expr_ty(begin));
|
||||
if !require_same_types(
|
||||
tcx, pat.span, b_ty,
|
||||
resolve_type_vars_if_possible(
|
||||
pcx.fcx, fcx.expr_ty(end)),
|
||||
{|| "mismatched types in range" }) {
|
||||
// no-op
|
||||
} else if !ty::type_is_numeric(b_ty) {
|
||||
tcx.sess.span_err(pat.span, "non-numeric type used in range");
|
||||
} else if !valid_range_bounds(pcx.fcx.ccx, begin, end) {
|
||||
tcx.sess.span_err(begin.span, "lower range bound must be less \
|
||||
than upper");
|
||||
}
|
||||
fcx.write_ty(pat.id, b_ty);
|
||||
}
|
||||
ast::pat_ident(name, sub) if !pat_is_variant(tcx.def_map, pat) {
|
||||
let vid = lookup_local(pcx.fcx, pat.span, pat.id);
|
||||
let mut typ = ty::mk_var(tcx, vid);
|
||||
demand::suptype(pcx.fcx, pat.span, expected, typ);
|
||||
let canon_id = pcx.map.get(pat_util::path_to_ident(name));
|
||||
if canon_id != pat.id {
|
||||
let tv_id = lookup_local(pcx.fcx, pat.span, canon_id);
|
||||
let ct = ty::mk_var(tcx, tv_id);
|
||||
demand::suptype(pcx.fcx, pat.span, ct, typ);
|
||||
}
|
||||
fcx.write_ty(pat.id, typ);
|
||||
alt sub {
|
||||
some(p) { check_pat(pcx, p, expected); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_ident(path, c) {
|
||||
check_pat_variant(pcx, pat, path, some([]), expected);
|
||||
}
|
||||
ast::pat_enum(path, subpats) {
|
||||
check_pat_variant(pcx, pat, path, subpats, expected);
|
||||
}
|
||||
ast::pat_rec(fields, etc) {
|
||||
let ex_fields = alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_rec(fields) { fields }
|
||||
_ {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span,
|
||||
#fmt["mismatched types: expected `%s` but found record",
|
||||
fcx.ty_to_str(expected)]);
|
||||
}
|
||||
};
|
||||
let f_count = vec::len(fields);
|
||||
let ex_f_count = vec::len(ex_fields);
|
||||
if ex_f_count < f_count || !etc && ex_f_count > f_count {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, #fmt["mismatched types: expected a record \
|
||||
with %u fields, found one with %u \
|
||||
fields",
|
||||
ex_f_count, f_count]);
|
||||
}
|
||||
fn matches(name: str, f: ty::field) -> bool {
|
||||
ret str::eq(name, f.ident);
|
||||
}
|
||||
for fields.each {|f|
|
||||
alt vec::find(ex_fields, bind matches(f.ident, _)) {
|
||||
some(field) {
|
||||
check_pat(pcx, f.pat, field.mt.ty);
|
||||
}
|
||||
none {
|
||||
tcx.sess.span_fatal(pat.span,
|
||||
#fmt["mismatched types: did not \
|
||||
expect a record with a field `%s`",
|
||||
f.ident]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
ast::pat_tup(elts) {
|
||||
let ex_elts = alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_tup(elts) { elts }
|
||||
_ {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span,
|
||||
#fmt["mismatched types: expected `%s`, found tuple",
|
||||
fcx.ty_to_str(expected)]);
|
||||
}
|
||||
};
|
||||
let e_count = vec::len(elts);
|
||||
if e_count != vec::len(ex_elts) {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, #fmt["mismatched types: expected a tuple \
|
||||
with %u fields, found one with %u \
|
||||
fields", vec::len(ex_elts), e_count]);
|
||||
}
|
||||
let mut i = 0u;
|
||||
for elts.each {|elt|
|
||||
check_pat(pcx, elt, ex_elts[i]);
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
ast::pat_box(inner) {
|
||||
alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_box(e_inner) {
|
||||
check_pat(pcx, inner, e_inner.ty);
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal(
|
||||
pat.span,
|
||||
"mismatched types: expected `" +
|
||||
pcx.fcx.ty_to_str(expected) +
|
||||
"` found box");
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::pat_uniq(inner) {
|
||||
alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_uniq(e_inner) {
|
||||
check_pat(pcx, inner, e_inner.ty);
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal(
|
||||
pat.span,
|
||||
"mismatched types: expected `" +
|
||||
pcx.fcx.ty_to_str(expected) +
|
||||
"` found uniq");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr_with(fcx: @fn_ctxt, expr: @ast::expr, expected: ty::t) -> bool {
|
||||
check_expr(fcx, expr, some(expected))
|
||||
}
|
||||
@ -1644,7 +1870,38 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||
bot = !may_break(body);
|
||||
}
|
||||
ast::expr_alt(discrim, arms, _) {
|
||||
alt::check_alt(expr, discrim, arms);
|
||||
let pattern_ty = fcx.next_ty_var();
|
||||
bot = check_expr_with(fcx, discrim, pattern_ty);
|
||||
|
||||
// Typecheck the patterns first, so that we get types for all the
|
||||
// bindings.
|
||||
//let pattern_ty = fcx.expr_ty(discrim);
|
||||
for arms.each {|arm|
|
||||
let pcx = {
|
||||
fcx: fcx,
|
||||
map: pat_id_map(tcx.def_map, arm.pats[0]),
|
||||
alt_region: ty::re_scope(expr.id),
|
||||
block_region: ty::re_scope(arm.body.node.id),
|
||||
pat_region: ty::re_scope(expr.id)
|
||||
};
|
||||
|
||||
for arm.pats.each {|p| check_pat(pcx, p, pattern_ty);}
|
||||
}
|
||||
// Now typecheck the blocks.
|
||||
let mut result_ty = fcx.next_ty_var();
|
||||
let mut arm_non_bot = false;
|
||||
for arms.each {|arm|
|
||||
alt arm.guard {
|
||||
some(e) { check_expr_with(fcx, e, ty::mk_bool(tcx)); }
|
||||
none { }
|
||||
}
|
||||
if !check_block(fcx, arm.body) { arm_non_bot = true; }
|
||||
let bty = fcx.node_ty(arm.body.node.id);
|
||||
demand::suptype(fcx, arm.body.span, result_ty, bty);
|
||||
}
|
||||
bot |= !arm_non_bot;
|
||||
if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
|
||||
fcx.write_ty(id, result_ty);
|
||||
}
|
||||
ast::expr_fn(proto, decl, body, cap_clause) {
|
||||
check_expr_fn(fcx, expr, proto, decl, body, false, expected);
|
||||
|
@ -1,263 +0,0 @@
|
||||
fn check_alt(fcx: @fn_ctxt,
|
||||
expr: @ast::expr,
|
||||
discrim: @ast::expr,
|
||||
arms: [ast::arm]) {
|
||||
let pattern_ty = fcx.next_ty_var();
|
||||
bot = check_expr_with(fcx, discrim, pattern_ty);
|
||||
|
||||
// Typecheck the patterns first, so that we get types for all the
|
||||
// bindings.
|
||||
for arms.each {|arm|
|
||||
let pcx = {
|
||||
fcx: fcx,
|
||||
map: pat_id_map(tcx.def_map, arm.pats[0]),
|
||||
alt_region: ty::re_scope(expr.id),
|
||||
block_region: ty::re_scope(arm.body.node.id),
|
||||
pat_region: ty::re_scope(expr.id)
|
||||
};
|
||||
|
||||
for arm.pats.each {|p| check_pat(pcx, p, pattern_ty);}
|
||||
}
|
||||
// Now typecheck the blocks.
|
||||
let mut result_ty = fcx.next_ty_var();
|
||||
let mut arm_non_bot = false;
|
||||
for arms.each {|arm|
|
||||
alt arm.guard {
|
||||
some(e) { check_expr_with(fcx, e, ty::mk_bool(tcx)); }
|
||||
none { }
|
||||
}
|
||||
if !check_block(fcx, arm.body) { arm_non_bot = true; }
|
||||
let bty = fcx.node_ty(arm.body.node.id);
|
||||
demand::suptype(fcx, arm.body.span, result_ty, bty);
|
||||
}
|
||||
bot |= !arm_non_bot;
|
||||
if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
|
||||
fcx.write_ty(id, result_ty);
|
||||
}
|
||||
|
||||
type pat_ctxt = {
|
||||
fcx: @fn_ctxt,
|
||||
map: pat_id_map,
|
||||
alt_region: ty::region,
|
||||
block_region: ty::region,
|
||||
/* Equal to either alt_region or block_region. */
|
||||
pat_region: ty::region
|
||||
};
|
||||
|
||||
fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
|
||||
subpats: option<[@ast::pat]>, expected: ty::t) {
|
||||
|
||||
// Typecheck the path.
|
||||
let fcx = pcx.fcx;
|
||||
let tcx = pcx.fcx.ccx.tcx;
|
||||
|
||||
// Lookup the enum and variant def ids:
|
||||
let v_def = lookup_def(pcx.fcx, path.span, pat.id);
|
||||
let v_def_ids = ast_util::variant_def_ids(v_def);
|
||||
|
||||
// Assign the pattern the type of the *enum*, not the variant.
|
||||
let enum_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
|
||||
instantiate_path(pcx.fcx, path, enum_tpt, pat.span, pat.id);
|
||||
|
||||
// Take the enum type params out of `expected`.
|
||||
alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_enum(_, expected_substs) {
|
||||
// check that the type of the value being matched is a subtype
|
||||
// of the type of the pattern:
|
||||
let pat_ty = fcx.node_ty(pat.id);
|
||||
demand::suptype(fcx, pat.span, pat_ty, expected);
|
||||
|
||||
// Get the expected types of the arguments.
|
||||
let arg_types = {
|
||||
let vinfo =
|
||||
ty::enum_variant_with_id(
|
||||
tcx, v_def_ids.enm, v_def_ids.var);
|
||||
vinfo.args.map { |t| ty::subst(tcx, expected_substs, t) }
|
||||
};
|
||||
let arg_len = arg_types.len(), subpats_len = alt subpats {
|
||||
none { arg_len }
|
||||
some(ps) { ps.len() }};
|
||||
if arg_len > 0u {
|
||||
// N-ary variant.
|
||||
if arg_len != subpats_len {
|
||||
let s = #fmt["this pattern has %u field%s, but the \
|
||||
corresponding variant has %u field%s",
|
||||
subpats_len,
|
||||
if subpats_len == 1u { "" } else { "s" },
|
||||
arg_len,
|
||||
if arg_len == 1u { "" } else { "s" }];
|
||||
tcx.sess.span_fatal(pat.span, s);
|
||||
}
|
||||
|
||||
option::iter(subpats) {|pats|
|
||||
vec::iter2(pats, arg_types) {|subpat, arg_ty|
|
||||
check_pat(pcx, subpat, arg_ty);
|
||||
}
|
||||
};
|
||||
} else if subpats_len > 0u {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, #fmt["this pattern has %u field%s, \
|
||||
but the corresponding variant has no fields",
|
||||
subpats_len,
|
||||
if subpats_len == 1u { "" }
|
||||
else { "s" }]);
|
||||
}
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span,
|
||||
#fmt["mismatched types: expected enum but found `%s`",
|
||||
fcx.ty_to_str(expected)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pattern checking is top-down rather than bottom-up so that bindings get
|
||||
// their types immediately.
|
||||
fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
|
||||
let fcx = pcx.fcx;
|
||||
let tcx = pcx.fcx.ccx.tcx;
|
||||
alt pat.node {
|
||||
ast::pat_wild {
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
ast::pat_lit(lt) {
|
||||
check_expr_with(pcx.fcx, lt, expected);
|
||||
fcx.write_ty(pat.id, fcx.expr_ty(lt));
|
||||
}
|
||||
ast::pat_range(begin, end) {
|
||||
check_expr_with(pcx.fcx, begin, expected);
|
||||
check_expr_with(pcx.fcx, end, expected);
|
||||
let b_ty = resolve_type_vars_if_possible(pcx.fcx,
|
||||
fcx.expr_ty(begin));
|
||||
if !require_same_types(
|
||||
tcx, pat.span, b_ty,
|
||||
resolve_type_vars_if_possible(
|
||||
pcx.fcx, fcx.expr_ty(end)),
|
||||
{|| "mismatched types in range" }) {
|
||||
// no-op
|
||||
} else if !ty::type_is_numeric(b_ty) {
|
||||
tcx.sess.span_err(pat.span, "non-numeric type used in range");
|
||||
} else if !valid_range_bounds(pcx.fcx.ccx, begin, end) {
|
||||
tcx.sess.span_err(begin.span, "lower range bound must be less \
|
||||
than upper");
|
||||
}
|
||||
fcx.write_ty(pat.id, b_ty);
|
||||
}
|
||||
ast::pat_ident(name, sub) if !pat_is_variant(tcx.def_map, pat) {
|
||||
let vid = lookup_local(pcx.fcx, pat.span, pat.id);
|
||||
let mut typ = ty::mk_var(tcx, vid);
|
||||
demand::suptype(pcx.fcx, pat.span, expected, typ);
|
||||
let canon_id = pcx.map.get(pat_util::path_to_ident(name));
|
||||
if canon_id != pat.id {
|
||||
let tv_id = lookup_local(pcx.fcx, pat.span, canon_id);
|
||||
let ct = ty::mk_var(tcx, tv_id);
|
||||
demand::suptype(pcx.fcx, pat.span, ct, typ);
|
||||
}
|
||||
fcx.write_ty(pat.id, typ);
|
||||
alt sub {
|
||||
some(p) { check_pat(pcx, p, expected); }
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
ast::pat_ident(path, c) {
|
||||
check_pat_variant(pcx, pat, path, some([]), expected);
|
||||
}
|
||||
ast::pat_enum(path, subpats) {
|
||||
check_pat_variant(pcx, pat, path, subpats, expected);
|
||||
}
|
||||
ast::pat_rec(fields, etc) {
|
||||
let ex_fields = alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_rec(fields) { fields }
|
||||
_ {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span,
|
||||
#fmt["mismatched types: expected `%s` but found record",
|
||||
fcx.ty_to_str(expected)]);
|
||||
}
|
||||
};
|
||||
let f_count = vec::len(fields);
|
||||
let ex_f_count = vec::len(ex_fields);
|
||||
if ex_f_count < f_count || !etc && ex_f_count > f_count {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, #fmt["mismatched types: expected a record \
|
||||
with %u fields, found one with %u \
|
||||
fields",
|
||||
ex_f_count, f_count]);
|
||||
}
|
||||
fn matches(name: str, f: ty::field) -> bool {
|
||||
ret str::eq(name, f.ident);
|
||||
}
|
||||
for fields.each {|f|
|
||||
alt vec::find(ex_fields, bind matches(f.ident, _)) {
|
||||
some(field) {
|
||||
check_pat(pcx, f.pat, field.mt.ty);
|
||||
}
|
||||
none {
|
||||
tcx.sess.span_fatal(pat.span,
|
||||
#fmt["mismatched types: did not \
|
||||
expect a record with a field `%s`",
|
||||
f.ident]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
ast::pat_tup(elts) {
|
||||
let ex_elts = alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_tup(elts) { elts }
|
||||
_ {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span,
|
||||
#fmt["mismatched types: expected `%s`, found tuple",
|
||||
fcx.ty_to_str(expected)]);
|
||||
}
|
||||
};
|
||||
let e_count = vec::len(elts);
|
||||
if e_count != vec::len(ex_elts) {
|
||||
tcx.sess.span_fatal
|
||||
(pat.span, #fmt["mismatched types: expected a tuple \
|
||||
with %u fields, found one with %u \
|
||||
fields", vec::len(ex_elts), e_count]);
|
||||
}
|
||||
let mut i = 0u;
|
||||
for elts.each {|elt|
|
||||
check_pat(pcx, elt, ex_elts[i]);
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
ast::pat_box(inner) {
|
||||
alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_box(e_inner) {
|
||||
check_pat(pcx, inner, e_inner.ty);
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal(
|
||||
pat.span,
|
||||
"mismatched types: expected `" +
|
||||
pcx.fcx.ty_to_str(expected) +
|
||||
"` found box");
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::pat_uniq(inner) {
|
||||
alt structure_of(pcx.fcx, pat.span, expected) {
|
||||
ty::ty_uniq(e_inner) {
|
||||
check_pat(pcx, inner, e_inner.ty);
|
||||
fcx.write_ty(pat.id, expected);
|
||||
}
|
||||
_ {
|
||||
tcx.sess.span_fatal(
|
||||
pat.span,
|
||||
"mismatched types: expected `" +
|
||||
pcx.fcx.ty_to_str(expected) +
|
||||
"` found uniq");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,7 @@ mod middle {
|
||||
mod ast_map;
|
||||
mod resolve;
|
||||
mod typeck {
|
||||
mod check {
|
||||
mod alt;
|
||||
}
|
||||
mod check;
|
||||
mod regionck;
|
||||
mod demand;
|
||||
mod infer;
|
||||
|
Loading…
Reference in New Issue
Block a user