Skip to content

Commit

Permalink
auto merge of #5461 : catamorphism/rust/flagless, r=nikomatsakis
Browse files Browse the repository at this point in the history
r? @nikomatsakis The typechecker previously passed around a boolean return flag to
indicate whether it saw something with type _|_ (that is, something
it knows at compile-time will definitely diverge) and also had some
manual checks for the `ty_err` pseudo-type that represents a previous
type error. This was because the typing rules implemented by the
typechecker didn't properly propagate _|_ and ty_err. I fixed it.

This also required changing expected error messages in a few tests,
as now we're printing out fewer derived errors -- in fact, at this
point we should print out no derived errors, so report any that
you see (ones that include "[type error]") as bugs.
  • Loading branch information
bors committed Mar 21, 2013
2 parents 87d9316 + f36f9fc commit 6aa612a
Show file tree
Hide file tree
Showing 13 changed files with 824 additions and 495 deletions.
4 changes: 3 additions & 1 deletion src/librustc/middle/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use util::ppaux::{expr_repr, ty_to_str};

use core::libc::c_uint;
use syntax::{ast, ast_util, codemap, ast_map};
use util::ppaux::ty_to_str;

pub fn const_lit(cx: @CrateContext, e: @ast::expr, lit: ast::lit)
-> ValueRef {
Expand All @@ -45,7 +46,8 @@ pub fn const_lit(cx: @CrateContext, e: @ast::expr, lit: ast::lit)
C_integral(T_uint_ty(cx, t), i as u64, False)
}
_ => cx.sess.span_bug(lit.span,
~"integer literal doesn't have a type")
fmt!("integer literal has type %s (expected int or uint)",
ty_to_str(cx.tcx, lit_int_ty)))
}
}
ast::lit_float(fs, t) => C_floating(/*bad*/copy *fs, T_float_ty(cx, t)),
Expand Down
28 changes: 22 additions & 6 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ enum tbox_flag {
needs_infer = 4,
has_regions = 8,
has_ty_err = 16,
has_ty_bot = 32,

// a meta-flag: subst may be required if the type has parameters, a self
// type, or references bound regions
Expand Down Expand Up @@ -355,9 +356,6 @@ pub pure fn type_needs_infer(t: t) -> bool {
pub pure fn type_has_regions(t: t) -> bool {
tbox_has_flag(get(t), has_regions)
}
pub pure fn type_contains_err(t: t) -> bool {
tbox_has_flag(get(t), has_ty_err)
}
pub pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
pub pure fn type_id(t: t) -> uint { get(t).id }

Expand Down Expand Up @@ -892,9 +890,17 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
flags |= rflags(r);
flags |= get(mt.ty).flags;
}
&ty_nil | &ty_bot | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_nil | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
&ty_opaque_box => (),
// You might think that we could just return ty_err for
// any type containing ty_err as a component, and get
// rid of the has_ty_err flag -- likewise for ty_bot (with
// the exception of function types that return bot).
// But doing so caused sporadic memory corruption, and
// neither I (tjc) nor nmatsakis could figure out why,
// so we're doing it this way.
&ty_bot => flags |= has_ty_bot as uint,
&ty_err => flags |= has_ty_err as uint,
&ty_param(_) => flags |= has_params as uint,
&ty_infer(_) => flags |= needs_infer as uint,
Expand All @@ -914,12 +920,16 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
&ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
&ty_bare_fn(ref f) => {
for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
flags |= get(f.sig.output).flags;
flags |= get(f.sig.output).flags;
// T -> _|_ is *not* _|_ !
flags &= !(has_ty_bot as uint);
}
&ty_closure(ref f) => {
flags |= rflags(f.region);
for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
flags |= get(f.sig.output).flags;
// T -> _|_ is *not* _|_ !
flags &= !(has_ty_bot as uint);
}
}

Expand Down Expand Up @@ -1465,7 +1475,13 @@ pub fn subst_substs(cx: ctxt, sup: &substs, sub: &substs) -> substs {

pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }

pub fn type_is_bot(ty: t) -> bool { get(ty).sty == ty_bot }
pub fn type_is_bot(ty: t) -> bool {
(get(ty).flags & (has_ty_bot as uint)) != 0
}

pub fn type_is_error(ty: t) -> bool {
(get(ty).flags & (has_ty_err as uint)) != 0
}

pub fn type_is_ty_var(ty: t) -> bool {
match get(ty).sty {
Expand Down
42 changes: 34 additions & 8 deletions src/librustc/middle/typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ use syntax::print::pprust;
pub fn check_match(fcx: @mut FnCtxt,
expr: @ast::expr,
discrim: @ast::expr,
arms: &[ast::arm]) -> bool {
arms: &[ast::arm]) {
let tcx = fcx.ccx.tcx;
let mut bot;

let pattern_ty = fcx.infcx().next_ty_var();
bot = check_expr_has_type(fcx, discrim, pattern_ty);
check_expr_has_type(fcx, discrim, pattern_ty);

// Typecheck the patterns first, so that we get types for all the
// bindings.
Expand All @@ -51,19 +50,46 @@ pub fn check_match(fcx: @mut FnCtxt,
// Now typecheck the blocks.
let mut result_ty = fcx.infcx().next_ty_var();
let mut arm_non_bot = false;
let mut saw_err = false;
for arms.each |arm| {
let mut guard_err = false;
let mut guard_bot = false;
match arm.guard {
Some(e) => { check_expr_has_type(fcx, e, ty::mk_bool(tcx)); },
Some(e) => {
check_expr_has_type(fcx, e, ty::mk_bool(tcx));
let e_ty = fcx.expr_ty(e);
if ty::type_is_error(e_ty) {
guard_err = true;
}
else if ty::type_is_bot(e_ty) {
guard_bot = true;
}
},
None => ()
}
if !check_block(fcx, &arm.body) { arm_non_bot = true; }
check_block(fcx, &arm.body);
let bty = fcx.node_ty(arm.body.node.id);
saw_err = saw_err || ty::type_is_error(bty);
if guard_err {
fcx.write_error(arm.body.node.id);
saw_err = true;
}
else if guard_bot {
fcx.write_bot(arm.body.node.id);
}
else if !ty::type_is_bot(bty) {
arm_non_bot = true; // If the match *may* evaluate to a non-_|_
// expr, the whole thing is non-_|_
}
demand::suptype(fcx, arm.body.span, result_ty, bty);
}
bot |= !arm_non_bot;
if !arm_non_bot { result_ty = ty::mk_bot(tcx); }
if saw_err {
result_ty = ty::mk_err(tcx);
}
else if !arm_non_bot {
result_ty = ty::mk_bot(tcx);
}
fcx.write_ty(expr.id, result_ty);
return bot;
}

pub struct pat_ctxt {
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/middle/typeck/check/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ pub enum TransformTypeFlag {

pub impl LookupContext/&self {
fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
let mut self_ty = structurally_resolved_type(self.fcx,
self.self_expr.span,
self_ty);

debug!("do_lookup(self_ty=%s, expr=%s, self_expr=%s)",
self.ty_to_str(self_ty),
expr_repr(self.tcx(), self.expr),
Expand Down
Loading

0 comments on commit 6aa612a

Please sign in to comment.