diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs index 435b1cb7f34..06f6185586d 100644 --- a/src/libcore/cleanup.rs +++ b/src/libcore/cleanup.rs @@ -15,7 +15,7 @@ use ptr::mut_null; use repr::BoxRepr; use sys::TypeDesc; use cast::transmute; -use unstable::lang::clear_task_borrow_list; +#[cfg(notest)] use unstable::lang::clear_task_borrow_list; #[cfg(notest)] use ptr::to_unsafe_ptr; diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 3b9bbbb9f1c..582e1d606bc 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -188,6 +188,9 @@ pub impl Session_ { fn err(@self, msg: &str) { self.span_diagnostic.handler().err(msg) } + fn err_count(@self) -> uint { + self.span_diagnostic.handler().err_count() + } fn has_errors(@self) -> bool { self.span_diagnostic.handler().has_errors() } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 5357d092a90..7e63db89edb 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -207,9 +207,11 @@ pub impl PurityState { } pub struct FnCtxt { - // var_bindings, locals and next_var_id are shared - // with any nested functions that capture the environment - // (and with any functions whose environment is being captured). + // Number of errors that had been reported when we started + // checking this function. On exit, if we find that *more* errors + // have been reported, we will skip regionck and other work that + // expects the types within the function to be consistent. + err_count_on_creation: uint, ret_ty: ty::t, // Used by loop bodies that return from the outer function @@ -263,6 +265,7 @@ pub fn blank_fn_ctxt(ccx: @mut CrateCtxt, // It's kind of a kludge to manufacture a fake function context // and statement context, but we might as well do write the code only once @mut FnCtxt { + err_count_on_creation: ccx.tcx.sess.err_count(), ret_ty: rty, indirect_ret_ty: None, ps: PurityState::function(ast::pure_fn, 0), @@ -328,6 +331,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, */ let tcx = ccx.tcx; + let err_count_on_creation = tcx.sess.err_count(); // ______________________________________________________________________ // First, we have to replace any bound regions in the fn and self @@ -368,6 +372,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, }; @mut FnCtxt { + err_count_on_creation: err_count_on_creation, ret_ty: ret_ty, indirect_ret_ty: indirect_ret_ty, ps: PurityState::function(purity, id), @@ -642,7 +647,12 @@ impl AstConv for FnCtxt { } pub impl FnCtxt { - fn infcx(&self) -> @mut infer::InferCtxt { self.inh.infcx } + fn infcx(&self) -> @mut infer::InferCtxt { + self.inh.infcx + } + fn err_count_since_creation(&self) -> uint { + self.ccx.tcx.sess.err_count() - self.err_count_on_creation + } fn search_in_scope_regions( &self, span: span, diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index b4a1cab7b21..03dd32353db 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -138,7 +138,8 @@ pub impl Rcx { pub fn regionck_expr(fcx: @mut FnCtxt, e: @ast::expr) { let rcx = @mut Rcx { fcx: fcx, errors_reported: 0 }; - if !fcx.tcx().sess.has_errors() { // regionck assumes typeck succeeded + if fcx.err_count_since_creation() == 0 { + // regionck assumes typeck succeeded let v = regionck_visitor(); (v.visit_expr)(e, rcx, v); } @@ -147,7 +148,8 @@ pub fn regionck_expr(fcx: @mut FnCtxt, e: @ast::expr) { pub fn regionck_fn(fcx: @mut FnCtxt, blk: &ast::blk) { let rcx = @mut Rcx { fcx: fcx, errors_reported: 0 }; - if !fcx.tcx().sess.has_errors() { // regionck assumes typeck succeeded + if fcx.err_count_since_creation() == 0 { + // regionck assumes typeck succeeded let v = regionck_visitor(); (v.visit_block)(blk, rcx, v); } @@ -409,10 +411,6 @@ fn constrain_callee(rcx: @mut Rcx, let call_region = ty::re_scope(call_expr.id); let callee_ty = rcx.resolve_node_type(call_expr.callee_id); - if ty::type_is_error(callee_ty) { - return; - } - match ty::get(callee_ty).sty { ty::ty_bare_fn(*) => { } ty::ty_closure(ref closure_ty) => { @@ -432,9 +430,12 @@ fn constrain_callee(rcx: @mut Rcx, } } _ => { - tcx.sess.span_bug( - callee_expr.span, - fmt!("Calling non-function: %s", callee_ty.repr(tcx))); + // this should not happen, but it does if the program is + // erroneous + // + // tcx.sess.span_bug( + // callee_expr.span, + // fmt!("Calling non-function: %s", callee_ty.repr(tcx))); } } } @@ -456,9 +457,6 @@ fn constrain_call(rcx: @mut Rcx, debug!("constrain_call(call_expr=%s, implicitly_ref_args=%?)", call_expr.repr(tcx), implicitly_ref_args); let callee_ty = rcx.resolve_node_type(call_expr.callee_id); - if ty::type_is_error(callee_ty) { - return; - } let fn_sig = ty::ty_fn_sig(callee_ty); // `callee_region` is the scope representing the time in which the @@ -919,7 +917,7 @@ pub mod guarantor { // expressions, both of which always yield a region variable, so // mk_subr should never fail. let rptr_ty = rcx.resolve_node_type(id); - if !ty::type_is_error(rptr_ty) && !ty::type_is_bot(rptr_ty) { + if !ty::type_is_bot(rptr_ty) { let tcx = rcx.fcx.ccx.tcx; debug!("rptr_ty=%s", ty_to_str(tcx, rptr_ty)); let r = ty::ty_region(tcx, span, rptr_ty); @@ -1216,29 +1214,25 @@ pub mod guarantor { } ast::pat_region(p) => { let rptr_ty = rcx.resolve_node_type(pat.id); - if !ty::type_is_error(rptr_ty) { - let r = ty::ty_region(rcx.fcx.tcx(), pat.span, rptr_ty); - link_ref_bindings_in_pat(rcx, p, Some(r)); - } + let r = ty::ty_region(rcx.fcx.tcx(), pat.span, rptr_ty); + link_ref_bindings_in_pat(rcx, p, Some(r)); } ast::pat_lit(*) => {} ast::pat_range(*) => {} ast::pat_vec(ref before, ref slice, ref after) => { let vec_ty = rcx.resolve_node_type(pat.id); - if !ty::type_is_error(vec_ty) { - let vstore = ty::ty_vstore(vec_ty); - let guarantor1 = match vstore { - ty::vstore_fixed(_) | ty::vstore_uniq => guarantor, - ty::vstore_slice(r) => Some(r), - ty::vstore_box => None - }; + let vstore = ty::ty_vstore(vec_ty); + let guarantor1 = match vstore { + ty::vstore_fixed(_) | ty::vstore_uniq => guarantor, + ty::vstore_slice(r) => Some(r), + ty::vstore_box => None + }; - link_ref_bindings_in_pats(rcx, before, guarantor1); - for slice.each |&p| { - link_ref_bindings_in_pat(rcx, p, guarantor); - } - link_ref_bindings_in_pats(rcx, after, guarantor1); + link_ref_bindings_in_pats(rcx, before, guarantor1); + for slice.each |&p| { + link_ref_bindings_in_pat(rcx, p, guarantor); } + link_ref_bindings_in_pats(rcx, after, guarantor1); } } } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 0012eb70030..1a152f3c291 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -414,7 +414,11 @@ pub fn check_crate(tcx: ty::ctxt, time(time_passes, ~"type collecting", || collect::collect_item_types(ccx, crate)); - time(time_passes, ~"method resolution", || + // this ensures that later parts of type checking can assume that items + // have valid types and not error + tcx.sess.abort_if_errors(); + + time(time_passes, ~"coherence checking", || coherence::check_coherence(ccx, crate)); time(time_passes, ~"type checking", || diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 0f2374a892b..b313a2fc6fc 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -24,6 +24,7 @@ pub trait handler { fn fatal(@mut self, msg: &str) -> !; fn err(@mut self, msg: &str); fn bump_err_count(@mut self); + fn err_count(@mut self) -> uint; fn has_errors(@mut self) -> bool; fn abort_if_errors(@mut self); fn warn(@mut self, msg: &str); @@ -98,7 +99,12 @@ impl handler for HandlerT { fn bump_err_count(@mut self) { self.err_count += 1u; } - fn has_errors(@mut self) -> bool { self.err_count > 0u } + fn err_count(@mut self) -> uint { + self.err_count + } + fn has_errors(@mut self) -> bool { + self.err_count > 0u + } fn abort_if_errors(@mut self) { let s; match self.err_count { diff --git a/src/test/compile-fail/dead-code-ret.rs b/src/test/compile-fail/dead-code-ret.rs index 97f6149b162..5fa796db884 100644 --- a/src/test/compile-fail/dead-code-ret.rs +++ b/src/test/compile-fail/dead-code-ret.rs @@ -10,8 +10,12 @@ // except according to those terms. -// error-pattern: dead +fn f(caller: &str) { + debug!(caller); + let x: uint = 0u32; // induce type error //~ ERROR mismatched types +} -fn f(caller: str) { debug!(caller); } - -fn main() { return f("main"); debug!("Paul is dead"); } +fn main() { + return f("main"); + debug!("Paul is dead"); //~ WARNING unreachable +} diff --git a/src/test/compile-fail/for-loop-decl.rs b/src/test/compile-fail/for-loop-decl.rs deleted file mode 100644 index de28d726777..00000000000 --- a/src/test/compile-fail/for-loop-decl.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern: mismatched types -extern mod std; -use std::bitv; -use core::hashmap::HashMap; - -struct FnInfo { - vars: HashMap -} - -struct VarInfo { - a: uint, - b: uint, -} - -fn bitv_to_str(enclosing: FnInfo, v: ~bitv::Bitv) -> str { - let s = ""; - - // error is that the value type in the hash map is var_info, not a box - for enclosing.vars.each_value |val| { - if *v.get(val) { s += "foo"; } - } - return s; -} - -fn main() { debug!("OK"); } diff --git a/src/test/compile-fail/regions-bounds.rs b/src/test/compile-fail/regions-bounds.rs index cccd135e9f8..ab2620d46fd 100644 --- a/src/test/compile-fail/regions-bounds.rs +++ b/src/test/compile-fail/regions-bounds.rs @@ -23,10 +23,8 @@ fn a_fn3<'a,'b>(e: a_class<'a>) -> a_class<'b> { return e; //~ ERROR mismatched types: expected `a_class/&'b ` but found `a_class/&'a ` } -fn a_fn4<'a,'b>(e: int<'a>) -> int<'b> { - //~^ ERROR region parameters are not allowed on this type - //~^^ ERROR region parameters are not allowed on this type - return e; +fn a_fn4<'a,'b>() { + let _: int<'a> = 1; //~ ERROR region parameters are not allowed on this type } fn main() { } diff --git a/src/test/compile-fail/regions-ret-borrowed-1.rs b/src/test/compile-fail/regions-ret-borrowed-1.rs index f600f6f6edd..a572d90313b 100644 --- a/src/test/compile-fail/regions-ret-borrowed-1.rs +++ b/src/test/compile-fail/regions-ret-borrowed-1.rs @@ -18,8 +18,6 @@ fn with<'a, R>(f: &fn(x: &'a int) -> R) -> R { fn return_it<'a>() -> &'a int { with(|o| o) //~ ERROR mismatched types - //~^ ERROR reference is not valid outside of its lifetime - //~^^ ERROR reference is not valid outside of its lifetime } fn main() { diff --git a/src/test/compile-fail/regions-ret-borrowed.rs b/src/test/compile-fail/regions-ret-borrowed.rs index a3540f8f931..ec9a908ba98 100644 --- a/src/test/compile-fail/regions-ret-borrowed.rs +++ b/src/test/compile-fail/regions-ret-borrowed.rs @@ -21,8 +21,6 @@ fn with(f: &fn(x: &int) -> R) -> R { fn return_it() -> &int { with(|o| o) //~ ERROR mismatched types - //~^ ERROR reference is not valid outside of its lifetime - //~^^ ERROR reference is not valid outside of its lifetime } fn main() { diff --git a/src/test/compile-fail/type-shadow.rs b/src/test/compile-fail/type-shadow.rs index a9b4a85e638..c4a412f64c8 100644 --- a/src/test/compile-fail/type-shadow.rs +++ b/src/test/compile-fail/type-shadow.rs @@ -9,14 +9,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -// error-pattern: mismatched types - fn main() { type X = int; type Y = X; if true { - type X = str; - let y: Y = "hello"; + type X = &'static str; + let y: Y = "hello"; //~ ERROR mismatched types } }