@@ -3,7 +3,8 @@ import middle::ty;
33import middle:: ty:: { arg, canon_mode} ;
44import middle:: ty:: { bound_region, br_anon, br_named, br_self, br_cap_avoid} ;
55import middle:: ty:: { ck_block, ck_box, ck_uniq, ctxt, field, method} ;
6- import middle:: ty:: { mt, re_bound, re_free, re_scope, re_var, region, t} ;
6+ import middle:: ty:: { mt, t} ;
7+ import middle:: ty:: { re_bound, re_free, re_scope, re_var, re_static, region} ;
78import middle:: ty:: { ty_bool, ty_bot, ty_box, ty_class, ty_enum} ;
89import middle:: ty:: { ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int} ;
910import middle:: ty:: { ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param} ;
@@ -12,13 +13,68 @@ import middle::ty::{ty_type, ty_uniq, ty_uint, ty_var, ty_var_integral};
1213import middle:: ty:: { ty_unboxed_vec, vid} ;
1314import metadata:: encoder;
1415import syntax:: codemap;
16+ import syntax:: codemap:: span;
1517import syntax:: print:: pprust;
1618import syntax:: print:: pprust:: { path_to_str, proto_to_str,
1719 mode_to_str, purity_to_str} ;
1820import syntax:: { ast, ast_util} ;
1921import syntax:: ast_map;
2022import driver:: session:: session;
2123
24+ /// Returns a string like "reference valid for the block at 27:31 in foo.rs"
25+ /// that attempts to explain a lifetime in a way it might plausibly be
26+ /// understood.
27+ fn explain_region( cx : ctxt , region : ty:: region ) -> ~str {
28+ ret alt region {
29+ re_scope( node_id) => {
30+ let scope_str = alt cx. items . find ( node_id) {
31+ some ( ast_map:: node_block ( blk) ) => {
32+ explain_span ( cx, ~"block", blk. span )
33+ }
34+ some( ast_map:: node_expr ( expr) ) => {
35+ alt expr. node {
36+ ast:: expr_call( * ) => { explain_span ( cx, ~"call", expr. span ) }
37+ ast:: expr_alt( * ) => { explain_span ( cx, ~"alt", expr. span ) }
38+ _ => { explain_span ( cx, ~"expression", expr. span ) }
39+ }
40+ }
41+ some ( _) | none => {
42+ // this really should not happen
43+ fmt ! { "unknown scope: %d. Please report a bug." , node_id}
44+ }
45+ } ;
46+ fmt ! { "reference valid for the %s" , scope_str}
47+ }
48+
49+ re_free ( id, br) => {
50+ alt cx. items . find ( id) {
51+ some ( ast_map:: node_block ( blk) ) => {
52+ fmt ! { "reference with lifetime %s as defined on %s" ,
53+ bound_region_to_str( cx, br) ,
54+ explain_span( cx, ~"the block", blk.span)}
55+ }
56+ some(_) | none => {
57+ // this really should not happen
58+ fmt!{" reference with lifetime %s as defined on node %d",
59+ bound_region_to_str(cx, br), id}
60+ }
61+ }
62+ }
63+
64+ re_static => { ~" reference to static data" }
65+
66+ // I believe these cases should not occur.
67+ re_var(_) | re_bound(_) => {
68+ fmt!{" reference with lifetime %?", region}
69+ }
70+ };
71+
72+ fn explain_span(cx: ctxt, heading: ~str, span: span) -> ~str {
73+ let lo = codemap::lookup_char_pos_adj(cx.sess.codemap, span.lo);
74+ fmt!{" %s at %u: %u", heading, lo.line, lo.col}
75+ }
76+ }
77+
2278fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str {
2379 alt br {
2480 br_anon => { ~" & " }
@@ -79,8 +135,16 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str {
79135
80136fn region_to_str(cx: ctxt, region: region) -> ~str {
81137 alt region {
82- re_scope( node_id) { fmt ! { "&%s" , re_scope_id_to_str( cx, node_id) } }
83- re_bound ( br) { bound_region_to_str ( cx, br) }
138+ re_scope(node_id) {
139+ if cx.sess.ppregions() {
140+ fmt!{" & %s", re_scope_id_to_str(cx, node_id)}
141+ } else {
142+ ~" & "
143+ }
144+ }
145+ re_bound(br) {
146+ bound_region_to_str(cx, br)
147+ }
84148 re_free(id, br) {
85149 if cx.sess.ppregions() {
86150 // For debugging, this version is sometimes helpful:
0 commit comments