improve borrowck error messages to explain regions better

This commit is contained in:
Niko Matsakis 2012-08-07 19:48:24 -07:00
parent 99af0d5480
commit 52c517383e
5 changed files with 34 additions and 20 deletions

View file

@ -220,7 +220,7 @@ import syntax::visit;
import syntax::ast_util; import syntax::ast_util;
import syntax::ast_map; import syntax::ast_map;
import syntax::codemap::span; import syntax::codemap::span;
import util::ppaux::{ty_to_str, region_to_str}; import util::ppaux::{ty_to_str, region_to_str, explain_region};
import std::map::{int_hash, hashmap, set}; import std::map::{int_hash, hashmap, set};
import std::list; import std::list;
import std::list::{list, cons, nil}; import std::list::{list, cons, nil};
@ -626,16 +626,16 @@ impl to_str_methods for borrowck_ctxt {
~"rooting is not permitted" ~"rooting is not permitted"
} }
err_out_of_root_scope(super_scope, sub_scope) => { err_out_of_root_scope(super_scope, sub_scope) => {
fmt!{"managed value would have to be rooted for lifetime %s, \ fmt!{"managed value would have to be rooted for %s, \
but can only be rooted for lifetime %s", but can only be rooted for %s",
self.region_to_str(sub_scope), explain_region(self.tcx, sub_scope),
self.region_to_str(super_scope)} explain_region(self.tcx, super_scope)}
} }
err_out_of_scope(super_scope, sub_scope) => { err_out_of_scope(super_scope, sub_scope) => {
fmt!{"borrowed pointer has lifetime %s, \ fmt!{"borrowed pointer must be valid for %s, \
but the borrowed value only has lifetime %s", but the borrowed value is only valid for %s",
self.region_to_str(sub_scope), explain_region(self.tcx, sub_scope),
self.region_to_str(super_scope)} explain_region(self.tcx, super_scope)}
} }
} }
} }

View file

@ -27,7 +27,7 @@ import driver::session::session;
fn explain_region(cx: ctxt, region: ty::region) -> ~str { fn explain_region(cx: ctxt, region: ty::region) -> ~str {
return match region { return match region {
re_scope(node_id) => { re_scope(node_id) => {
let scope_str = match cx.items.find(node_id) { match cx.items.find(node_id) {
some(ast_map::node_block(blk)) => { some(ast_map::node_block(blk)) => {
explain_span(cx, ~"block", blk.span) explain_span(cx, ~"block", blk.span)
} }
@ -42,36 +42,36 @@ fn explain_region(cx: ctxt, region: ty::region) -> ~str {
// this really should not happen // this really should not happen
fmt!{"unknown scope: %d. Please report a bug.", node_id} fmt!{"unknown scope: %d. Please report a bug.", node_id}
} }
}; }
fmt!{"reference valid for the %s", scope_str}
} }
re_free(id, br) => { re_free(id, br) => {
match cx.items.find(id) { match cx.items.find(id) {
some(ast_map::node_block(blk)) => { some(ast_map::node_block(blk)) => {
fmt!{"reference with lifetime %s as defined on %s", fmt!{"the lifetime %s as defined on %s",
bound_region_to_str(cx, br), bound_region_to_str(cx, br),
explain_span(cx, ~"the block", blk.span)} explain_span(cx, ~"the block", blk.span)}
} }
some(_) | none => { some(_) | none => {
// this really should not happen // this really should not happen
fmt!{"reference with lifetime %s as defined on node %d", fmt!{"the lifetime %s as defined on node %d",
bound_region_to_str(cx, br), id} bound_region_to_str(cx, br), id}
} }
} }
} }
re_static => { ~"reference to static data" } re_static => { ~"the static lifetime" }
// I believe these cases should not occur. // I believe these cases should not occur (except when debugging,
// perhaps)
re_var(_) | re_bound(_) => { re_var(_) | re_bound(_) => {
fmt!{"reference with lifetime %?", region} fmt!{"lifetime %?", region}
} }
}; };
fn explain_span(cx: ctxt, heading: ~str, span: span) -> ~str { fn explain_span(cx: ctxt, heading: ~str, span: span) -> ~str {
let lo = codemap::lookup_char_pos_adj(cx.sess.codemap, span.lo); let lo = codemap::lookup_char_pos_adj(cx.sess.codemap, span.lo);
fmt!{"%s at %u:%u", heading, lo.line, lo.col} fmt!{"the %s at %u:%u", heading, lo.line, lo.col}
} }
} }

View file

@ -0,0 +1,14 @@
// Here we are checking that a reasonable error msg is provided.
//
// The current message is not ideal, but we used to say "borrowed
// pointer has lifetime &, but the borrowed value only has lifetime &"
// which is definitely no good.
fn get() -> &int {
let x = 3;
return &x;
//~^ ERROR illegal borrow: borrowed pointer must be valid for the lifetime & as defined on the the block at 8:17, but the borrowed value is only valid for the block at 8:17
}
fn main() {}

View file

@ -7,7 +7,7 @@ fn foo(cond: fn() -> bool, box: fn() -> @int) {
// Here we complain because the resulting region // Here we complain because the resulting region
// of this borrow is the fn body as a whole. // of this borrow is the fn body as a whole.
y = borrow(x); //~ ERROR managed value would have to be rooted for lifetime y = borrow(x); //~ ERROR illegal borrow: managed value would have to be rooted
assert *x == *y; assert *x == *y;
if cond() { break; } if cond() { break; }