mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-11 22:43:42 +00:00
Propagate bounds from generators
This commit is contained in:
parent
121320d523
commit
ef1a40d5fe
@ -1268,7 +1268,7 @@ pub trait ClosureRegionRequirementsExt<'gcx, 'tcx> {
|
|||||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
closure_def_id: DefId,
|
closure_def_id: DefId,
|
||||||
closure_substs: ty::ClosureSubsts<'tcx>,
|
closure_substs: &'tcx ty::subst::Substs<'tcx>,
|
||||||
) -> Vec<QueryRegionConstraint<'tcx>>;
|
) -> Vec<QueryRegionConstraint<'tcx>>;
|
||||||
|
|
||||||
fn subst_closure_mapping<T>(
|
fn subst_closure_mapping<T>(
|
||||||
@ -1299,23 +1299,19 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
|
|||||||
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
tcx: TyCtxt<'_, 'gcx, 'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
closure_def_id: DefId,
|
closure_def_id: DefId,
|
||||||
closure_substs: ty::ClosureSubsts<'tcx>,
|
closure_substs: &'tcx ty::subst::Substs<'tcx>,
|
||||||
) -> Vec<QueryRegionConstraint<'tcx>> {
|
) -> Vec<QueryRegionConstraint<'tcx>> {
|
||||||
debug!(
|
debug!(
|
||||||
"apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
|
"apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
|
||||||
location, closure_def_id, closure_substs
|
location, closure_def_id, closure_substs
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get Tu.
|
// Extract the values of the free regions in `closure_substs`
|
||||||
let user_closure_ty = tcx.mk_closure(closure_def_id, closure_substs);
|
|
||||||
debug!("apply_requirements: user_closure_ty={:?}", user_closure_ty);
|
|
||||||
|
|
||||||
// Extract the values of the free regions in `user_closure_ty`
|
|
||||||
// into a vector. These are the regions that we will be
|
// into a vector. These are the regions that we will be
|
||||||
// relating to one another.
|
// relating to one another.
|
||||||
let closure_mapping = &UniversalRegions::closure_mapping(
|
let closure_mapping = &UniversalRegions::closure_mapping(
|
||||||
tcx,
|
tcx,
|
||||||
user_closure_ty,
|
closure_substs,
|
||||||
self.num_external_vids,
|
self.num_external_vids,
|
||||||
tcx.closure_base_def_id(closure_def_id),
|
tcx.closure_base_def_id(closure_def_id),
|
||||||
);
|
);
|
||||||
|
@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
|
|||||||
use rustc::traits::query::{Fallible, NoSolution};
|
use rustc::traits::query::{Fallible, NoSolution};
|
||||||
use rustc::traits::{ObligationCause, PredicateObligations};
|
use rustc::traits::{ObligationCause, PredicateObligations};
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::ty::subst::{Subst, UnpackedKind};
|
use rustc::ty::subst::{Subst, Substs, UnpackedKind};
|
||||||
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
|
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{fmt, iter};
|
use std::{fmt, iter};
|
||||||
@ -2075,12 +2075,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
// desugaring. A closure gets desugared to a struct, and
|
// desugaring. A closure gets desugared to a struct, and
|
||||||
// these extra requirements are basically like where
|
// these extra requirements are basically like where
|
||||||
// clauses on the struct.
|
// clauses on the struct.
|
||||||
AggregateKind::Closure(def_id, substs) => {
|
AggregateKind::Closure(def_id, ty::ClosureSubsts { substs })
|
||||||
self.prove_closure_bounds(tcx, *def_id, *substs, location)
|
| AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
|
||||||
}
|
self.prove_closure_bounds(tcx, *def_id, substs, location)
|
||||||
|
|
||||||
AggregateKind::Generator(def_id, substs, _) => {
|
|
||||||
tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
|
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
|
||||||
@ -2096,7 +2093,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
substs: ty::ClosureSubsts<'tcx>,
|
substs: &'tcx Substs<'tcx>,
|
||||||
location: Location,
|
location: Location,
|
||||||
) -> ty::InstantiatedPredicates<'tcx> {
|
) -> ty::InstantiatedPredicates<'tcx> {
|
||||||
if let Some(closure_region_requirements) =
|
if let Some(closure_region_requirements) =
|
||||||
@ -2155,7 +2152,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
tcx.predicates_of(def_id).instantiate(tcx, substs.substs)
|
tcx.predicates_of(def_id).instantiate(tcx, substs)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prove_trait_ref(
|
fn prove_trait_ref(
|
||||||
|
@ -232,13 +232,13 @@ impl<'tcx> UniversalRegions<'tcx> {
|
|||||||
/// `V[1]: V[2]`.
|
/// `V[1]: V[2]`.
|
||||||
pub fn closure_mapping(
|
pub fn closure_mapping(
|
||||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||||
closure_ty: Ty<'tcx>,
|
closure_substs: &'tcx Substs<'tcx>,
|
||||||
expected_num_vars: usize,
|
expected_num_vars: usize,
|
||||||
closure_base_def_id: DefId,
|
closure_base_def_id: DefId,
|
||||||
) -> IndexVec<RegionVid, ty::Region<'tcx>> {
|
) -> IndexVec<RegionVid, ty::Region<'tcx>> {
|
||||||
let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
|
let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
|
||||||
region_mapping.push(tcx.types.re_static);
|
region_mapping.push(tcx.types.re_static);
|
||||||
tcx.for_each_free_region(&closure_ty, |fr| {
|
tcx.for_each_free_region(&closure_substs, |fr| {
|
||||||
region_mapping.push(fr);
|
region_mapping.push(fr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0621]: explicit lifetime required in the type of `x`
|
||||||
|
--> $DIR/generator-region-requirements.rs:15:51
|
||||||
|
|
|
||||||
|
LL | fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||||
|
| -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
|
||||||
|
...
|
||||||
|
LL | GeneratorState::Complete(c) => return c,
|
||||||
|
| ^ lifetime `'static` required
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0621`.
|
@ -0,0 +1,12 @@
|
|||||||
|
error[E0621]: explicit lifetime required in the type of `x`
|
||||||
|
--> $DIR/generator-region-requirements.rs:11:9
|
||||||
|
|
|
||||||
|
LL | fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||||
|
| -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32`
|
||||||
|
...
|
||||||
|
LL | x
|
||||||
|
| ^ lifetime `'static` required
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0621`.
|
21
src/test/ui/generator/generator-region-requirements.rs
Normal file
21
src/test/ui/generator/generator-region-requirements.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// revisions: ast nll
|
||||||
|
// ignore-compare-mode-nll
|
||||||
|
|
||||||
|
#![feature(generators, generator_trait)]
|
||||||
|
#![cfg_attr(nll, feature(nll))]
|
||||||
|
use std::ops::{Generator, GeneratorState};
|
||||||
|
|
||||||
|
fn dangle(x: &mut i32) -> &'static mut i32 {
|
||||||
|
let mut g = || {
|
||||||
|
yield;
|
||||||
|
x
|
||||||
|
};
|
||||||
|
loop {
|
||||||
|
match unsafe { g.resume() } {
|
||||||
|
GeneratorState::Complete(c) => return c,
|
||||||
|
GeneratorState::Yielded(_) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
Reference in New Issue
Block a user