Make _|_ unify with anything

The typechecker had a number of special cases for unifying types
with _|_ (as with checking if and alt). But, a value of type _|_
should be usable in any context, as such a value always diverges,
and will never be used by its immediate context. Changed unify
accordingly, removed special cases.
This commit is contained in:
Tim Chevalier 2011-05-26 20:14:00 -07:00
parent af6b4821c1
commit 1a96e79fe0
5 changed files with 54 additions and 12 deletions

View File

@ -2209,6 +2209,12 @@ mod unify {
if (eq_ty(expected, actual)) { ret ures_ok(expected); }
alt (struct(cx.tcx, actual)) {
// a _|_ type can be used anywhere
case (ty::ty_bot) {
ret ures_ok(expected);
}
// If the RHS is a variable type, then just do the appropriate
// binding.
case (ty::ty_var(?actual_id)) {

View File

@ -1341,17 +1341,13 @@ mod pushdown {
ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
auto then_t = ty::block_ty(scx.fcx.ccx.tcx, then_0);
if (!ty::type_is_bot(scx.fcx.ccx.tcx, then_t)) {
pushdown_block(scx, expected, then_0);
}
pushdown_block(scx, expected, then_0);
alt (else_0) {
case (none[@ast::expr]) { /* no-op */ }
case (some[@ast::expr](?e_0)) {
auto else_t = ty::expr_ty(scx.fcx.ccx.tcx, e_0);
if (!ty::type_is_bot(scx.fcx.ccx.tcx, else_t)) {
pushdown_expr(scx, expected, e_0);
}
pushdown_expr(scx, expected, e_0);
}
}
write::ty_only_fixup(scx, ann.id, t);
@ -1472,10 +1468,7 @@ mod pushdown {
for (ast::arm arm_0 in arms_0) {
pushdown_block(scx, expected, arm_0.block);
auto bty = block_ty(scx.fcx.ccx.tcx, arm_0.block);
// Failing alt arms don't need to have a matching type
if (!ty::type_is_bot(scx.fcx.ccx.tcx, bty)) {
t = demand::simple(scx, e.span, t, bty);
}
t = demand::simple(scx, e.span, t, bty);
}
write::ty_only_fixup(scx, ann.id, t);
}
@ -2245,8 +2238,6 @@ fn check_expr(&@stmt_ctxt scx, &@ast::expr expr) {
pushdown::pushdown_expr(scx, pattern_ty, expr);
// FIXME: If all the the arms were ty_bot then the result should
// also be ty_bot. At the moment this doesn't seem to matter
write::ty_only_fixup(scx, a.id, result_ty);
}

View File

@ -0,0 +1,21 @@
// xfail-stage0
// xfail-stage1
// xfail-stage2
// xfail-stage3
use std;
import std::option::*;
fn foo(str s) {
}
fn main() {
auto i = alt (some[int](3)) {
case (none[int]) {
fail
}
case (some[int](_)) {
fail
}
};
foo(i);
}

View File

@ -0,0 +1,15 @@
// xfail-stage0
use std;
import std::option::*;
fn main() {
let int i = alt (some[int](3)) {
case (none[int]) {
fail
}
case (some[int](_)) {
5
}
};
log i;
}

View File

@ -0,0 +1,9 @@
fn main() {
let int i = if (false) {
fail
}
else {
5
};
log i;
}