Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make typechecker compositional #5461

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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