about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2016-12-22 19:46:08 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-01-04 05:48:18 +0200
commitbb04da4822ea57b8651b494e24a992b2072c4429 (patch)
tree38c3101f6c91ddbcfff8fb4f5b311cf897c44e03
parent468227129d08b52c4cf90313b29fdad1b80e596b (diff)
downloadrust-bb04da4822ea57b8651b494e24a992b2072c4429.tar.gz
rust-bb04da4822ea57b8651b494e24a992b2072c4429.zip
Don't leak the compiler's internal representation of scopes in error messages.
-rw-r--r--src/librustc/infer/error_reporting.rs56
-rw-r--r--src/test/compile-fail/issue-27942.rs31
-rw-r--r--src/test/compile-fail/issue-37884.rs27
3 files changed, 99 insertions, 15 deletions
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 9ff7dcc7d58..56f211c66b8 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -113,6 +113,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
         }
 
+        fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str {
+            match item.node {
+                hir::MethodTraitItem(..) => "method body",
+                hir::ConstTraitItem(..) |
+                hir::TypeTraitItem(..) => "associated item"
+            }
+        }
+
+        fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
+            match item.node {
+                hir::ImplItemKind::Method(..) => "method body",
+                hir::ImplItemKind::Const(..) |
+                hir::ImplItemKind::Type(_) => "associated item"
+            }
+        }
+
         fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                         heading: &str, span: Span)
                                         -> (String, Option<Span>) {
@@ -148,6 +164,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     },
                     Some(ast_map::NodeStmt(_)) => "statement",
                     Some(ast_map::NodeItem(it)) => item_scope_tag(&it),
+                    Some(ast_map::NodeTraitItem(it)) => trait_item_scope_tag(&it),
+                    Some(ast_map::NodeImplItem(it)) => impl_item_scope_tag(&it),
                     Some(_) | None => {
                         err.span_note(span, &unknown_scope());
                         return;
@@ -186,23 +204,31 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     }
                 };
 
-                match self.map.find(fr.scope.node_id(&self.region_maps)) {
-                    Some(ast_map::NodeBlock(ref blk)) => {
-                        let (msg, opt_span) = explain_span(self, "block", blk.span);
-                        (format!("{} {}", prefix, msg), opt_span)
-                    }
-                    Some(ast_map::NodeItem(it)) => {
-                        let tag = item_scope_tag(&it);
-                        let (msg, opt_span) = explain_span(self, tag, it.span);
-                        (format!("{} {}", prefix, msg), opt_span)
+                let node = fr.scope.node_id(&self.region_maps);
+                let unknown;
+                let tag = match self.map.find(node) {
+                    Some(ast_map::NodeBlock(_)) |
+                    Some(ast_map::NodeExpr(_)) => "body",
+                    Some(ast_map::NodeItem(it)) => item_scope_tag(&it),
+                    Some(ast_map::NodeTraitItem(it)) => trait_item_scope_tag(&it),
+                    Some(ast_map::NodeImplItem(it)) => impl_item_scope_tag(&it),
+
+                    // this really should not happen, but it does:
+                    // FIXME(#27942)
+                    Some(_) => {
+                        unknown = format!("unexpected node ({}) for scope {:?}.  \
+                                           Please report a bug.",
+                                          self.map.node_to_string(node), fr.scope);
+                        &unknown
                     }
-                    Some(_) | None => {
-                        // this really should not happen, but it does:
-                        // FIXME(#27942)
-                        (format!("{} unknown free region bounded by scope {:?}",
-                                 prefix, fr.scope), None)
+                    None => {
+                        unknown = format!("unknown node for scope {:?}.  \
+                                           Please report a bug.", fr.scope);
+                        &unknown
                     }
-                }
+                };
+                let (msg, opt_span) = explain_span(self, tag, self.map.span(node));
+                (format!("{} {}", prefix, msg), opt_span)
             }
 
             ty::ReStatic => ("the static lifetime".to_owned(), None),
diff --git a/src/test/compile-fail/issue-27942.rs b/src/test/compile-fail/issue-27942.rs
new file mode 100644
index 00000000000..b8552794eb5
--- /dev/null
+++ b/src/test/compile-fail/issue-27942.rs
@@ -0,0 +1,31 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Resources<'a> {}
+
+pub trait Buffer<'a, R: Resources<'a>> {
+    fn select(&self) -> BufferViewHandle<R>;
+    //~^ ERROR mismatched types
+    //~| lifetime mismatch
+    //~| NOTE expected type `Resources<'_>`
+    //~| NOTE    found type `Resources<'a>`
+    //~| NOTE the lifetime 'a as defined on the method body at 14:4...
+    //~| NOTE ...does not necessarily outlive the anonymous lifetime #1 defined on the method body
+    //~| ERROR mismatched types
+    //~| lifetime mismatch
+    //~| NOTE expected type `Resources<'_>`
+    //~| NOTE    found type `Resources<'a>`
+    //~| NOTE the anonymous lifetime #1 defined on the method body at 14:4...
+    //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the method body
+}
+
+pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-37884.rs b/src/test/compile-fail/issue-37884.rs
new file mode 100644
index 00000000000..a73b1dbe34c
--- /dev/null
+++ b/src/test/compile-fail/issue-37884.rs
@@ -0,0 +1,27 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct RepeatMut<'a, T>(T, &'a ());
+
+impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+    type Item = &'a mut T;
+    fn next(&'a mut self) -> Option<Self::Item>
+    //~^ ERROR method not compatible with trait
+    //~| lifetime mismatch
+    //~| NOTE expected type `fn(&mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
+    //~| NOTE    found type `fn(&'a mut RepeatMut<'a, T>) -> std::option::Option<&mut T>`
+    {
+    //~^ NOTE the anonymous lifetime #1 defined on the body
+    //~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the body
+        Some(&mut self.0)
+    }
+}
+
+fn main() {}