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:
diff --git a/src/test/compile-fail/regions-nested-fns.rs b/src/test/compile-fail/regions-nested-fns.rs
index ae3102b8ec2..bd6e3644556 100644
--- a/src/test/compile-fail/regions-nested-fns.rs
+++ b/src/test/compile-fail/regions-nested-fns.rs
@@ -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;
     });
 }
diff --git a/src/test/compile-fail/regions-scoping.rs b/src/test/compile-fail/regions-scoping.rs
index 8526c6722f4..c17319ca7bb 100644
--- a/src/test/compile-fail/regions-scoping.rs
+++ b/src/test/compile-fail/regions-scoping.rs
@@ -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 `&
     }
 }