]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #56460 - davidtwco:issue-55850, r=pnkfelix
authorbors <bors@rust-lang.org>
Fri, 7 Dec 2018 17:37:44 +0000 (17:37 +0000)
committerbors <bors@rust-lang.org>
Fri, 7 Dec 2018 17:37:44 +0000 (17:37 +0000)
Fix ICE with generators and NLL

Fix #55850.

This PR stops an ICE in #55850 by not panicking when a region cannot be named. However, this PR does not (yet) fix the underlying issue that the correct name for the test case provided for the issue (in this instance, `'a`) was not found.

This PR also lays a little bit of groundwork by categorizing yields separately from returns so that region naming can be specialized for this case.

r? @pnkfelix

src/librustc/ich/impls_mir.rs
src/librustc/mir/mod.rs
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/test/ui/nll/issue-55850.nll.stderr [new file with mode: 0644]
src/test/ui/nll/issue-55850.rs [new file with mode: 0644]
src/test/ui/nll/issue-55850.stderr [new file with mode: 0644]

index c72887124aa0b4ab7b11619d032fa9b5507841a9..a46e12be1aeace57d5b28a503e8f90111c98e075 100644 (file)
@@ -471,6 +471,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(enum mir::ConstraintCategory {
     Return,
+    Yield,
     UseAsConst,
     UseAsStatic,
     TypeAnnotation,
index 7259bbfb780bfe47b0368db6dabc235147565e37..6ff60b39bd341298097050ca2a0cbe50d77808a9 100644 (file)
@@ -2905,6 +2905,7 @@ pub struct ClosureOutlivesRequirement<'tcx> {
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub enum ConstraintCategory {
     Return,
+    Yield,
     UseAsConst,
     UseAsStatic,
     TypeAnnotation,
index 477b78926084e86d0efa701f2b66ba47519bbca3..7fb3f02e0e3f3f07c3367bd61ab647d6a908d9ad 100644 (file)
@@ -277,13 +277,17 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
                         borrow_region_vid,
                         region,
                     );
-                let opt_place_desc = self.describe_place(&borrow.borrowed_place);
-                BorrowExplanation::MustBeValidFor {
-                    category,
-                    from_closure,
-                    span,
-                    region_name,
-                    opt_place_desc,
+                if let Some(region_name) = region_name {
+                    let opt_place_desc = self.describe_place(&borrow.borrowed_place);
+                    BorrowExplanation::MustBeValidFor {
+                        category,
+                        from_closure,
+                        span,
+                        region_name,
+                        opt_place_desc,
+                    }
+                } else {
+                    BorrowExplanation::Unexplained
                 }
             } else {
                 BorrowExplanation::Unexplained
index 3358e5851f939d10c7da2d079c8ee0fc92839f47..32aaa0590d2f9efbe6d3df17e8d52086c9aed831 100644 (file)
@@ -38,6 +38,7 @@ fn description(&self) -> &'static str {
         match self {
             ConstraintCategory::Assignment => "assignment ",
             ConstraintCategory::Return => "returning this value ",
+            ConstraintCategory::Yield => "yielding this value ",
             ConstraintCategory::UseAsConst => "using this value as a constant ",
             ConstraintCategory::UseAsStatic => "using this value as a static ",
             ConstraintCategory::Cast => "cast ",
@@ -133,11 +134,10 @@ fn best_blame_constraint(
             let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
 
             match categorized_path[i].0 {
-                ConstraintCategory::OpaqueType
-                | ConstraintCategory::Boring
-                | ConstraintCategory::BoringNoLocation
-                | ConstraintCategory::Internal => false,
-                ConstraintCategory::TypeAnnotation | ConstraintCategory::Return => true,
+                ConstraintCategory::OpaqueType | ConstraintCategory::Boring |
+                ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false,
+                ConstraintCategory::TypeAnnotation | ConstraintCategory::Return |
+                ConstraintCategory::Yield => true,
                 _ => constraint_sup_scc != target_scc,
             }
         });
@@ -376,9 +376,7 @@ fn report_fnmut_error(
 
         diag.span_label(span, message);
 
-        match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1)
-            .source
-        {
+        match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).unwrap().source {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
             | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -521,10 +519,10 @@ fn report_general_error(
         );
 
         let counter = &mut 1;
-        let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter);
+        let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter).unwrap();
         fr_name.highlight_region_name(&mut diag);
         let outlived_fr_name =
-            self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter);
+            self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter).unwrap();
         outlived_fr_name.highlight_region_name(&mut diag);
 
         let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
