Skip to content

Commit f3aedd5

Browse files
committed
add region outlives to generator witness
1 parent 6672907 commit f3aedd5

File tree

18 files changed

+180
-27
lines changed

18 files changed

+180
-27
lines changed

src/librustc/ty/walk.rs

+138
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//! An iterator over the type substructure.
2+
//! WARNING: this does not keep track of the region depth.
3+
4+
use crate::ty::{self, Ty};
5+
use smallvec::{self, SmallVec};
6+
7+
// The TypeWalker's stack is hot enough that it's worth going to some effort to
8+
// avoid heap allocations.
9+
pub type TypeWalkerArray<'tcx> = [Ty<'tcx>; 8];
10+
pub type TypeWalkerStack<'tcx> = SmallVec<TypeWalkerArray<'tcx>>;
11+
12+
pub struct TypeWalker<'tcx> {
13+
stack: TypeWalkerStack<'tcx>,
14+
last_subtree: usize,
15+
}
16+
17+
impl<'tcx> TypeWalker<'tcx> {
18+
pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> {
19+
TypeWalker { stack: smallvec![ty], last_subtree: 1 }
20+
}
21+
22+
/// Skips the subtree of types corresponding to the last type
23+
/// returned by `next()`.
24+
///
25+
/// Example: Imagine you are walking `Foo<Bar<int>, usize>`.
26+
///
27+
/// ```
28+
/// let mut iter: TypeWalker = ...;
29+
/// iter.next(); // yields Foo
30+
/// iter.next(); // yields Bar<int>
31+
/// iter.skip_current_subtree(); // skips int
32+
/// iter.next(); // yields usize
33+
/// ```
34+
pub fn skip_current_subtree(&mut self) {
35+
self.stack.truncate(self.last_subtree);
36+
}
37+
}
38+
39+
impl<'tcx> Iterator for TypeWalker<'tcx> {
40+
type Item = Ty<'tcx>;
41+
42+
fn next(&mut self) -> Option<Ty<'tcx>> {
43+
debug!("next(): stack={:?}", self.stack);
44+
match self.stack.pop() {
45+
None => None,
46+
Some(ty) => {
47+
self.last_subtree = self.stack.len();
48+
push_subtypes(&mut self.stack, ty);
49+
debug!("next: stack={:?}", self.stack);
50+
Some(ty)
51+
}
52+
}
53+
}
54+
}
55+
56+
pub fn walk_shallow(ty: Ty<'_>) -> smallvec::IntoIter<TypeWalkerArray<'_>> {
57+
let mut stack = SmallVec::new();
58+
push_subtypes(&mut stack, ty);
59+
stack.into_iter()
60+
}
61+
62+
// We push types on the stack in reverse order so as to
63+
// maintain a pre-order traversal. As of the time of this
64+
// writing, the fact that the traversal is pre-order is not
65+
// known to be significant to any code, but it seems like the
66+
// natural order one would expect (basically, the order of the
67+
// types as they are written).
68+
fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
69+
match parent_ty.kind {
70+
ty::Bool
71+
| ty::Char
72+
| ty::Int(_)
73+
| ty::Uint(_)
74+
| ty::Float(_)
75+
| ty::Str
76+
| ty::Infer(_)
77+
| ty::Param(_)
78+
| ty::Never
79+
| ty::Error
80+
| ty::Placeholder(..)
81+
| ty::Bound(..)
82+
| ty::Foreign(..) => {}
83+
ty::Array(ty, len) => {
84+
if let ty::ConstKind::Unevaluated(_, substs, promoted) = len.val {
85+
assert!(promoted.is_none());
86+
stack.extend(substs.types().rev());
87+
}
88+
stack.push(len.ty);
89+
stack.push(ty);
90+
}
91+
ty::Slice(ty) => {
92+
stack.push(ty);
93+
}
94+
ty::RawPtr(ref mt) => {
95+
stack.push(mt.ty);
96+
}
97+
ty::Ref(_, ty, _) => {
98+
stack.push(ty);
99+
}
100+
ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => {
101+
stack.extend(data.substs.types().rev());
102+
}
103+
ty::Dynamic(ref obj, ..) => {
104+
stack.extend(obj.iter().rev().flat_map(|predicate| {
105+
let (substs, opt_ty) = match *predicate.skip_binder() {
106+
ty::ExistentialPredicate::Trait(tr) => (tr.substs, None),
107+
ty::ExistentialPredicate::Projection(p) => (p.substs, Some(p.ty)),
108+
ty::ExistentialPredicate::AutoTrait(_) =>
109+
// Empty iterator
110+
{
111+
(ty::InternalSubsts::empty(), None)
112+
}
113+
};
114+
115+
substs.types().rev().chain(opt_ty)
116+
}));
117+
}
118+
ty::Adt(_, substs) | ty::Opaque(_, substs) => {
119+
stack.extend(substs.types().rev());
120+
}
121+
ty::Closure(_, ref substs) | ty::Generator(_, ref substs, _) => {
122+
stack.extend(substs.types().rev());
123+
}
124+
ty::GeneratorWitness(ts, _) => {
125+
stack.extend(ts.skip_binder().iter().cloned().rev());
126+
}
127+
ty::Tuple(..) => {
128+
stack.extend(parent_ty.tuple_fields().rev());
129+
}
130+
ty::FnDef(_, substs) => {
131+
stack.extend(substs.types().rev());
132+
}
133+
ty::FnPtr(sig) => {
134+
stack.push(sig.skip_binder().output());
135+
stack.extend(sig.skip_binder().inputs().iter().cloned().rev());
136+
}
137+
}
138+
}

