change how we print and explain region types
This commit is contained in:
parent
c5437c0bbf
commit
a334deb5d5
src
@ -9,8 +9,7 @@ import syntax::ast_util::{is_local, local_def, split_class_items,
|
||||
new_def_hash};
|
||||
import syntax::codemap::span;
|
||||
import metadata::csearch;
|
||||
import util::ppaux::region_to_str;
|
||||
import util::ppaux::vstore_to_str;
|
||||
import util::ppaux::{region_to_str, explain_region, vstore_to_str};
|
||||
import middle::lint;
|
||||
import middle::lint::{get_lint_level, allow};
|
||||
import syntax::ast::*;
|
||||
@ -2590,10 +2589,9 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> ~str {
|
||||
~" but found " + mode_to_str(a_mode);
|
||||
}
|
||||
terr_regions_differ(subregion, superregion) {
|
||||
ret fmt!{"references with lifetime %s do not necessarily \
|
||||
outlive references with lifetime %s",
|
||||
region_to_str(cx, subregion),
|
||||
region_to_str(cx, superregion)};
|
||||
ret fmt!{"%s does not necessarily outlive %s",
|
||||
explain_region(cx, subregion),
|
||||
explain_region(cx, superregion)};
|
||||
}
|
||||
terr_vstores_differ(k, e_vs, a_vs) {
|
||||
ret fmt!{"%s storage differs: expected %s but found %s",
|
||||
|
@ -3,7 +3,8 @@ import middle::ty;
|
||||
import middle::ty::{arg, canon_mode};
|
||||
import middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
|
||||
import middle::ty::{ck_block, ck_box, ck_uniq, ctxt, field, method};
|
||||
import middle::ty::{mt, re_bound, re_free, re_scope, re_var, region, t};
|
||||
import middle::ty::{mt, t};
|
||||
import middle::ty::{re_bound, re_free, re_scope, re_var, re_static, region};
|
||||
import middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_enum};
|
||||
import middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int};
|
||||
import middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
|
||||
@ -12,6 +13,7 @@ import middle::ty::{ty_type, ty_uniq, ty_uint, ty_var, ty_var_integral};
|
||||
import middle::ty::{ty_unboxed_vec, vid};
|
||||
import metadata::encoder;
|
||||
import syntax::codemap;
|
||||
import syntax::codemap::span;
|
||||
import syntax::print::pprust;
|
||||
import syntax::print::pprust::{path_to_str, proto_to_str,
|
||||
mode_to_str, purity_to_str};
|
||||
@ -19,6 +21,60 @@ import syntax::{ast, ast_util};
|
||||
import syntax::ast_map;
|
||||
import driver::session::session;
|
||||
|
||||
/// Returns a string like "reference valid for the block at 27:31 in foo.rs"
|
||||
/// that attempts to explain a lifetime in a way it might plausibly be
|
||||
/// understood.
|
||||
fn explain_region(cx: ctxt, region: ty::region) -> ~str {
|
||||
ret alt region {
|
||||
re_scope(node_id) => {
|
||||
let scope_str = alt cx.items.find(node_id) {
|
||||
some(ast_map::node_block(blk)) => {
|
||||
explain_span(cx, ~"block", blk.span)
|
||||
}
|
||||
some(ast_map::node_expr(expr)) => {
|
||||
alt expr.node {
|
||||
ast::expr_call(*) => { explain_span(cx, ~"call", expr.span) }
|
||||
ast::expr_alt(*) => { explain_span(cx, ~"alt", expr.span) }
|
||||
_ => { explain_span(cx, ~"expression", expr.span) }
|
||||
}
|
||||
}
|
||||
some(_) | none => {
|
||||
// this really should not happen
|
||||
fmt!{"unknown scope: %d. Please report a bug.", node_id}
|
||||
}
|
||||
};
|
||||
fmt!{"reference valid for the %s", scope_str}
|
||||
}
|
||||
|
||||
re_free(id, br) => {
|
||||
alt cx.items.find(id) {
|
||||
some(ast_map::node_block(blk)) => {
|
||||
fmt!{"reference with lifetime %s as defined on %s",
|
||||
bound_region_to_str(cx, br),
|
||||
explain_span(cx, ~"the block", blk.span)}
|
||||
}
|
||||
some(_) | none => {
|
||||
// this really should not happen
|
||||
fmt!{"reference with lifetime %s as defined on node %d",
|
||||
bound_region_to_str(cx, br), id}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
re_static => { ~"reference to static data" }
|
||||
|
||||
// I believe these cases should not occur.
|
||||
re_var(_) | re_bound(_) => {
|
||||
fmt!{"reference with lifetime %?", region}
|
||||
}
|
||||
};
|
||||
|
||||
fn explain_span(cx: ctxt, heading: ~str, span: span) -> ~str {
|
||||
let lo = codemap::lookup_char_pos_adj(cx.sess.codemap, span.lo);
|
||||
fmt!{"%s at %u:%u", heading, lo.line, lo.col}
|
||||
}
|
||||
}
|
||||
|
||||
fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str {
|
||||
alt br {
|
||||
br_anon => { ~"&" }
|
||||
@ -79,8 +135,16 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str {
|
||||
|
||||
fn region_to_str(cx: ctxt, region: region) -> ~str {
|
||||
alt region {
|
||||
re_scope(node_id) { fmt!{"&%s", re_scope_id_to_str(cx, node_id)} }
|
||||
re_bound(br) { bound_region_to_str(cx, br) }
|
||||
re_scope(node_id) {
|
||||
if cx.sess.ppregions() {
|
||||
fmt!{"&%s", re_scope_id_to_str(cx, node_id)}
|
||||
} else {
|
||||
~"&"
|
||||
}
|
||||
}
|
||||
re_bound(br) {
|
||||
bound_region_to_str(cx, br)
|
||||
}
|
||||
re_free(id, br) {
|
||||
if cx.sess.ppregions() {
|
||||
// For debugging, this version is sometimes helpful:
|
||||
|
@ -7,12 +7,12 @@ fn nested(x: &x/int) {
|
||||
ignore(fn&(z: &z/int) {
|
||||
ay = x;
|
||||
ay = &y;
|
||||
ay = z; //~ ERROR references with lifetime
|
||||
ay = z; //~ ERROR mismatched types
|
||||
});
|
||||
|
||||
ignore(fn&(z: &z/int) -> &z/int {
|
||||
if false { ret x; } //~ ERROR references with lifetime
|
||||
if false { ret ay; } //~ ERROR references with lifetime
|
||||
if false { ret x; } //~ ERROR mismatched types
|
||||
if false { ret ay; } //~ ERROR mismatched types
|
||||
ret z;
|
||||
});
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ fn nested(x: &x/int) { // (1)
|
||||
// let f: &x/int = foo(&z, &z, |_x, _y, z| z ); // ERROR mismatched types: expected `&x/int` but found
|
||||
|
||||
foo(x, &z, |x, _y, _z| x ); //~ ERROR mismatched types: expected `&z/int` but found `&x/int`
|
||||
foo(x, &z, |_x, y, _z| y ); //~ ERROR mismatched types: expected `&z/int` but found `&<expression at
|
||||
foo(x, &z, |_x, y, _z| y ); //~ ERROR mismatched types: expected `&z/int` but found `&
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user