1 use crate::ty
::subst
::{GenericArg, GenericArgKind}
;
2 use crate::ty
::{self, InferConst, Ty, TypeFlags}
;
6 pub struct FlagComputation
{
9 // see `Ty::outer_exclusive_binder` for details
10 pub outer_exclusive_binder
: ty
::DebruijnIndex
,
13 impl FlagComputation
{
14 fn new() -> FlagComputation
{
15 FlagComputation { flags: TypeFlags::empty(), outer_exclusive_binder: ty::INNERMOST }
18 #[allow(rustc::usage_of_ty_tykind)]
19 pub fn for_kind(kind
: &ty
::TyKind
<'_
>) -> FlagComputation
{
20 let mut result
= FlagComputation
::new();
21 result
.add_kind(kind
);
25 pub fn for_predicate
<'tcx
>(binder
: ty
::Binder
<'tcx
, ty
::PredicateKind
<'_
>>) -> FlagComputation
{
26 let mut result
= FlagComputation
::new();
27 result
.add_predicate(binder
);
31 pub fn for_const(c
: ty
::Const
<'_
>) -> TypeFlags
{
32 let mut result
= FlagComputation
::new();
37 pub fn for_unevaluated_const(uv
: ty
::Unevaluated
<'_
>) -> TypeFlags
{
38 let mut result
= FlagComputation
::new();
39 result
.add_unevaluated_const(uv
);
43 fn add_flags(&mut self, flags
: TypeFlags
) {
44 self.flags
= self.flags
| flags
;
47 /// indicates that `self` refers to something at binding level `binder`
48 fn add_bound_var(&mut self, binder
: ty
::DebruijnIndex
) {
49 let exclusive_binder
= binder
.shifted_in(1);
50 self.add_exclusive_binder(exclusive_binder
);
53 /// indicates that `self` refers to something *inside* binding
54 /// level `binder` -- not bound by `binder`, but bound by the next
55 /// binder internal to it
56 fn add_exclusive_binder(&mut self, exclusive_binder
: ty
::DebruijnIndex
) {
57 self.outer_exclusive_binder
= self.outer_exclusive_binder
.max(exclusive_binder
);
60 /// Adds the flags/depth from a set of types that appear within the current type, but within a
62 fn bound_computation
<T
, F
>(&mut self, value
: ty
::Binder
<'_
, T
>, f
: F
)
64 F
: FnOnce(&mut Self, T
),
66 let mut computation
= FlagComputation
::new();
68 if !value
.bound_vars().is_empty() {
69 computation
.flags
= computation
.flags
| TypeFlags
::HAS_RE_LATE_BOUND
;
72 f(&mut computation
, value
.skip_binder());
74 self.add_flags(computation
.flags
);
76 // The types that contributed to `computation` occurred within
77 // a region binder, so subtract one from the region depth
78 // within when adding the depth to `self`.
79 let outer_exclusive_binder
= computation
.outer_exclusive_binder
;
80 if outer_exclusive_binder
> ty
::INNERMOST
{
81 self.add_exclusive_binder(outer_exclusive_binder
.shifted_out(1));
82 } // otherwise, this binder captures nothing
85 #[allow(rustc::usage_of_ty_tykind)]
86 fn add_kind(&mut self, kind
: &ty
::TyKind
<'_
>) {
95 | &ty
::Foreign(..) => {}
97 &ty
::Error(_
) => self.add_flags(TypeFlags
::HAS_ERROR
),
100 self.add_flags(TypeFlags
::HAS_TY_PARAM
);
101 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
104 &ty
::Generator(_
, ref substs
, _
) => {
105 let substs
= substs
.as_generator();
106 let should_remove_further_specializable
=
107 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
108 self.add_substs(substs
.parent_substs());
109 if should_remove_further_specializable
{
110 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
113 self.add_ty(substs
.resume_ty());
114 self.add_ty(substs
.return_ty());
115 self.add_ty(substs
.witness());
116 self.add_ty(substs
.yield_ty());
117 self.add_ty(substs
.tupled_upvars_ty());
120 &ty
::GeneratorWitness(ts
) => {
121 self.bound_computation(ts
, |flags
, ts
| flags
.add_tys(ts
));
124 &ty
::Closure(_
, substs
) => {
125 let substs
= substs
.as_closure();
126 let should_remove_further_specializable
=
127 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
128 self.add_substs(substs
.parent_substs());
129 if should_remove_further_specializable
{
130 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
133 self.add_ty(substs
.sig_as_fn_ptr_ty());
134 self.add_ty(substs
.kind_ty());
135 self.add_ty(substs
.tupled_upvars_ty());
138 &ty
::Bound(debruijn
, _
) => {
139 self.add_bound_var(debruijn
);
142 &ty
::Placeholder(..) => {
143 self.add_flags(TypeFlags
::HAS_TY_PLACEHOLDER
);
144 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
147 &ty
::Infer(infer
) => {
148 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
150 ty
::FreshTy(_
) | ty
::FreshIntTy(_
) | ty
::FreshFloatTy(_
) => {
151 self.add_flags(TypeFlags
::HAS_TY_FRESH
)
154 ty
::TyVar(_
) | ty
::IntVar(_
) | ty
::FloatVar(_
) => {
155 self.add_flags(TypeFlags
::HAS_TY_INFER
)
160 &ty
::Adt(_
, substs
) => {
161 self.add_substs(substs
);
164 &ty
::Projection(data
) => {
165 self.add_flags(TypeFlags
::HAS_TY_PROJECTION
);
166 self.add_projection_ty(data
);
169 &ty
::Opaque(_
, substs
) => {
170 self.add_flags(TypeFlags
::HAS_TY_OPAQUE
);
171 self.add_substs(substs
);
174 &ty
::Dynamic(obj
, r
, _
) => {
175 for predicate
in obj
.iter() {
176 self.bound_computation(predicate
, |computation
, predicate
| match predicate
{
177 ty
::ExistentialPredicate
::Trait(tr
) => computation
.add_substs(tr
.substs
),
178 ty
::ExistentialPredicate
::Projection(p
) => {
179 computation
.add_existential_projection(&p
);
181 ty
::ExistentialPredicate
::AutoTrait(_
) => {}
188 &ty
::Array(tt
, len
) => {
193 &ty
::Slice(tt
) => self.add_ty(tt
),
195 &ty
::RawPtr(ref m
) => {
199 &ty
::Ref(r
, ty
, _
) => {
204 &ty
::Tuple(types
) => {
208 &ty
::FnDef(_
, substs
) => {
209 self.add_substs(substs
);
212 &ty
::FnPtr(fn_sig
) => self.bound_computation(fn_sig
, |computation
, fn_sig
| {
213 computation
.add_tys(fn_sig
.inputs());
214 computation
.add_ty(fn_sig
.output());
219 fn add_predicate(&mut self, binder
: ty
::Binder
<'_
, ty
::PredicateKind
<'_
>>) {
220 self.bound_computation(binder
, |computation
, atom
| computation
.add_predicate_atom(atom
));
223 fn add_predicate_atom(&mut self, atom
: ty
::PredicateKind
<'_
>) {
225 ty
::PredicateKind
::Trait(trait_pred
) => {
226 self.add_substs(trait_pred
.trait_ref
.substs
);
228 ty
::PredicateKind
::RegionOutlives(ty
::OutlivesPredicate(a
, b
)) => {
232 ty
::PredicateKind
::TypeOutlives(ty
::OutlivesPredicate(ty
, region
)) => {
234 self.add_region(region
);
236 ty
::PredicateKind
::Subtype(ty
::SubtypePredicate { a_is_expected: _, a, b }
) => {
240 ty
::PredicateKind
::Coerce(ty
::CoercePredicate { a, b }
) => {
244 ty
::PredicateKind
::Projection(ty
::ProjectionPredicate { projection_ty, term }
) => {
245 self.add_projection_ty(projection_ty
);
246 match term
.unpack() {
247 ty
::TermKind
::Ty(ty
) => self.add_ty(ty
),
248 ty
::TermKind
::Const(c
) => self.add_const(c
),
251 ty
::PredicateKind
::WellFormed(arg
) => {
252 self.add_substs(slice
::from_ref(&arg
));
254 ty
::PredicateKind
::ObjectSafe(_def_id
) => {}
255 ty
::PredicateKind
::ClosureKind(_def_id
, substs
, _kind
) => {
256 self.add_substs(substs
);
258 ty
::PredicateKind
::ConstEvaluatable(uv
) => {
259 self.add_unevaluated_const(uv
);
261 ty
::PredicateKind
::ConstEquate(expected
, found
) => {
262 self.add_const(expected
);
263 self.add_const(found
);
265 ty
::PredicateKind
::TypeWellFormedFromEnv(ty
) => {
271 fn add_ty(&mut self, ty
: Ty
<'_
>) {
272 self.add_flags(ty
.flags());
273 self.add_exclusive_binder(ty
.outer_exclusive_binder());
276 fn add_tys(&mut self, tys
: &[Ty
<'_
>]) {
282 fn add_region(&mut self, r
: ty
::Region
<'_
>) {
283 self.add_flags(r
.type_flags());
284 if let ty
::ReLateBound(debruijn
, _
) = *r
{
285 self.add_bound_var(debruijn
);
289 fn add_const(&mut self, c
: ty
::Const
<'_
>) {
292 ty
::ConstKind
::Unevaluated(unevaluated
) => self.add_unevaluated_const(unevaluated
),
293 ty
::ConstKind
::Infer(infer
) => {
294 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
296 InferConst
::Fresh(_
) => self.add_flags(TypeFlags
::HAS_CT_FRESH
),
297 InferConst
::Var(_
) => self.add_flags(TypeFlags
::HAS_CT_INFER
),
300 ty
::ConstKind
::Bound(debruijn
, _
) => {
301 self.add_bound_var(debruijn
);
303 ty
::ConstKind
::Param(_
) => {
304 self.add_flags(TypeFlags
::HAS_CT_PARAM
);
305 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
307 ty
::ConstKind
::Placeholder(_
) => {
308 self.add_flags(TypeFlags
::HAS_CT_PLACEHOLDER
);
309 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
311 ty
::ConstKind
::Value(_
) => {}
312 ty
::ConstKind
::Error(_
) => self.add_flags(TypeFlags
::HAS_ERROR
),
316 fn add_unevaluated_const
<P
>(&mut self, ct
: ty
::Unevaluated
<'_
, P
>) {
317 self.add_substs(ct
.substs
);
318 self.add_flags(TypeFlags
::HAS_CT_PROJECTION
);
321 fn add_existential_projection(&mut self, projection
: &ty
::ExistentialProjection
<'_
>) {
322 self.add_substs(projection
.substs
);
323 match projection
.term
.unpack() {
324 ty
::TermKind
::Ty(ty
) => self.add_ty(ty
),
325 ty
::TermKind
::Const(ct
) => self.add_const(ct
),
329 fn add_projection_ty(&mut self, projection_ty
: ty
::ProjectionTy
<'_
>) {
330 self.add_substs(projection_ty
.substs
);
333 fn add_substs(&mut self, substs
: &[GenericArg
<'_
>]) {
335 match kind
.unpack() {
336 GenericArgKind
::Type(ty
) => self.add_ty(ty
),
337 GenericArgKind
::Lifetime(lt
) => self.add_region(lt
),
338 GenericArgKind
::Const(ct
) => self.add_const(ct
),