Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record lifetime constraints inside generator interior #68362

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/librustc_infer/infer/region_constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use rustc_hir::def_id::DefId;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::ReStatic;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReLateBound, ReVar};
use rustc_middle::ty::{
OutlivesPredicate, ReLateBound, ReVar, RegionKind, RegionOutlivesPredicate,
};
use rustc_middle::ty::{Region, RegionVid};
use rustc_span::Span;

Expand Down Expand Up @@ -137,14 +139,26 @@ pub enum Constraint<'tcx> {
RegSubReg(Region<'tcx>, Region<'tcx>),
}

impl Constraint<'_> {
impl<'tcx> Constraint<'tcx> {
pub fn involves_placeholders(&self) -> bool {
match self {
Constraint::VarSubVar(_, _) => false,
Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(),
Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(),
}
}

pub fn to_region_outlives_predicate(&self, tcx: TyCtxt<'tcx>) -> RegionOutlivesPredicate<'tcx> {
match self {
Self::VarSubVar(a, b) => OutlivesPredicate(
tcx.mk_region(RegionKind::ReVar(*a)),
tcx.mk_region(RegionKind::ReVar(*b)),
),
Self::RegSubVar(a, b) => OutlivesPredicate(a, tcx.mk_region(RegionKind::ReVar(*b))),
Self::VarSubReg(a, b) => OutlivesPredicate(tcx.mk_region(RegionKind::ReVar(*a)), b),
Self::RegSubReg(a, b) => OutlivesPredicate(a, b),
}
}
}

/// `VerifyGenericBound(T, _, R, RS)`: the parameter type `T` (or
Expand Down
44 changes: 41 additions & 3 deletions src/librustc_middle/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ use crate::ty::{self, DefIdTree, Ty, TypeAndMut};
use crate::ty::{AdtDef, AdtKind, Const, Region};
use crate::ty::{BindingMode, BoundVar};
use crate::ty::{ConstVid, FloatVar, FloatVid, IntVar, IntVid, TyVar, TyVid};
use crate::ty::{ExistentialPredicate, InferTy, ParamTy, PolyFnSig, Predicate, ProjectionTy};
use crate::ty::{
ExistentialPredicate, InferTy, ParamTy, PolyFnSig, Predicate, ProjectionTy,
RegionOutlivesPredicate,
};
use crate::ty::{InferConst, ParamConst};
use crate::ty::{List, TyKind, TyS};
use rustc_ast::ast;
Expand Down Expand Up @@ -91,6 +94,7 @@ pub struct CtxtInterners<'tcx> {
canonical_var_infos: InternedSet<'tcx, List<CanonicalVarInfo>>,
region: InternedSet<'tcx, RegionKind>,
existential_predicates: InternedSet<'tcx, List<ExistentialPredicate<'tcx>>>,
region_outlives_predicates: InternedSet<'tcx, List<RegionOutlivesPredicate<'tcx>>>,
predicates: InternedSet<'tcx, List<Predicate<'tcx>>>,
clauses: InternedSet<'tcx, List<Clause<'tcx>>>,
goal: InternedSet<'tcx, GoalKind<'tcx>>,
Expand All @@ -109,6 +113,7 @@ impl<'tcx> CtxtInterners<'tcx> {
substs: Default::default(),
region: Default::default(),
existential_predicates: Default::default(),
region_outlives_predicates: Default::default(),
canonical_var_infos: Default::default(),
predicates: Default::default(),
clauses: Default::default(),
Expand Down Expand Up @@ -1588,6 +1593,7 @@ nop_list_lift! {goal_list; Goal<'a> => Goal<'tcx>}
nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
nop_list_lift! {region_outlives_predicates; RegionOutlivesPredicate<'a> => RegionOutlivesPredicate<'tcx>}
nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
nop_list_lift! {canonical_var_infos; CanonicalVarInfo => CanonicalVarInfo}
nop_list_lift! {projs; ProjectionKind => ProjectionKind}
Expand Down Expand Up @@ -2010,6 +2016,14 @@ impl<'tcx> Borrow<[ExistentialPredicate<'tcx>]>
}
}

impl<'tcx> Borrow<[RegionOutlivesPredicate<'tcx>]>
for Interned<'tcx, List<RegionOutlivesPredicate<'tcx>>>
{
fn borrow<'a>(&'a self) -> &'a [RegionOutlivesPredicate<'tcx>] {
&self.0[..]
}
}