@@ -661,7 +659,7 @@ fn add_static_impl_trait_suggestion(
         infcx: &InferCtxt<'_, '_, 'tcx>,
         borrow_region: RegionVid,
         outlived_region: RegionVid,
-    ) -> (ConstraintCategory, bool, Span, RegionName) {
+    ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
         let (category, from_closure, span) =
             self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
         let outlived_fr_name =
index a32fb0503a814e6ba74f7e65f3134091de8eded8..b01e257ae2effd5ac7f2b506d3e24a0f6fd8695a 100644 (file)
@@ -157,7 +157,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         mir_def_id: DefId,
         fr: RegionVid,
         counter: &mut usize,
-    ) -> RegionName {
+    ) -> Option<RegionName> {
         debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
 
         assert!(self.universal_regions.is_universal_region(fr));
@@ -177,8 +177,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 self.give_name_if_anonymous_region_appears_in_output(
                     infcx, mir, mir_def_id, fr, counter,
                 )
-            })
-            .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr));
+            });
 
         debug!("give_region_a_name: gave name {:?}", value);
         value
index 5f64dfd931c8989a6f2c31f0bf1cc2c6fa742124..33346a584e5a47e6f659e93b370ccfa3b3644840 100644 (file)
@@ -1467,7 +1467,7 @@ fn check_terminator(
                             value_ty,
                             ty,
                             term_location.to_locations(),
-                            ConstraintCategory::Return,
+                            ConstraintCategory::Yield,
                         ) {
                             span_mirbug!(
                                 self,
diff --git a/src/test/ui/nll/issue-55850.nll.stderr b/src/test/ui/nll/issue-55850.nll.stderr
new file mode 100644 (file)
index 0000000..08e5217
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/issue-55850.rs:38:16
+   |
+LL |         yield &s[..] //~ ERROR `s` does not live long enough [E0597]
+   |                ^ borrowed value does not live long enough
+LL |     })
+   |     - `s` dropped here while still borrowed
+
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/issue-55850.rs:38:16
+   |
+LL |         yield &s[..] //~ ERROR `s` does not live long enough [E0597]
+   |         -------^---- possible yield occurs here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0597, E0626.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-55850.rs b/src/test/ui/nll/issue-55850.rs
new file mode 100644 (file)
index 0000000..4140815
--- /dev/null
@@ -0,0 +1,44 @@
+// 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.
+
+#![allow(unused_mut)]
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+use std::ops::GeneratorState::Yielded;
+
+pub struct GenIter<G>(G);
+
+impl <G> Iterator for GenIter<G>
+where
+    G: Generator,
+{
+    type Item = G::Yield;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        unsafe {
+            match self.0.resume() {
+                Yielded(y) => Some(y),
+                _ => None
+            }
+        }
+    }
+}
+
+fn bug<'a>() -> impl Iterator<Item = &'a str> {
+    GenIter(move || {
+        let mut s = String::new();
+        yield &s[..] //~ ERROR `s` does not live long enough [E0597]
+    })
+}
+
+fn main() {
+    bug();
+}
diff --git a/src/test/ui/nll/issue-55850.stderr b/src/test/ui/nll/issue-55850.stderr
new file mode 100644 (file)
index 0000000..26b4c82
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0597]: `s` does not live long enough
+  --> $DIR/issue-55850.rs:38:16
+   |
+LL |         yield &s[..] //~ ERROR `s` does not live long enough [E0597]
+   |                ^ borrowed value does not live long enough
+LL |     })
+   |     - borrowed value only lives until here
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 35:8...
+  --> $DIR/issue-55850.rs:35:8
+   |
+LL | fn bug<'a>() -> impl Iterator<Item = &'a str> {
+   |        ^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.