impl_stable_hash_for!(enum mir::ConstraintCategory {
Return,
+ Yield,
UseAsConst,
UseAsStatic,
TypeAnnotation,
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub enum ConstraintCategory {
Return,
+ Yield,
UseAsConst,
UseAsStatic,
TypeAnnotation,
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
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 ",
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,
}
});
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, _)
);
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) {
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 =
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));
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
value_ty,
ty,
term_location.to_locations(),
- ConstraintCategory::Return,
+ ConstraintCategory::Yield,
) {
span_mirbug!(
self,
--- /dev/null
+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`.
--- /dev/null
+// 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();
+}
--- /dev/null
+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`.