impl<'tcx> Borrow<[Predicate<'tcx>]> for Interned<'tcx, List<Predicate<'tcx>>> {
fn borrow<'a>(&'a self) -> &'a [Predicate<'tcx>] {
&self.0[..]
Expand Down Expand Up @@ -2083,6 +2097,7 @@ slice_interners!(
substs: _intern_substs(GenericArg<'tcx>),
canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo),
existential_predicates: _intern_existential_predicates(ExistentialPredicate<'tcx>),
region_outlives_predicates: _intern_region_outlive_predicates(RegionOutlivesPredicate<'tcx>),
predicates: _intern_predicates(Predicate<'tcx>),
clauses: _intern_clauses(Clause<'tcx>),
goal_list: _intern_goals(Goal<'tcx>),
Expand Down Expand Up @@ -2329,8 +2344,12 @@ impl<'tcx> TyCtxt<'tcx> {
}

#[inline]
pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
self.mk_ty(GeneratorWitness(types))
pub fn mk_generator_witness(
self,
types: ty::Binder<&'tcx List<Ty<'tcx>>>,
region_outlives: ty::Binder<&'tcx List<RegionOutlivesPredicate<'tcx>>>,
) -> Ty<'tcx> {
self.mk_ty(GeneratorWitness(types, region_outlives))
}

#[inline]
Expand Down Expand Up @@ -2441,6 +2460,16 @@ impl<'tcx> TyCtxt<'tcx> {
self._intern_existential_predicates(eps)
}

pub fn intern_region_outlives_predicates(
self,
predicates: &[RegionOutlivesPredicate<'tcx>],
) -> &'tcx List<RegionOutlivesPredicate<'tcx>> {
if predicates.is_empty() {
List::empty()
} else {
self._intern_region_outlive_predicates(predicates)
}
}
pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List<Predicate<'tcx>> {
// FIXME consider asking the input slice to be sorted to avoid
// re-interning permutations, in which case that would be asserted
Expand Down Expand Up @@ -2509,6 +2538,15 @@ impl<'tcx> TyCtxt<'tcx> {
iter.intern_with(|xs| self.intern_existential_predicates(xs))
}

pub fn mk_region_outlives_predicates<
I: InternAs<[RegionOutlivesPredicate<'tcx>], &'tcx List<RegionOutlivesPredicate<'tcx>>>,
>(
self,
iter: I,
) -> I::Output {
iter.intern_with(|xs| self.intern_region_outlives_predicates(xs))
}

pub fn mk_predicates<I: InternAs<[Predicate<'tcx>], &'tcx List<Predicate<'tcx>>>>(
self,
iter: I,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub fn simplify_type(
}
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
ty::GeneratorWitness(ref tys) => {
ty::GeneratorWitness(ref tys, _) => {
Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len()))
}
ty::Never => Some(NeverSimplifiedType),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl FlagComputation {
self.add_substs(substs);
}

&ty::GeneratorWitness(ref ts) => {
&ty::GeneratorWitness(ref ts, _) => {
let mut computation = FlagComputation::new();
computation.add_tys(&ts.skip_binder()[..]);
self.add_bound_computation(&computation);
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ impl<'a, T> IntoIterator for &'a List<T> {
}

impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<Ty<'tcx>> {}
impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<RegionOutlivesPredicate<'tcx>> {}

impl<T> List<T> {
#[inline(always)]
Expand Down Expand Up @@ -1371,7 +1372,7 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<SubtypePredicate<'tcx>>;
/// equality between arbitrary types. Processing an instance of
/// Form #2 eventually yields one of these `ProjectionPredicate`
/// instances to normalize the LHS.
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
#[derive(HashStable, TypeFoldable)]
pub struct ProjectionPredicate<'tcx> {
pub projection_ty: ProjectionTy<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/print/obsolete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl DefPathBasedNames<'tcx> {
| ty::UnnormalizedProjection(..)
| ty::Projection(..)
| ty::Param(_)
| ty::GeneratorWitness(_)
| ty::GeneratorWitness(..)
| ty::Opaque(..) => {
if debug {
output.push_str(&format!("`{:?}`", t));
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ pub trait PrettyPrinter<'tcx>:

p!(write("]"))
}
ty::GeneratorWitness(types) => {
ty::GeneratorWitness(types, _) => {
p!(in_binder(&types));
}
ty::Closure(did, substs) => {
Expand Down
44 changes: 34 additions & 10 deletions src/librustc_middle/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,19 +308,38 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
}
}

impl<'tcx> Relate<'tcx> for ty::RegionOutlivesPredicate<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: &Self,
b: &Self,
) -> RelateResult<'tcx, Self> {
let a_region = relation.relate(&a.0, &b.0)?;
let b_region = relation.relate(&a.1, &b.1)?;
Ok(ty::OutlivesPredicate(a_region, b_region))
}
}

#[derive(Debug, Clone, TypeFoldable)]
struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
struct GeneratorWitness<'tcx>(
&'tcx ty::List<Ty<'tcx>>,
&'tcx ty::List<ty::RegionOutlivesPredicate<'tcx>>,
);

impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {
fn relate<R: TypeRelation<'tcx>>(
relation: &mut R,
a: &GeneratorWitness<'tcx>,
b: &GeneratorWitness<'tcx>,
) -> RelateResult<'tcx, GeneratorWitness<'tcx>> {
a: &Self,
b: &Self,
) -> RelateResult<'tcx, Self> {
assert_eq!(a.0.len(), b.0.len());
assert_eq!(a.1.len(), b.1.len());
let tcx = relation.tcx();
let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
Ok(GeneratorWitness(types))
let predicates = tcx.mk_region_outlives_predicates(
a.1.iter().zip(b.1).map(|(a, b)| relation.relate(a, b)),
)?;
Ok(GeneratorWitness(types, predicates))
}
}

Expand Down Expand Up @@ -396,14 +415,19 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
Ok(tcx.mk_generator(a_id, substs, movability))
}

(&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
(
&ty::GeneratorWitness(a_types, a_outlive_predicates),
&ty::GeneratorWitness(b_types, b_outlive_predicates),
) => {
// Wrap our types with a temporary GeneratorWitness struct
// inside the binder so we can related them
let a_types = a_types.map_bound(GeneratorWitness);
let b_types = b_types.map_bound(GeneratorWitness);
let a_witness = a_types.fuse(a_outlive_predicates, GeneratorWitness);
let b_witness = b_types.fuse(b_outlive_predicates, GeneratorWitness);
// Then remove the GeneratorWitness for the result
let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0);
Ok(tcx.mk_generator_witness(types))
let types = relation.relate(&a_witness, &b_witness)?.map_bound(|witness| witness.0);
let predicates =
relation.relate(&a_witness, &b_witness)?.map_bound(|witness| witness.1);
Ok(tcx.mk_generator_witness(types, predicates))
}

(&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {
Expand Down
16 changes: 14 additions & 2 deletions src/librustc_middle/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,16 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>>
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::RegionOutlivesPredicate<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
fold_list(*self, folder, |tcx, v| tcx.intern_region_outlives_predicates(v))
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|p| p.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
fold_list(*self, folder, |tcx, v| tcx.intern_type_list(v))
Expand Down Expand Up @@ -884,7 +894,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::Generator(did, substs, movability) => {
ty::Generator(did, substs.fold_with(folder), movability)
}
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
ty::GeneratorWitness(types, region_outlives) => {
ty::GeneratorWitness(types.fold_with(folder), region_outlives)
}
ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
ty::Projection(ref data) => ty::Projection(data.fold_with(folder)),
ty::UnnormalizedProjection(ref data) => {
Expand Down Expand Up @@ -928,7 +940,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
ty::FnPtr(ref f) => f.visit_with(visitor),
ty::Ref(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor),
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
ty::GeneratorWitness(ref types, _) => types.visit_with(visitor),
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => {
data.visit_with(visitor)
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_middle/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,10 @@ pub enum TyKind<'tcx> {

/// A type representin the types stored inside a generator.
/// This should only appear in GeneratorInteriors.
GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>),
GeneratorWitness(
Binder<&'tcx List<Ty<'tcx>>>,
Binder<&'tcx List<ty::RegionOutlivesPredicate<'tcx>>>,
),

/// The never type `!`
Never,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ impl<'tcx> ty::TyS<'tcx> {
| ty::Dynamic(..)
| ty::Foreign(_)
| ty::Generator(..)
| ty::GeneratorWitness(_)
| ty::GeneratorWitness(..)
| ty::Infer(_)
| ty::Opaque(..)
| ty::Param(_)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ty/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
| ty::FnDef(_, substs) => {
stack.extend(substs.iter().copied().rev());
}
ty::GeneratorWitness(ts) => {
ty::GeneratorWitness(ts, _) => {
stack.extend(ts.skip_binder().iter().cloned().rev().map(|ty| ty.into()));
}
ty::FnPtr(sig) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/intrinsics/type_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
| ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),

ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
ty::GeneratorWitness(..) => bug!("type_name: unexpected `GeneratorWitness`"),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/transform/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ fn compute_layout<'tcx>(
// MIR types
let allowed_upvars = tcx.erase_regions(upvars);
let allowed = match interior.kind {
ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
ty::GeneratorWitness(s, _) => tcx.erase_late_bound_regions(&s),
_ => bug!(),
};

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_symbol_mangling/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
self = r.print(self)?;
}

ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"),
ty::GeneratorWitness(..) => bug!("symbol_names: unexpected `GeneratorWitness`"),
}

// Only cache types that do not refer to an enclosing
Expand Down
Loading