From 3f0f10ab73bef1d8401e3288d5140c988af8fd64 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 19 Jan 2020 16:51:25 +0800 Subject: [PATCH 1/6] retrieve outlives constraints from inferctxt --- src/librustc_infer/infer/region_constraints/mod.rs | 13 +++++++++++-- src/librustc_typeck/check/generator_interior.rs | 10 ++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index e10b0938955af..e8c1527673949 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -13,7 +13,7 @@ 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}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; @@ -137,7 +137,7 @@ 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, @@ -145,6 +145,15 @@ impl Constraint<'_> { Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(), } } + + pub fn to_region_outlives_predicate(self) -> OutlivesPredicate { + match self { + Self::VarSubVar(a, b) => OutlivesPredicate(RegionKind::ReVar(a), RegionKind::ReVar(b)), + Self::RegSubVar(a, b) => OutlivesPredicate(*a, RegionKind::ReVar(b)), + Self::VarSubReg(a, b) => OutlivesPredicate(RegionKind::ReVar(a), *b), + Self::RegSubReg(a, b) => OutlivesPredicate(*a, *b), + } + } } /// `VerifyGenericBound(T, _, R, RS)`: the parameter type `T` (or diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index ce376a08ea604..7a3de56665189 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -188,6 +188,16 @@ pub fn resolve_interior<'a, 'tcx>( // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); + let _region_constraints = visitor.fcx.with_region_constraints(|constraints_data| { + constraints_data + .constraints + .keys() + .map(|constraints| constraints.to_region_outlives_predicate()) + .collect::>() + }); + + debug!("region outlives inside generator: {:?}", _region_constraints); + let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list)); // Store the generator types and spans into the tables for this generator. From 66729078482204c51f049f622eef5716568db271 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 9 Feb 2020 15:14:10 +0800 Subject: [PATCH 2/6] add test for lifetime inside generator witness --- src/test/ui/async-await/issues/issue-64552.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/ui/async-await/issues/issue-64552.rs diff --git a/src/test/ui/async-await/issues/issue-64552.rs b/src/test/ui/async-await/issues/issue-64552.rs new file mode 100644 index 0000000000000..bf9a3e90ebed1 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-64552.rs @@ -0,0 +1,18 @@ +// edition: 2018 + +async fn use_async(_val: T) {} + +struct MyStruct<'a, T: 'a> { + val: &'a T +} + +unsafe impl<'a, T: 'a> Send for MyStruct<'a, T> {} + +async fn use_my_struct(val: MyStruct<'static, &'static u8>) { + use_async(val).await; +} + +fn main() { + let first_struct: MyStruct<'static, &'static u8> = MyStruct { val: &&26 }; + needs_send(use_my_struct(second_struct)); +} From f3aedd5618b205a6f905d2eb33c8444b693674bc Mon Sep 17 00:00:00 2001 From: csmoe Date: Tue, 11 Feb 2020 21:51:56 +0800 Subject: [PATCH 3/6] add region outlives to generator witness --- src/librustc/ty/walk.rs | 138 ++++++++++++++++++ .../infer/region_constraints/mod.rs | 16 +- src/librustc_middle/ty/context.rs | 8 +- src/librustc_middle/ty/fast_reject.rs | 2 +- src/librustc_middle/ty/flags.rs | 2 +- src/librustc_middle/ty/mod.rs | 1 + src/librustc_middle/ty/print/obsolete.rs | 2 +- src/librustc_middle/ty/print/pretty.rs | 2 +- src/librustc_middle/ty/relate.rs | 6 +- src/librustc_middle/ty/structural_impls.rs | 6 +- src/librustc_middle/ty/sty.rs | 5 +- src/librustc_middle/ty/util.rs | 2 +- src/librustc_middle/ty/walk.rs | 2 +- .../interpret/intrinsics/type_name.rs | 2 +- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_symbol_mangling/v0.rs | 2 +- src/librustc_trait_selection/traits/select.rs | 2 +- .../check/generator_interior.rs | 7 +- 18 files changed, 180 insertions(+), 27 deletions(-) create mode 100644 src/librustc/ty/walk.rs diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs new file mode 100644 index 0000000000000..5ebf63fd2dd44 --- /dev/null +++ b/src/librustc/ty/walk.rs @@ -0,0 +1,138 @@ +//! An iterator over the type substructure. +//! WARNING: this does not keep track of the region depth. + +use crate::ty::{self, Ty}; +use smallvec::{self, SmallVec}; + +// The TypeWalker's stack is hot enough that it's worth going to some effort to +// avoid heap allocations. +pub type TypeWalkerArray<'tcx> = [Ty<'tcx>; 8]; +pub type TypeWalkerStack<'tcx> = SmallVec>; + +pub struct TypeWalker<'tcx> { + stack: TypeWalkerStack<'tcx>, + last_subtree: usize, +} + +impl<'tcx> TypeWalker<'tcx> { + pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> { + TypeWalker { stack: smallvec![ty], last_subtree: 1 } + } + + /// Skips the subtree of types corresponding to the last type + /// returned by `next()`. + /// + /// Example: Imagine you are walking `Foo, usize>`. + /// + /// ``` + /// let mut iter: TypeWalker = ...; + /// iter.next(); // yields Foo + /// iter.next(); // yields Bar + /// iter.skip_current_subtree(); // skips int + /// iter.next(); // yields usize + /// ``` + pub fn skip_current_subtree(&mut self) { + self.stack.truncate(self.last_subtree); + } +} + +impl<'tcx> Iterator for TypeWalker<'tcx> { + type Item = Ty<'tcx>; + + fn next(&mut self) -> Option> { + debug!("next(): stack={:?}", self.stack); + match self.stack.pop() { + None => None, + Some(ty) => { + self.last_subtree = self.stack.len(); + push_subtypes(&mut self.stack, ty); + debug!("next: stack={:?}", self.stack); + Some(ty) + } + } + } +} + +pub fn walk_shallow(ty: Ty<'_>) -> smallvec::IntoIter> { + let mut stack = SmallVec::new(); + push_subtypes(&mut stack, ty); + stack.into_iter() +} + +// We push types on the stack in reverse order so as to +// maintain a pre-order traversal. As of the time of this +// writing, the fact that the traversal is pre-order is not +// known to be significant to any code, but it seems like the +// natural order one would expect (basically, the order of the +// types as they are written). +fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { + match parent_ty.kind { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Str + | ty::Infer(_) + | ty::Param(_) + | ty::Never + | ty::Error + | ty::Placeholder(..) + | ty::Bound(..) + | ty::Foreign(..) => {} + ty::Array(ty, len) => { + if let ty::ConstKind::Unevaluated(_, substs, promoted) = len.val { + assert!(promoted.is_none()); + stack.extend(substs.types().rev()); + } + stack.push(len.ty); + stack.push(ty); + } + ty::Slice(ty) => { + stack.push(ty); + } + ty::RawPtr(ref mt) => { + stack.push(mt.ty); + } + ty::Ref(_, ty, _) => { + stack.push(ty); + } + ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => { + stack.extend(data.substs.types().rev()); + } + ty::Dynamic(ref obj, ..) => { + stack.extend(obj.iter().rev().flat_map(|predicate| { + let (substs, opt_ty) = match *predicate.skip_binder() { + ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), + ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)), + ty::ExistentialPredicate::AutoTrait(_) => + // Empty iterator + { + (ty::InternalSubsts::empty(), None) + } + }; + + substs.types().rev().chain(opt_ty) + })); + } + ty::Adt(_, substs) | ty::Opaque(_, substs) => { + stack.extend(substs.types().rev()); + } + ty::Closure(_, ref substs) | ty::Generator(_, ref substs, _) => { + stack.extend(substs.types().rev()); + } + ty::GeneratorWitness(ts, _) => { + stack.extend(ts.skip_binder().iter().cloned().rev()); + } + ty::Tuple(..) => { + stack.extend(parent_ty.tuple_fields().rev()); + } + ty::FnDef(_, substs) => { + stack.extend(substs.types().rev()); + } + ty::FnPtr(sig) => { + stack.push(sig.skip_binder().output()); + stack.extend(sig.skip_binder().inputs().iter().cloned().rev()); + } + } +} diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index e8c1527673949..be126dcc1b7d4 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -146,12 +146,18 @@ impl<'tcx> Constraint<'tcx> { } } - pub fn to_region_outlives_predicate(self) -> OutlivesPredicate { + pub fn to_region_outlives_predicate( + &self, + tcx: &TyCtxt<'tcx>, + ) -> RegionOutlivesPredicate, Region<'tcx>> { match self { - Self::VarSubVar(a, b) => OutlivesPredicate(RegionKind::ReVar(a), RegionKind::ReVar(b)), - Self::RegSubVar(a, b) => OutlivesPredicate(*a, RegionKind::ReVar(b)), - Self::VarSubReg(a, b) => OutlivesPredicate(RegionKind::ReVar(a), *b), - Self::RegSubReg(a, b) => OutlivesPredicate(*a, *b), + 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), } } } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index c5813ae57a653..5a4535382d05d 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -2329,8 +2329,12 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List>>) -> Ty<'tcx> { - self.mk_ty(GeneratorWitness(types)) + pub fn mk_generator_witness( + self, + types: ty::Binder<&'tcx List>>, + region_outlives: &'tcx List>, + ) -> Ty<'tcx> { + self.mk_ty(GeneratorWitness(types, region_outlives)) } #[inline] diff --git a/src/librustc_middle/ty/fast_reject.rs b/src/librustc_middle/ty/fast_reject.rs index 2a937d6581d6a..67ccdca7045eb 100644 --- a/src/librustc_middle/ty/fast_reject.rs +++ b/src/librustc_middle/ty/fast_reject.rs @@ -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), diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index a88f362810995..a8a1fc8f639af 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -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); diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 0abe44b31065d..deb7c66de7dd3 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -795,6 +795,7 @@ impl<'a, T> IntoIterator for &'a List { } impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List> {} +impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List> {} impl List { #[inline(always)] diff --git a/src/librustc_middle/ty/print/obsolete.rs b/src/librustc_middle/ty/print/obsolete.rs index 757a8bd23f62b..eeacced6ac61e 100644 --- a/src/librustc_middle/ty/print/obsolete.rs +++ b/src/librustc_middle/ty/print/obsolete.rs @@ -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)); diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 2d2704fc2bd89..bc01e6c32da08 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -643,7 +643,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("]")) } - ty::GeneratorWitness(types) => { + ty::GeneratorWitness(types, _) => { p!(in_binder(&types)); } ty::Closure(did, substs) => { diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index f4f0b6c41b92f..8814e7fd07166 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -8,7 +8,7 @@ use crate::mir::interpret::{get_slice_bytes, ConstValue}; use crate::traits; use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, List, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; use rustc_target::spec::abi; @@ -396,14 +396,14 @@ pub fn super_relate_tys>( Ok(tcx.mk_generator(a_id, substs, movability)) } - (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => { + (&ty::GeneratorWitness(a_types, _), &ty::GeneratorWitness(b_types, _)) => { // 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); // 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)) + Ok(tcx.mk_generator_witness(types, List::empty())) } (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => { diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index 1c0ffe12314b3..b5b811f8bfaf9 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -884,7 +884,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) => { @@ -928,7 +930,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) diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index ac5477edcc3c0..d46e2c64d5581 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -12,7 +12,8 @@ use crate::mir::interpret::{LitToConstInput, Scalar}; use crate::mir::Promoted; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::{ - self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, + self, AdtDef, DefIdTree, Discr, RegionOutlivesPredicate, Ty, TyCtxt, TypeFlags, TypeFoldable, + WithConstness, }; use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS}; use polonius_engine::Atom; @@ -168,7 +169,7 @@ pub enum TyKind<'tcx> { /// A type representin the types stored inside a generator. /// This should only appear in GeneratorInteriors. - GeneratorWitness(Binder<&'tcx List>>), + GeneratorWitness(Binder<&'tcx List>>, &'tcx List>), /// The never type `!` Never, diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs index b46caf7985208..e1daccb11aa39 100644 --- a/src/librustc_middle/ty/util.rs +++ b/src/librustc_middle/ty/util.rs @@ -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(_) diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs index b6cadd0099656..8da2813a076f8 100644 --- a/src/librustc_middle/ty/walk.rs +++ b/src/librustc_middle/ty/walk.rs @@ -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) => { diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index b81a454cac408..0a1488c985c33 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -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`"), } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 611d03405e2c8..5141a3fa38c8f 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -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!(), }; diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs index 53df140e0b5ae..08e369a616eeb 100644 --- a/src/librustc_symbol_mangling/v0.rs +++ b/src/librustc_symbol_mangling/v0.rs @@ -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 diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index dfbb07424487d..e92571df531b3 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -2312,7 +2312,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { substs.as_generator().upvar_tys().chain(iter::once(witness)).collect() } - ty::GeneratorWitness(types) => { + ty::GeneratorWitness(types, _) => { // This is sound because no regions in the witness can refer to // the binder outside the witness. So we'll effectivly reuse // the implicit binder around the witness. diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 7a3de56665189..fa5e93f84abd8 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -188,17 +188,18 @@ pub fn resolve_interior<'a, 'tcx>( // Extract type components to build the witness type. let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty)); - let _region_constraints = visitor.fcx.with_region_constraints(|constraints_data| { + let region_constraints = visitor.fcx.with_region_constraints(|constraints_data| { constraints_data .constraints .keys() .map(|constraints| constraints.to_region_outlives_predicate()) .collect::>() }); + debug!("region outlives inside generator: {:?}", region_constraints); - debug!("region outlives inside generator: {:?}", _region_constraints); + let region_outlives_list = fcx.tcx.mk_predicates(region_constraints.iter()); - let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list)); + let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list), region_outlives_list); // Store the generator types and spans into the tables for this generator. visitor.fcx.inh.tables.borrow_mut().generator_interior_types = type_causes; From 3e8280d93114b6775a41519ab4ceafba158cbe47 Mon Sep 17 00:00:00 2001 From: csmoe Date: Tue, 3 Mar 2020 22:21:55 +0800 Subject: [PATCH 4/6] intern region outlives predicate --- src/librustc_infer/infer/region_constraints/mod.rs | 7 ++----- src/librustc_middle/ty/context.rs | 2 +- src/librustc_middle/ty/mod.rs | 2 +- src/librustc_middle/ty/relate.rs | 4 ++-- src/librustc_middle/ty/sty.rs | 5 ++--- src/librustc_typeck/check/generator_interior.rs | 10 +++++++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index be126dcc1b7d4..b68d06a575c8b 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -13,7 +13,7 @@ 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::{OutlivesPredicate, ReLateBound, ReVar, RegionKind}; +use rustc_middle::ty::{OutlivesPredicate, ReLateBound, ReVar, RegionKind, RegionOutlivesPredicate}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; @@ -146,10 +146,7 @@ impl<'tcx> Constraint<'tcx> { } } - pub fn to_region_outlives_predicate( - &self, - tcx: &TyCtxt<'tcx>, - ) -> RegionOutlivesPredicate, Region<'tcx>> { + 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)), diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 5a4535382d05d..7f3edded03d35 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -2332,7 +2332,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_generator_witness( self, types: ty::Binder<&'tcx List>>, - region_outlives: &'tcx List>, + region_outlives: ty::Binder<&'tcx List>>, ) -> Ty<'tcx> { self.mk_ty(GeneratorWitness(types, region_outlives)) } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index deb7c66de7dd3..05c8ac8119c28 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1372,7 +1372,7 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder>; /// 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>, diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 8814e7fd07166..f252151a3c2b6 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -8,7 +8,7 @@ use crate::mir::interpret::{get_slice_bytes, ConstValue}; use crate::traits; use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use crate::ty::{self, List, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as ast; use rustc_hir::def_id::DefId; use rustc_target::spec::abi; @@ -403,7 +403,7 @@ pub fn super_relate_tys>( let b_types = b_types.map_bound(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, List::empty())) + Ok(tcx.mk_generator_witness(types, ty::Binder::dummy())) } (&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => { diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index d46e2c64d5581..7e9e18e8a4fc3 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -12,8 +12,7 @@ use crate::mir::interpret::{LitToConstInput, Scalar}; use crate::mir::Promoted; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::{ - self, AdtDef, DefIdTree, Discr, RegionOutlivesPredicate, Ty, TyCtxt, TypeFlags, TypeFoldable, - WithConstness, + self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, }; use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS}; use polonius_engine::Atom; @@ -169,7 +168,7 @@ pub enum TyKind<'tcx> { /// A type representin the types stored inside a generator. /// This should only appear in GeneratorInteriors. - GeneratorWitness(Binder<&'tcx List>>, &'tcx List>), + GeneratorWitness(Binder<&'tcx List>>, Binder<&'tcx List>>), /// The never type `!` Never, diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index fa5e93f84abd8..5e40c45f6d279 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_middle::middle::region::{self, YieldData}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, ToPredicate, Ty}; use rustc_span::Span; struct InteriorVisitor<'a, 'tcx> { @@ -192,14 +192,18 @@ pub fn resolve_interior<'a, 'tcx>( constraints_data .constraints .keys() - .map(|constraints| constraints.to_region_outlives_predicate()) + .map(|constraints| { + ty::Binder::bind(constraints.to_region_outlives_predicate(fcx.tcx)).to_predicate() + }) .collect::>() }); debug!("region outlives inside generator: {:?}", region_constraints); let region_outlives_list = fcx.tcx.mk_predicates(region_constraints.iter()); - let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list), region_outlives_list); + let witness = fcx + .tcx + .mk_generator_witness(ty::Binder::bind(type_list), ty::Binder::bind(region_outlives_list)); // Store the generator types and spans into the tables for this generator. visitor.fcx.inh.tables.borrow_mut().generator_interior_types = type_causes; From 461a94937cad79891134b70d0f0c769b8626b9d7 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 22 Mar 2020 19:24:54 +0800 Subject: [PATCH 5/6] intern regionoutlivespredicate --- src/librustc_middle/ty/context.rs | 38 +++++++++++++++- src/librustc_middle/ty/relate.rs | 44 ++++++++++++++----- src/librustc_middle/ty/structural_impls.rs | 10 +++++ src/librustc_middle/ty/sty.rs | 5 ++- .../check/generator_interior.rs | 6 +-- 5 files changed, 86 insertions(+), 17 deletions(-) diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 7f3edded03d35..0cb2a9a53e64f 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -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; @@ -91,6 +94,7 @@ pub struct CtxtInterners<'tcx> { canonical_var_infos: InternedSet<'tcx, List>, region: InternedSet<'tcx, RegionKind>, existential_predicates: InternedSet<'tcx, List>>, + region_outlives_predicates: InternedSet<'tcx, List>>, predicates: InternedSet<'tcx, List>>, clauses: InternedSet<'tcx, List>>, goal: InternedSet<'tcx, GoalKind<'tcx>>, @@ -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(), @@ -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} @@ -2010,6 +2016,14 @@ impl<'tcx> Borrow<[ExistentialPredicate<'tcx>]> } } +impl<'tcx> Borrow<[RegionOutlivesPredicate<'tcx>]> + for Interned<'tcx, List>> +{ + fn borrow<'a>(&'a self) -> &'a [RegionOutlivesPredicate<'tcx>] { + &self.0[..] + } +} + impl<'tcx> Borrow<[Predicate<'tcx>]> for Interned<'tcx, List>> { fn borrow<'a>(&'a self) -> &'a [Predicate<'tcx>] { &self.0[..] @@ -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>), @@ -2332,7 +2347,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn mk_generator_witness( self, types: ty::Binder<&'tcx List>>, - region_outlives: ty::Binder<&'tcx List>>, + region_outlives: ty::Binder<&'tcx List>>, ) -> Ty<'tcx> { self.mk_ty(GeneratorWitness(types, region_outlives)) } @@ -2445,6 +2460,16 @@ impl<'tcx> TyCtxt<'tcx> { self._intern_existential_predicates(eps) } + pub fn intern_region_outlives_predicates( + self, + predicates: &[RegionOutlivesPredicate<'tcx>], + ) -> &'tcx List> { + if predicates.is_empty() { + List::empty() + } else { + self._intern_region_outlive_predicates(predicates) + } + } pub fn intern_predicates(self, preds: &[Predicate<'tcx>]) -> &'tcx List> { // FIXME consider asking the input slice to be sorted to avoid // re-interning permutations, in which case that would be asserted @@ -2513,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>>, + >( + self, + iter: I, + ) -> I::Output { + iter.intern_with(|xs| self.intern_region_outlives_predicates(xs)) + } + pub fn mk_predicates], &'tcx List>>>( self, iter: I, diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index f252151a3c2b6..07aadf07ccaef 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -308,19 +308,38 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { } } +impl<'tcx> Relate<'tcx> for ty::RegionOutlivesPredicate<'tcx> { + fn relate>( + 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>); +struct GeneratorWitness<'tcx>( + &'tcx ty::List>, + &'tcx ty::List>, +); impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> { fn relate>( 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)) } } @@ -396,14 +415,19 @@ pub fn super_relate_tys>( 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, ty::Binder::dummy())) + 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 => { diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index b5b811f8bfaf9..0e0c762c4b6ae 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -800,6 +800,16 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> } } +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + fold_list(*self, folder, |tcx, v| tcx.intern_region_outlives_predicates(v)) + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.iter().any(|p| p.visit_with(visitor)) + } +} + impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { fold_list(*self, folder, |tcx, v| tcx.intern_type_list(v)) diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 7e9e18e8a4fc3..59a763c20bf2d 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -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>>, Binder<&'tcx List>>), + GeneratorWitness( + Binder<&'tcx List>>, + Binder<&'tcx List>>, + ), /// The never type `!` Never, diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 5e40c45f6d279..c4c51f9ef420f 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -192,14 +192,12 @@ pub fn resolve_interior<'a, 'tcx>( constraints_data .constraints .keys() - .map(|constraints| { - ty::Binder::bind(constraints.to_region_outlives_predicate(fcx.tcx)).to_predicate() - }) + .map(|constraints| constraints.to_region_outlives_predicate(fcx.tcx)) .collect::>() }); debug!("region outlives inside generator: {:?}", region_constraints); - let region_outlives_list = fcx.tcx.mk_predicates(region_constraints.iter()); + let region_outlives_list = fcx.tcx.mk_region_outlives_predicates(region_constraints.iter()); let witness = fcx .tcx From f02fdd524627ca8c4108ca55cefeabea680fce7f Mon Sep 17 00:00:00 2001 From: csmoe Date: Tue, 24 Mar 2020 17:42:35 +0800 Subject: [PATCH 6/6] extend param_env with predicates from generator_witness --- src/librustc/ty/walk.rs | 138 ------------------ .../infer/region_constraints/mod.rs | 4 +- src/librustc_trait_selection/traits/select.rs | 19 ++- src/librustc_ty/needs_drop.rs | 2 +- .../check/generator_interior.rs | 2 +- 5 files changed, 23 insertions(+), 142 deletions(-) delete mode 100644 src/librustc/ty/walk.rs diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs deleted file mode 100644 index 5ebf63fd2dd44..0000000000000 --- a/src/librustc/ty/walk.rs +++ /dev/null @@ -1,138 +0,0 @@ -//! An iterator over the type substructure. -//! WARNING: this does not keep track of the region depth. - -use crate::ty::{self, Ty}; -use smallvec::{self, SmallVec}; - -// The TypeWalker's stack is hot enough that it's worth going to some effort to -// avoid heap allocations. -pub type TypeWalkerArray<'tcx> = [Ty<'tcx>; 8]; -pub type TypeWalkerStack<'tcx> = SmallVec>; - -pub struct TypeWalker<'tcx> { - stack: TypeWalkerStack<'tcx>, - last_subtree: usize, -} - -impl<'tcx> TypeWalker<'tcx> { - pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> { - TypeWalker { stack: smallvec![ty], last_subtree: 1 } - } - - /// Skips the subtree of types corresponding to the last type - /// returned by `next()`. - /// - /// Example: Imagine you are walking `Foo, usize>`. - /// - /// ``` - /// let mut iter: TypeWalker = ...; - /// iter.next(); // yields Foo - /// iter.next(); // yields Bar - /// iter.skip_current_subtree(); // skips int - /// iter.next(); // yields usize - /// ``` - pub fn skip_current_subtree(&mut self) { - self.stack.truncate(self.last_subtree); - } -} - -impl<'tcx> Iterator for TypeWalker<'tcx> { - type Item = Ty<'tcx>; - - fn next(&mut self) -> Option> { - debug!("next(): stack={:?}", self.stack); - match self.stack.pop() { - None => None, - Some(ty) => { - self.last_subtree = self.stack.len(); - push_subtypes(&mut self.stack, ty); - debug!("next: stack={:?}", self.stack); - Some(ty) - } - } - } -} - -pub fn walk_shallow(ty: Ty<'_>) -> smallvec::IntoIter> { - let mut stack = SmallVec::new(); - push_subtypes(&mut stack, ty); - stack.into_iter() -} - -// We push types on the stack in reverse order so as to -// maintain a pre-order traversal. As of the time of this -// writing, the fact that the traversal is pre-order is not -// known to be significant to any code, but it seems like the -// natural order one would expect (basically, the order of the -// types as they are written). -fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { - match parent_ty.kind { - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Str - | ty::Infer(_) - | ty::Param(_) - | ty::Never - | ty::Error - | ty::Placeholder(..) - | ty::Bound(..) - | ty::Foreign(..) => {} - ty::Array(ty, len) => { - if let ty::ConstKind::Unevaluated(_, substs, promoted) = len.val { - assert!(promoted.is_none()); - stack.extend(substs.types().rev()); - } - stack.push(len.ty); - stack.push(ty); - } - ty::Slice(ty) => { - stack.push(ty); - } - ty::RawPtr(ref mt) => { - stack.push(mt.ty); - } - ty::Ref(_, ty, _) => { - stack.push(ty); - } - ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => { - stack.extend(data.substs.types().rev()); - } - ty::Dynamic(ref obj, ..) => { - stack.extend(obj.iter().rev().flat_map(|predicate| { - let (substs, opt_ty) = match *predicate.skip_binder() { - ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), - ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)), - ty::ExistentialPredicate::AutoTrait(_) => - // Empty iterator - { - (ty::InternalSubsts::empty(), None) - } - }; - - substs.types().rev().chain(opt_ty) - })); - } - ty::Adt(_, substs) | ty::Opaque(_, substs) => { - stack.extend(substs.types().rev()); - } - ty::Closure(_, ref substs) | ty::Generator(_, ref substs, _) => { - stack.extend(substs.types().rev()); - } - ty::GeneratorWitness(ts, _) => { - stack.extend(ts.skip_binder().iter().cloned().rev()); - } - ty::Tuple(..) => { - stack.extend(parent_ty.tuple_fields().rev()); - } - ty::FnDef(_, substs) => { - stack.extend(substs.types().rev()); - } - ty::FnPtr(sig) => { - stack.push(sig.skip_binder().output()); - stack.extend(sig.skip_binder().inputs().iter().cloned().rev()); - } - } -} diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index b68d06a575c8b..ebcc244c8bc53 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -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::{OutlivesPredicate, ReLateBound, ReVar, RegionKind, RegionOutlivesPredicate}; +use rustc_middle::ty::{ + OutlivesPredicate, ReLateBound, ReVar, RegionKind, RegionOutlivesPredicate, +}; use rustc_middle::ty::{Region, RegionVid}; use rustc_span::Span; diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index e92571df531b3..c749df59646c8 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -2335,7 +2335,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn collect_predicates_for_types( &mut self, - param_env: ty::ParamEnv<'tcx>, + mut param_env: ty::ParamEnv<'tcx>, cause: ObligationCause<'tcx>, recursion_depth: usize, trait_def_id: DefId, @@ -2359,6 +2359,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .skip_binder() .iter() .flat_map(|ty| { + let param_env = if let ty::GeneratorWitness(_, predicates) = ty.kind { + let predicates: Vec<_> = param_env + .caller_bounds + .to_vec() + .into_iter() + .chain( + predicates + .skip_binder() + .into_iter() + .map(|&p| ty::Binder::bind(p).to_predicate()), + ) + .collect(); + param_env.caller_bounds = self.infcx.tcx.mk_predicates(predicates.iter()); + param_env + } else { + param_env + }; // binder moved -\ let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs index 97994b465b54c..effa1d736c7b4 100644 --- a/src/librustc_ty/needs_drop.rs +++ b/src/librustc_ty/needs_drop.rs @@ -107,7 +107,7 @@ where let witness = substs.witness(); let interior_tys = match &witness.kind { - ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys), + ty::GeneratorWitness(tys, _) => tcx.erase_late_bound_regions(tys), _ => bug!(), }; diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index c4c51f9ef420f..1bbf41a3eb441 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, ExprKind, Pat, PatKind}; use rustc_middle::middle::region::{self, YieldData}; -use rustc_middle::ty::{self, ToPredicate, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_span::Span; struct InteriorVisitor<'a, 'tcx> {