Skip to content

Commit a40fded

Browse files
committedDec 7, 2018
Auto merge of rust-lang#56460 - davidtwco:issue-55850, r=pnkfelix
Fix ICE with generators and NLL Fix rust-lang#55850. This PR stops an ICE in rust-lang#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

File tree

9 files changed

+104
-22
lines changed

9 files changed

+104
-22
lines changed
 

‎src/librustc/ich/impls_mir.rs

+1
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ impl_stable_hash_for!(struct mir::ClosureOutlivesRequirement<'tcx> {
471471

472472
impl_stable_hash_for!(enum mir::ConstraintCategory {
473473
Return,
474+
Yield,
474475
UseAsConst,
475476
UseAsStatic,
476477
TypeAnnotation,

‎src/librustc/mir/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2905,6 +2905,7 @@ pub struct ClosureOutlivesRequirement<'tcx> {
29052905
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
29062906
pub enum ConstraintCategory {
29072907
Return,
2908+
Yield,
29082909
UseAsConst,
29092910
UseAsStatic,
29102911
TypeAnnotation,

‎src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
277277
borrow_region_vid,
278278
region,
279279
);
280-
let opt_place_desc = self.describe_place(&borrow.borrowed_place);
281-
BorrowExplanation::MustBeValidFor {
282-
category,
283-
from_closure,
284-
span,
285-
region_name,
286-
opt_place_desc,
280+
if let Some(region_name) = region_name {
281+
let opt_place_desc = self.describe_place(&borrow.borrowed_place);
282+
BorrowExplanation::MustBeValidFor {
283+
category,
284+
from_closure,
285+
span,
286+
region_name,
287+
opt_place_desc,
288+
}
289+
} else {
290+
BorrowExplanation::Unexplained
287291
}
288292
} else {
289293
BorrowExplanation::Unexplained

‎src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl ConstraintDescription for ConstraintCategory {
3838
match self {
3939
ConstraintCategory::Assignment => "assignment ",
4040
ConstraintCategory::Return => "returning this value ",
41+
ConstraintCategory::Yield => "yielding this value ",
4142
ConstraintCategory::UseAsConst => "using this value as a constant ",
4243
ConstraintCategory::UseAsStatic => "using this value as a static ",
4344
ConstraintCategory::Cast => "cast ",
@@ -133,11 +134,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
133134
let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
134135

135136
match categorized_path[i].0 {
136-
ConstraintCategory::OpaqueType
137-
| ConstraintCategory::Boring
138-
| ConstraintCategory::BoringNoLocation
139-
| ConstraintCategory::Internal => false,
140-
ConstraintCategory::TypeAnnotation | ConstraintCategory::Return => true,
137+
ConstraintCategory::OpaqueType | ConstraintCategory::Boring |
138+
ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal => false,
139+
ConstraintCategory::TypeAnnotation | ConstraintCategory::Return |
140+
ConstraintCategory::Yield => true,
141141
_ => constraint_sup_scc != target_scc,
142142
}
143143
});
@@ -376,9 +376,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
376376

377377
diag.span_label(span, message);
378378

379-
match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1)
380-
.source
381-
{
379+
match self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, &mut 1).unwrap().source {
382380
RegionNameSource::NamedEarlyBoundRegion(fr_span)
383381
| RegionNameSource::NamedFreeRegion(fr_span)
384382
| RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -521,10 +519,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
521519
);
522520

523521
let counter = &mut 1;
524-
let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter);
522+
let fr_name = self.give_region_a_name(infcx, mir, mir_def_id, fr, counter).unwrap();
525523
fr_name.highlight_region_name(&mut diag);
526524
let outlived_fr_name =
527-
self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter);
525+
self.give_region_a_name(infcx, mir, mir_def_id, outlived_fr, counter).unwrap();
528526
outlived_fr_name.highlight_region_name(&mut diag);
529527

530528
let mir_def_name = if infcx.tcx.is_closure(mir_def_id) {
@@ -661,7 +659,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
661659
infcx: &InferCtxt<'_, '_, 'tcx>,
662660
borrow_region: RegionVid,
663661
outlived_region: RegionVid,
664-
) -> (ConstraintCategory, bool, Span, RegionName) {
662+
) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
665663
let (category, from_closure, span) =
666664
self.best_blame_constraint(mir, borrow_region, |r| r == outlived_region);
667665
let outlived_fr_name =

‎src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
157157
mir_def_id: DefId,
158158
fr: RegionVid,
159159
counter: &mut usize,
160-
) -> RegionName {
160+
) -> Option<RegionName> {
161161
debug!("give_region_a_name(fr={:?}, counter={})", fr, counter);
162162

163163
assert!(self.universal_regions.is_universal_region(fr));
@@ -177,8 +177,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
177177
self.give_name_if_anonymous_region_appears_in_output(
178178
infcx, mir, mir_def_id, fr, counter,
179179
)
180-
})
181-
.unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr));
180+
});
182181

