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:
parent
af6b4821c1
commit
1a96e79fe0
5 changed files with 54 additions and 12 deletions
|
@ -2209,6 +2209,12 @@ mod unify {
|
||||||
if (eq_ty(expected, actual)) { ret ures_ok(expected); }
|
if (eq_ty(expected, actual)) { ret ures_ok(expected); }
|
||||||
|
|
||||||
alt (struct(cx.tcx, actual)) {
|
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
|
// If the RHS is a variable type, then just do the appropriate
|
||||||
// binding.
|
// binding.
|
||||||
case (ty::ty_var(?actual_id)) {
|
case (ty::ty_var(?actual_id)) {
|
||||||
|
|
|
@ -1341,19 +1341,15 @@ mod pushdown {
|
||||||
ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
|
ann_to_type(scx.fcx.ccx.tcx.node_types, ann), adk);
|
||||||
|
|
||||||
auto then_t = ty::block_ty(scx.fcx.ccx.tcx, then_0);
|
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) {
|
alt (else_0) {
|
||||||
case (none[@ast::expr]) { /* no-op */ }
|
case (none[@ast::expr]) { /* no-op */ }
|
||||||
case (some[@ast::expr](?e_0)) {
|
case (some[@ast::expr](?e_0)) {
|
||||||
auto else_t = ty::expr_ty(scx.fcx.ccx.tcx, 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);
|
write::ty_only_fixup(scx, ann.id, t);
|
||||||
}
|
}
|
||||||
case (ast::expr_for(?decl, ?seq, ?bloc, ?ann)) {
|
case (ast::expr_for(?decl, ?seq, ?bloc, ?ann)) {
|
||||||
|
@ -1472,11 +1468,8 @@ mod pushdown {
|
||||||
for (ast::arm arm_0 in arms_0) {
|
for (ast::arm arm_0 in arms_0) {
|
||||||
pushdown_block(scx, expected, arm_0.block);
|
pushdown_block(scx, expected, arm_0.block);
|
||||||
auto bty = block_ty(scx.fcx.ccx.tcx, 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);
|
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);
|
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);
|
write::ty_only_fixup(scx, a.id, result_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
src/test/run-fail/alt-bot-fail.rs
Normal file
21
src/test/run-fail/alt-bot-fail.rs
Normal 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);
|
||||||
|
}
|
15
src/test/run-pass/alt-bot.rs
Normal file
15
src/test/run-pass/alt-bot.rs
Normal 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;
|
||||||
|
}
|
9
src/test/run-pass/if-bot.rs
Normal file
9
src/test/run-pass/if-bot.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
fn main() {
|
||||||
|
let int i = if (false) {
|
||||||
|
fail
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
5
|
||||||
|
};
|
||||||
|
log i;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue