refinement to technique used to not run regionck
This commit is contained in:
parent
e235f6ca53
commit
2ea52a38e5
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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", ||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"); }
|
@ -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() { }
|
||||
|
@ -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() {
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user