183182
debug!("give_region_a_name: gave name {:?}", value);
184183
value

‎src/librustc_mir/borrow_check/nll/type_check/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1467,7 +1467,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
14671467
value_ty,
14681468
ty,
14691469
term_location.to_locations(),
1470-
ConstraintCategory::Return,
1470+
ConstraintCategory::Yield,
14711471
) {
14721472
span_mirbug!(
14731473
self,
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0597]: `s` does not live long enough
2+
--> $DIR/issue-55850.rs:38:16
3+
|
4+
LL | yield &s[..] //~ ERROR `s` does not live long enough [E0597]
5+
| ^ borrowed value does not live long enough
6+
LL | })
7+
| - `s` dropped here while still borrowed
8+
9+
error[E0626]: borrow may still be in use when generator yields
10+
--> $DIR/issue-55850.rs:38:16
11+
|
12+
LL | yield &s[..] //~ ERROR `s` does not live long enough [E0597]
13+
| -------^---- possible yield occurs here
14+
15+
error: aborting due to 2 previous errors
16+
17+
Some errors occurred: E0597, E0626.
18+
For more information about an error, try `rustc --explain E0597`.

‎src/test/ui/nll/issue-55850.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(unused_mut)]
12+
#![feature(generators, generator_trait)]
13+
14+
use std::ops::Generator;
15+
use std::ops::GeneratorState::Yielded;
16+
17+
pub struct GenIter<G>(G);
18+
19+
impl <G> Iterator for GenIter<G>
20+
where
21+
G: Generator,
22+
{
23+
type Item = G::Yield;
24+
25+
fn next(&mut self) -> Option<Self::Item> {
26+
unsafe {
27+
match self.0.resume() {
28+
Yielded(y) => Some(y),
29+
_ => None
30+
}
31+
}
32+
}
33+
}
34+
35+
fn bug<'a>() -> impl Iterator<Item = &'a str> {
36+
GenIter(move || {
37+
let mut s = String::new();
38+
yield &s[..] //~ ERROR `s` does not live long enough [E0597]
39+
})
40+
}
41+
42+
fn main() {
43+
bug();
44+
}

‎src/test/ui/nll/issue-55850.stderr

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0597]: `s` does not live long enough
2+
--> $DIR/issue-55850.rs:38:16
3+
|
4+
LL | yield &s[..] //~ ERROR `s` does not live long enough [E0597]
5+
| ^ borrowed value does not live long enough
6+
LL | })
7+
| - borrowed value only lives until here
8+
|
9+
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 35:8...
10+
--> $DIR/issue-55850.rs:35:8
11+
|
12+
LL | fn bug<'a>() -> impl Iterator<Item = &'a str> {
13+
| ^^
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0597`.

0 commit comments

Comments
 (0)
Please sign in to comment.