src/librustc_infer/infer/region_constraints/mod.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,18 @@ impl<'tcx> Constraint<'tcx> {
146146
}
147147
}
148148

149-
pub fn to_region_outlives_predicate(self) -> OutlivesPredicate<RegionKind, RegionKind> {
149+
pub fn to_region_outlives_predicate(
150+
&self,
151+
tcx: &TyCtxt<'tcx>,
152+
) -> RegionOutlivesPredicate<Region<'tcx>, Region<'tcx>> {
150153
match self {
151-
Self::VarSubVar(a, b) => OutlivesPredicate(RegionKind::ReVar(a), RegionKind::ReVar(b)),
152-
Self::RegSubVar(a, b) => OutlivesPredicate(*a, RegionKind::ReVar(b)),
153-
Self::VarSubReg(a, b) => OutlivesPredicate(RegionKind::ReVar(a), *b),
154-
Self::RegSubReg(a, b) => OutlivesPredicate(*a, *b),
154+
Self::VarSubVar(a, b) => OutlivesPredicate(
155+
tcx.mk_region(RegionKind::ReVar(*a)),
156+
tcx.mk_region(RegionKind::ReVar(*b)),
157+
),
158+
Self::RegSubVar(a, b) => OutlivesPredicate(a, tcx.mk_region(RegionKind::ReVar(*b))),
159+
Self::VarSubReg(a, b) => OutlivesPredicate(tcx.mk_region(RegionKind::ReVar(*a)), b),
160+
Self::RegSubReg(a, b) => OutlivesPredicate(a, b),
155161
}
156162
}
157163
}

src/librustc_middle/ty/context.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2329,8 +2329,12 @@ impl<'tcx> TyCtxt<'tcx> {
23292329
}
23302330

23312331
#[inline]
2332-
pub fn mk_generator_witness(self, types: ty::Binder<&'tcx List<Ty<'tcx>>>) -> Ty<'tcx> {
2333-
self.mk_ty(GeneratorWitness(types))
2332+
pub fn mk_generator_witness(
2333+
self,
2334+
types: ty::Binder<&'tcx List<Ty<'tcx>>>,
2335+
region_outlives: &'tcx List<ty::RegionOutlivesPredicate<'tcx>>,
2336+
) -> Ty<'tcx> {
2337+
self.mk_ty(GeneratorWitness(types, region_outlives))
23342338
}
23352339

23362340
#[inline]

src/librustc_middle/ty/fast_reject.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub fn simplify_type(
8484
}
8585
ty::FnDef(def_id, _) | ty::Closure(def_id, _) => Some(ClosureSimplifiedType(def_id)),
8686
ty::Generator(def_id, _, _) => Some(GeneratorSimplifiedType(def_id)),
87-
ty::GeneratorWitness(ref tys) => {
87+
ty::GeneratorWitness(ref tys, _) => {
8888
Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len()))
8989
}
9090
ty::Never => Some(NeverSimplifiedType),

