about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-12-20 04:54:35 -0500
committerNiko Matsakis <niko@alum.mit.edu>2017-12-20 14:38:13 -0500
commit80c510e353b34f006c284f9557e2b59d2f356029 (patch)
tree51d9af72a61e7b4e22599caf63786b6f18d4648e
parentcfa4ffa374f264cad971b8177e8d3a9cdd8152b3 (diff)
when using feature(nll), don't warn about AST-based region errors
Also, keep reporting AST-based region errors that are not occuring in
a fn body.
-rw-r--r--src/librustc/infer/error_reporting/mod.rs13
-rw-r--r--src/librustc/infer/mod.rs45
-rw-r--r--src/librustc_typeck/check/regionck.rs10
-rw-r--r--src/test/compile-fail/regions-struct-not-wf.rs12
-rw-r--r--src/test/ui/nll/capture-ref-in-struct.rs2
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs41
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr10
7 files changed, 120 insertions, 13 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 38bbddfd825..cae7bf5c25c 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -258,10 +258,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn report_region_errors(&self,
                                 region_scope_tree: &region::ScopeTree,
-                                errors: &Vec<RegionResolutionError<'tcx>>) {
+                                errors: &Vec<RegionResolutionError<'tcx>>,
+                                will_later_be_reported_by_nll: bool) {
         debug!("report_region_errors(): {} errors to start", errors.len());
 
-        if self.tcx.sess.nll() {
+        if will_later_be_reported_by_nll && self.tcx.sess.nll() {
+            // With `#![feature(nll)]`, we want to present a nice user
+            // experience, so don't even mention the errors from the
+            // AST checker.
+            if self.tcx.sess.features.borrow().nll {
+                return;
+            }
+
+            // But with -Znll, it's nice to have some note for later.
             for error in errors {
                 match *error {
                     RegionResolutionError::ConcreteFailure(ref origin, ..) |
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 32da08bf476..07c5b319970 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1159,10 +1159,45 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// result. After this, no more unification operations should be
     /// done -- or the compiler will panic -- but it is legal to use
     /// `resolve_type_vars_if_possible` as well as `fully_resolve`.
-    pub fn resolve_regions_and_report_errors(&self,
-                                             region_context: DefId,
-                                             region_map: &region::ScopeTree,
-                                             outlives_env: &OutlivesEnvironment<'tcx>) {
+    pub fn resolve_regions_and_report_errors(
+        &self,
+        region_context: DefId,
+        region_map: &region::ScopeTree,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+    ) {
+        self.resolve_regions_and_report_errors_inner(
+            region_context,
+            region_map,
+            outlives_env,
+            false,
+        )
+    }
+
+    /// Like `resolve_regions_and_report_errors`, but skips error
+    /// reporting if NLL is enabled.  This is used for fn bodies where
+    /// the same error may later be reported by the NLL-based
+    /// inference.
+    pub fn resolve_regions_and_report_errors_unless_nll(
+        &self,
+        region_context: DefId,
+        region_map: &region::ScopeTree,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+    ) {
+        self.resolve_regions_and_report_errors_inner(
+            region_context,
+            region_map,
+            outlives_env,
+            true,
+        )
+    }
+
+    fn resolve_regions_and_report_errors_inner(
+        &self,
+        region_context: DefId,
+        region_map: &region::ScopeTree,
+        outlives_env: &OutlivesEnvironment<'tcx>,
+        will_later_be_reported_by_nll: bool,
+    ) {
         assert!(self.is_tainted_by_errors() || self.region_obligations.borrow().is_empty(),
                 "region_obligations not empty: {:#?}",
                 self.region_obligations.borrow());
@@ -1187,7 +1222,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             // this infcx was in use.  This is totally hokey but
             // otherwise we have a hard time separating legit region
             // errors from silly ones.
-            self.report_region_errors(region_map, &errors); // see error_reporting module
+            self.report_region_errors(region_map, &errors, will_later_be_reported_by_nll);
         }
     }
 
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 97352783db8..64063ec5bed 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -124,7 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             rcx.visit_body(body);
             rcx.visit_region_obligations(id);
         }
-        rcx.resolve_regions_and_report_errors();
+        rcx.resolve_regions_and_report_errors_unless_nll();
 
         assert!(self.tables.borrow().free_region_map.is_empty());
         self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map();
@@ -173,7 +173,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             rcx.visit_fn_body(fn_id, body, self.tcx.hir.span(fn_id));
         }
 
-        rcx.resolve_regions_and_report_errors();
+        rcx.resolve_regions_and_report_errors_unless_nll();
 
         // In this mode, we also copy the free-region-map into the
         // tables of the enclosing fcx. In the other regionck modes
@@ -371,6 +371,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                                                    &self.outlives_environment);
     }
 
+    fn resolve_regions_and_report_errors_unless_nll(&self) {
+        self.fcx.resolve_regions_and_report_errors_unless_nll(self.subject_def_id,
+                                                              &self.region_scope_tree,
+                                                              &self.outlives_environment);
+    }
+
     fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
         debug!("regionck::visit_pat(pat={:?})", pat);
         pat.each_binding(|_, id, span, _| {
diff --git a/src/test/compile-fail/regions-struct-not-wf.rs b/src/test/compile-fail/regions-struct-not-wf.rs
index a7f18289703..9106f1f0ba6 100644
--- a/src/test/compile-fail/regions-struct-not-wf.rs
+++ b/src/test/compile-fail/regions-struct-not-wf.rs
@@ -10,11 +10,15 @@
 
 // Various examples of structs whose fields are not well-formed.
 
+// revisions:lexical nll
+
 #![allow(dead_code)]
+#![cfg_attr(nll, feature(nll))]
 
 struct Ref<'a, T> {
     field: &'a T
-        //~^ ERROR the parameter type `T` may not live long enough
+        //[lexical]~^ ERROR the parameter type `T` may not live long enough
+        //[nll]~^^ ERROR the parameter type `T` may not live long enough
 }
 
 struct RefOk<'a, T:'a> {
@@ -23,12 +27,14 @@ struct RefOk<'a, T:'a> {
 
 struct RefIndirect<'a, T> {
     field: RefOk<'a, T>
-        //~^ ERROR the parameter type `T` may not live long enough
+        //[lexical]~^ ERROR the parameter type `T` may not live long enough
+        //[nll]~^^ ERROR the parameter type `T` may not live long enough
 }
 
 struct DoubleRef<'a, 'b, T> {
     field: &'a &'b T
-        //~^ ERROR reference has a longer lifetime than the data it references
+        //[lexical]~^ ERROR reference has a longer lifetime than the data it references
+        //[nll]~^^ ERROR reference has a longer lifetime than the data it references
 }
 
 fn main() { }
diff --git a/src/test/ui/nll/capture-ref-in-struct.rs b/src/test/ui/nll/capture-ref-in-struct.rs
index 2d208c88552..74b086ab18a 100644
--- a/src/test/ui/nll/capture-ref-in-struct.rs
+++ b/src/test/ui/nll/capture-ref-in-struct.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-Zborrowck=mir -Znll-dump-cause
+// compile-flags:-Znll-dump-cause
 
 // Test that a structure which tries to store a pointer to `y` into
 // `p` (indirectly) fails to compile.
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
new file mode 100644
index 00000000000..babe608354f
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs
@@ -0,0 +1,41 @@
+// 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.
+
+// Test that we assume that universal types like `T` outlive the
+// function body. Same as ty-param-fn-body, but uses `feature(nll)`,
+// which affects error reporting.
+
+#![feature(nll)]
+
+#![allow(warnings)]
+#![feature(dyn_trait)]
+
+use std::cell::Cell;
+
+// No errors here, because `'a` is local to the body.
+fn region_within_body<T>(t: T) {
+    let some_int = 22;
+    let cell = Cell::new(&some_int);
+    outlives(cell, t)
+}
+
+// Error here, because T: 'a is not satisfied.
+fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) {
+    outlives(cell, t)
+    //~^ ERROR the parameter type `T` may not live long enough
+}
+
+fn outlives<'a, T>(x: Cell<&'a usize>, y: T)
+where
+    T: 'a,
+{
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
new file mode 100644
index 00000000000..fa9105df070
--- /dev/null
+++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr
@@ -0,0 +1,10 @@
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/ty-param-fn-body-nll-feature.rs:31:5
+   |
+31 |     outlives(cell, t)
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'a`...
+
+error: aborting due to previous error
+