about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-07-31 21:08:24 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-07-31 22:00:19 -0700
commita334deb5d58c455e20fececea649c4997c6867ca (patch)
tree7b176ebcfd37e07d86e91d576293be2ccb62a716 /src/rustc
parentc5437c0bbf65204390762acfc544fb29b3150619 (diff)
downloadrust-a334deb5d58c455e20fececea649c4997c6867ca.tar.gz
rust-a334deb5d58c455e20fececea649c4997c6867ca.zip
change how we print and explain region types
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/ty.rs10
-rw-r--r--src/rustc/util/ppaux.rs70
2 files changed, 71 insertions, 9 deletions
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index 71e0fedef61..aba8d250b20 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -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",
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index bf97df5fd5f..f6f0cf8b363 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -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: