improve borrowck error messages to explain regions better
This commit is contained in:
parent
99af0d5480
commit
52c517383e
@ -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)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/test/compile-fail/borrowck-confuse-region.rs
Normal file
14
src/test/compile-fail/borrowck-confuse-region.rs
Normal 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() {}
|
@ -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; }
|
||||||
|
Loading…
Reference in New Issue
Block a user