src/librustc_middle/ty/flags.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl FlagComputation {
8181
self.add_substs(substs);
8282
}
8383

84-
&ty::GeneratorWitness(ref ts) => {
84+
&ty::GeneratorWitness(ref ts, _) => {
8585
let mut computation = FlagComputation::new();
8686
computation.add_tys(&ts.skip_binder()[..]);
8787
self.add_bound_computation(&computation);

src/librustc_middle/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ impl<'a, T> IntoIterator for &'a List<T> {
795795
}
796796

797797
impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<Ty<'tcx>> {}
798+
impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List<RegionOutlivesPredicate<'tcx>> {}
798799

799800
impl<T> List<T> {
800801
#[inline(always)]

src/librustc_middle/ty/print/obsolete.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl DefPathBasedNames<'tcx> {
151151
| ty::UnnormalizedProjection(..)
152152
| ty::Projection(..)
153153
| ty::Param(_)
154-
| ty::GeneratorWitness(_)
154+
| ty::GeneratorWitness(..)
155155
| ty::Opaque(..) => {
156156
if debug {
157157
output.push_str(&format!("`{:?}`", t));

src/librustc_middle/ty/print/pretty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ pub trait PrettyPrinter<'tcx>:
643643

644644
p!(write("]"))
645645
}
646-
ty::GeneratorWitness(types) => {
646+
ty::GeneratorWitness(types, _) => {
647647
p!(in_binder(&types));
648648
}
649649
ty::Closure(did, substs) => {

src/librustc_middle/ty/relate.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::mir::interpret::{get_slice_bytes, ConstValue};
88
use crate::traits;
99
use crate::ty::error::{ExpectedFound, TypeError};
1010
use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
11-
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
11+
use crate::ty::{self, List, Ty, TyCtxt, TypeFoldable};
1212
use rustc_hir as ast;
1313
use rustc_hir::def_id::DefId;
1414
use rustc_target::spec::abi;
@@ -396,14 +396,14 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
396396
Ok(tcx.mk_generator(a_id, substs, movability))
397397
}
398398

399-
(&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
399+
(&ty::GeneratorWitness(a_types, _), &ty::GeneratorWitness(b_types, _)) => {
400400
// Wrap our types with a temporary GeneratorWitness struct
401401
// inside the binder so we can related them
402402
let a_types = a_types.map_bound(GeneratorWitness);
403403
let b_types = b_types.map_bound(GeneratorWitness);
404404
// Then remove the GeneratorWitness for the result
405405
let types = relation.relate(&a_types, &b_types)?.map_bound(|witness| witness.0);
406-
Ok(tcx.mk_generator_witness(types))
406+
Ok(tcx.mk_generator_witness(types, List::empty()))
407407
}
408408

409409
(&ty::Closure(a_id, a_substs), &ty::Closure(b_id, b_substs)) if a_id == b_id => {

src/librustc_middle/ty/structural_impls.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
884884
ty::Generator(did, substs, movability) => {
885885
ty::Generator(did, substs.fold_with(folder), movability)
886886
}
887-
ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
887+
ty::GeneratorWitness(types, region_outlives) => {
888+
ty::GeneratorWitness(types.fold_with(folder), region_outlives)
889+
}
888890
ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
889891
ty::Projection(ref data) => ty::Projection(data.fold_with(folder)),
890892
ty::UnnormalizedProjection(ref data) => {
@@ -928,7 +930,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
928930
ty::FnPtr(ref f) => f.visit_with(visitor),
929931
ty::Ref(r, ty, _) => r.visit_with(visitor) || ty.visit_with(visitor),
930932
ty::Generator(_did, ref substs, _) => substs.visit_with(visitor),
931-
ty::GeneratorWitness(ref types) => types.visit_with(visitor),
933+
ty::GeneratorWitness(ref types, _) => types.visit_with(visitor),
932934
ty::Closure(_did, ref substs) => substs.visit_with(visitor),
933935
ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => {
934936
data.visit_with(visitor)

src/librustc_middle/ty/sty.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use crate::mir::interpret::{LitToConstInput, Scalar};
1212
use crate::mir::Promoted;
1313
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
1414
use crate::ty::{
15-
self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness,
15+
self, AdtDef, DefIdTree, Discr, RegionOutlivesPredicate, Ty, TyCtxt, TypeFlags, TypeFoldable,
16+
WithConstness,
1617
};
1718
use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS};
1819
use polonius_engine::Atom;
@@ -168,7 +169,7 @@ pub enum TyKind<'tcx> {
168169

169170
/// A type representin the types stored inside a generator.
170171
/// This should only appear in GeneratorInteriors.
171-
GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>),
172+
GeneratorWitness(Binder<&'tcx List<Ty<'tcx>>>, &'tcx List<RegionOutlivesPredicate<'tcx>>),
172173

173174
/// The never type `!`
174175
Never,

src/librustc_middle/ty/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ impl<'tcx> ty::TyS<'tcx> {
734734
| ty::Dynamic(..)
735735
| ty::Foreign(_)
736736
| ty::Generator(..)
737-
| ty::GeneratorWitness(_)
737+
| ty::GeneratorWitness(..)
738738
| ty::Infer(_)
739739
| ty::Opaque(..)
740740
| ty::Param(_)

src/librustc_middle/ty/walk.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
154154
| ty::FnDef(_, substs) => {
155155
stack.extend(substs.iter().copied().rev());
156156
}
157-
ty::GeneratorWitness(ts) => {
157+
ty::GeneratorWitness(ts, _) => {
158158
stack.extend(ts.skip_binder().iter().cloned().rev().map(|ty| ty.into()));
159159
}
160160
ty::FnPtr(sig) => {

src/librustc_mir/interpret/intrinsics/type_name.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
6565
| ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
6666
ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
6767

68-
ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
68+
ty::GeneratorWitness(..) => bug!("type_name: unexpected `GeneratorWitness`"),
6969
}
7070
}
7171

src/librustc_mir/transform/generator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ fn compute_layout<'tcx>(
702702
// MIR types
703703
let allowed_upvars = tcx.erase_regions(upvars);
704704
let allowed = match interior.kind {
705-
ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s),
705+
ty::GeneratorWitness(s, _) => tcx.erase_late_bound_regions(&s),
706706
_ => bug!(),
707707
};
708708

src/librustc_symbol_mangling/v0.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
460460
self = r.print(self)?;
461461
}
462462

463-
ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"),
463+
ty::GeneratorWitness(..) => bug!("symbol_names: unexpected `GeneratorWitness`"),
464464
}
465465

466466
// Only cache types that do not refer to an enclosing

src/librustc_trait_selection/traits/select.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2312,7 +2312,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
23122312
substs.as_generator().upvar_tys().chain(iter::once(witness)).collect()
23132313
}
23142314

2315-
ty::GeneratorWitness(types) => {
2315+
ty::GeneratorWitness(types, _) => {
23162316
// This is sound because no regions in the witness can refer to
23172317
// the binder outside the witness. So we'll effectivly reuse
23182318
// the implicit binder around the witness.

src/librustc_typeck/check/generator_interior.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -188,17 +188,18 @@ pub fn resolve_interior<'a, 'tcx>(
188188

189189
// Extract type components to build the witness type.
190190
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
191-
let _region_constraints = visitor.fcx.with_region_constraints(|constraints_data| {
191+
let region_constraints = visitor.fcx.with_region_constraints(|constraints_data| {
192192
constraints_data
193193
.constraints
194194
.keys()
195195
.map(|constraints| constraints.to_region_outlives_predicate())
196196
.collect::<Vec<_>>()
197197
});
198+
debug!("region outlives inside generator: {:?}", region_constraints);
198199

199-
debug!("region outlives inside generator: {:?}", _region_constraints);
200+
let region_outlives_list = fcx.tcx.mk_predicates(region_constraints.iter());
200201

201-
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list));
202+
let witness = fcx.tcx.mk_generator_witness(ty::Binder::bind(type_list), region_outlives_list);
202203

203204
// Store the generator types and spans into the tables for this generator.
204205
visitor.fcx.inh.tables.borrow_mut().generator_interior_types = type_causes;

0 commit comments

Comments
 (0)