1 use crate::ty
::{self, InferConst, Ty, TypeFlags}
;
2 use crate::ty
::{GenericArg, GenericArgKind}
;
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(binder
: ty
::Binder
<'_
, 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 fn add_flags(&mut self, flags
: TypeFlags
) {
38 self.flags
= self.flags
| flags
;
41 /// indicates that `self` refers to something at binding level `binder`
42 fn add_bound_var(&mut self, binder
: ty
::DebruijnIndex
) {
43 let exclusive_binder
= binder
.shifted_in(1);
44 self.add_exclusive_binder(exclusive_binder
);
47 /// indicates that `self` refers to something *inside* binding
48 /// level `binder` -- not bound by `binder`, but bound by the next
49 /// binder internal to it
50 fn add_exclusive_binder(&mut self, exclusive_binder
: ty
::DebruijnIndex
) {
51 self.outer_exclusive_binder
= self.outer_exclusive_binder
.max(exclusive_binder
);
54 /// Adds the flags/depth from a set of types that appear within the current type, but within a
56 fn bound_computation
<T
, F
>(&mut self, value
: ty
::Binder
<'_
, T
>, f
: F
)
58 F
: FnOnce(&mut Self, T
),
60 let mut computation
= FlagComputation
::new();
62 if !value
.bound_vars().is_empty() {
63 computation
.add_flags(TypeFlags
::HAS_BINDER_VARS
);
66 f(&mut computation
, value
.skip_binder());
68 self.add_flags(computation
.flags
);
70 // The types that contributed to `computation` occurred within
71 // a region binder, so subtract one from the region depth
72 // within when adding the depth to `self`.
73 let outer_exclusive_binder
= computation
.outer_exclusive_binder
;
74 if outer_exclusive_binder
> ty
::INNERMOST
{
75 self.add_exclusive_binder(outer_exclusive_binder
.shifted_out(1));
76 } // otherwise, this binder captures nothing
79 #[allow(rustc::usage_of_ty_tykind)]
80 fn add_kind(&mut self, kind
: &ty
::TyKind
<'_
>) {
89 | &ty
::Foreign(..) => {}
91 &ty
::Error(_
) => self.add_flags(TypeFlags
::HAS_ERROR
),
94 self.add_flags(TypeFlags
::HAS_TY_PARAM
);
95 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
98 ty
::Generator(_
, args
, _
) => {
99 let args
= args
.as_generator();
100 let should_remove_further_specializable
=
101 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
102 self.add_args(args
.parent_args());
103 if should_remove_further_specializable
{
104 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
107 self.add_ty(args
.resume_ty());
108 self.add_ty(args
.return_ty());
109 self.add_ty(args
.witness());
110 self.add_ty(args
.yield_ty());
111 self.add_ty(args
.tupled_upvars_ty());
114 ty
::GeneratorWitness(_
, args
) => {
115 let should_remove_further_specializable
=
116 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
118 if should_remove_further_specializable
{
119 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
121 self.add_flags(TypeFlags
::HAS_TY_GENERATOR
);
124 &ty
::Closure(_
, args
) => {
125 let args
= args
.as_closure();
126 let should_remove_further_specializable
=
127 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
128 self.add_args(args
.parent_args());
129 if should_remove_further_specializable
{
130 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
133 self.add_ty(args
.sig_as_fn_ptr_ty());
134 self.add_ty(args
.kind_ty());
135 self.add_ty(args
.tupled_upvars_ty());
138 &ty
::Bound(debruijn
, _
) => {
139 self.add_bound_var(debruijn
);
140 self.add_flags(TypeFlags
::HAS_TY_LATE_BOUND
);
143 &ty
::Placeholder(..) => {
144 self.add_flags(TypeFlags
::HAS_TY_PLACEHOLDER
);
145 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
148 &ty
::Infer(infer
) => {
149 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
151 ty
::FreshTy(_
) | ty
::FreshIntTy(_
) | ty
::FreshFloatTy(_
) => {
152 self.add_flags(TypeFlags
::HAS_TY_FRESH
)
155 ty
::TyVar(_
) | ty
::IntVar(_
) | ty
::FloatVar(_
) => {
156 self.add_flags(TypeFlags
::HAS_TY_INFER
)
161 &ty
::Adt(_
, args
) => {
165 &ty
::Alias(kind
, data
) => {
166 self.add_flags(match kind
{
167 ty
::Weak
| ty
::Projection
=> TypeFlags
::HAS_TY_PROJECTION
,
168 ty
::Inherent
=> TypeFlags
::HAS_TY_INHERENT
,
169 ty
::Opaque
=> TypeFlags
::HAS_TY_OPAQUE
,
172 self.add_alias_ty(data
);
175 &ty
::Dynamic(obj
, r
, _
) => {
176 for predicate
in obj
.iter() {
177 self.bound_computation(predicate
, |computation
, predicate
| match predicate
{
178 ty
::ExistentialPredicate
::Trait(tr
) => computation
.add_args(tr
.args
),
179 ty
::ExistentialPredicate
::Projection(p
) => {
180 computation
.add_existential_projection(&p
);
182 ty
::ExistentialPredicate
::AutoTrait(_
) => {}
189 &ty
::Array(tt
, len
) => {
194 &ty
::Slice(tt
) => self.add_ty(tt
),
200 &ty
::Ref(r
, ty
, _
) => {
205 &ty
::Tuple(types
) => {
209 &ty
::FnDef(_
, args
) => {
213 &ty
::FnPtr(fn_sig
) => self.bound_computation(fn_sig
, |computation
, fn_sig
| {
214 computation
.add_tys(fn_sig
.inputs());
215 computation
.add_ty(fn_sig
.output());
220 fn add_predicate(&mut self, binder
: ty
::Binder
<'_
, ty
::PredicateKind
<'_
>>) {
221 self.bound_computation(binder
, |computation
, atom
| computation
.add_predicate_atom(atom
));
224 fn add_predicate_atom(&mut self, atom
: ty
::PredicateKind
<'_
>) {
226 ty
::PredicateKind
::Clause(ty
::ClauseKind
::Trait(trait_pred
)) => {
227 self.add_args(trait_pred
.trait_ref
.args
);
229 ty
::PredicateKind
::Clause(ty
::ClauseKind
::RegionOutlives(ty
::OutlivesPredicate(
236 ty
::PredicateKind
::Clause(ty
::ClauseKind
::TypeOutlives(ty
::OutlivesPredicate(
241 self.add_region(region
);
243 ty
::PredicateKind
::Clause(ty
::ClauseKind
::ConstArgHasType(ct
, ty
)) => {
247 ty
::PredicateKind
::Subtype(ty
::SubtypePredicate { a_is_expected: _, a, b }
) => {
251 ty
::PredicateKind
::Coerce(ty
::CoercePredicate { a, b }
) => {
255 ty
::PredicateKind
::Clause(ty
::ClauseKind
::Projection(ty
::ProjectionPredicate
{
259 self.add_alias_ty(projection_ty
);
262 ty
::PredicateKind
::Clause(ty
::ClauseKind
::WellFormed(arg
)) => {
263 self.add_args(slice
::from_ref(&arg
));
265 ty
::PredicateKind
::ObjectSafe(_def_id
) => {}
266 ty
::PredicateKind
::ClosureKind(_def_id
, args
, _kind
) => {
269 ty
::PredicateKind
::Clause(ty
::ClauseKind
::ConstEvaluatable(uv
)) => {
272 ty
::PredicateKind
::ConstEquate(expected
, found
) => {
273 self.add_const(expected
);
274 self.add_const(found
);
276 ty
::PredicateKind
::Ambiguous
=> {}
277 ty
::PredicateKind
::AliasRelate(t1
, t2
, _
) => {
284 fn add_ty(&mut self, ty
: Ty
<'_
>) {
285 self.add_flags(ty
.flags());
286 self.add_exclusive_binder(ty
.outer_exclusive_binder());
289 fn add_tys(&mut self, tys
: &[Ty
<'_
>]) {
295 fn add_region(&mut self, r
: ty
::Region
<'_
>) {
296 self.add_flags(r
.type_flags());
297 if let ty
::ReLateBound(debruijn
, _
) = *r
{
298 self.add_bound_var(debruijn
);
302 fn add_const(&mut self, c
: ty
::Const
<'_
>) {
305 ty
::ConstKind
::Unevaluated(uv
) => {
306 self.add_args(uv
.args
);
307 self.add_flags(TypeFlags
::HAS_CT_PROJECTION
);
309 ty
::ConstKind
::Infer(infer
) => {
310 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
312 InferConst
::Fresh(_
) => self.add_flags(TypeFlags
::HAS_CT_FRESH
),
313 InferConst
::Var(_
) | InferConst
::EffectVar(_
) => {
314 self.add_flags(TypeFlags
::HAS_CT_INFER
)
318 ty
::ConstKind
::Bound(debruijn
, _
) => {
319 self.add_bound_var(debruijn
);
320 self.add_flags(TypeFlags
::HAS_CT_LATE_BOUND
);
322 ty
::ConstKind
::Param(_
) => {
323 self.add_flags(TypeFlags
::HAS_CT_PARAM
);
324 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
326 ty
::ConstKind
::Placeholder(_
) => {
327 self.add_flags(TypeFlags
::HAS_CT_PLACEHOLDER
);
328 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
330 ty
::ConstKind
::Value(_
) => {}
331 ty
::ConstKind
::Expr(e
) => {
334 Expr
::Binop(_
, l
, r
) => {
338 Expr
::UnOp(_
, v
) => self.add_const(v
),
339 Expr
::FunctionCall(f
, args
) => {
345 Expr
::Cast(_
, c
, t
) => {
351 ty
::ConstKind
::Error(_
) => self.add_flags(TypeFlags
::HAS_ERROR
),
355 fn add_existential_projection(&mut self, projection
: &ty
::ExistentialProjection
<'_
>) {
356 self.add_args(projection
.args
);
357 match projection
.term
.unpack() {
358 ty
::TermKind
::Ty(ty
) => self.add_ty(ty
),
359 ty
::TermKind
::Const(ct
) => self.add_const(ct
),
363 fn add_alias_ty(&mut self, alias_ty
: ty
::AliasTy
<'_
>) {
364 self.add_args(alias_ty
.args
);
367 fn add_args(&mut self, args
: &[GenericArg
<'_
>]) {
369 match kind
.unpack() {
370 GenericArgKind
::Type(ty
) => self.add_ty(ty
),
371 GenericArgKind
::Lifetime(lt
) => self.add_region(lt
),
372 GenericArgKind
::Const(ct
) => self.add_const(ct
),
377 fn add_term(&mut self, term
: ty
::Term
<'_
>) {
378 match term
.unpack() {
379 ty
::TermKind
::Ty(ty
) => self.add_ty(ty
),
380 ty
::TermKind
::Const(ct
) => self.add_const(ct
),