refinement to technique used to not run regionck

This commit is contained in:
Niko Matsakis 2013-05-06 09:00:37 -04:00
parent e235f6ca53
commit 2ea52a38e5
12 changed files with 65 additions and 88 deletions

View file

@ -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;

View file

@ -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()
}

View file

@ -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,

View file

@ -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);
}
}
}

View file

@ -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", ||

View file

@ -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 {

View file

@ -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
}

View file

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<uint, VarInfo>
}
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"); }

View file

@ -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() { }

View file

@ -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() {

View file

@ -21,8 +21,6 @@ fn with<R>(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() {

View file

@ -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
}
}