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 for bv
in value
.bound_vars() {
64 ty
::BoundVariableKind
::Ty(_
) => {
65 computation
.flags
|= TypeFlags
::HAS_TY_LATE_BOUND
;
67 ty
::BoundVariableKind
::Region(_
) => {
68 computation
.flags
|= TypeFlags
::HAS_RE_LATE_BOUND
;
70 ty
::BoundVariableKind
::Const
=> {
71 computation
.flags
|= TypeFlags
::HAS_CT_LATE_BOUND
;
76 f(&mut computation
, value
.skip_binder());
78 self.add_flags(computation
.flags
);
80 // The types that contributed to `computation` occurred within
81 // a region binder, so subtract one from the region depth
82 // within when adding the depth to `self`.
83 let outer_exclusive_binder
= computation
.outer_exclusive_binder
;
84 if outer_exclusive_binder
> ty
::INNERMOST
{
85 self.add_exclusive_binder(outer_exclusive_binder
.shifted_out(1));
86 } // otherwise, this binder captures nothing
89 #[allow(rustc::usage_of_ty_tykind)]
90 fn add_kind(&mut self, kind
: &ty
::TyKind
<'_
>) {
99 | &ty
::Foreign(..) => {}
101 &ty
::Error(_
) => self.add_flags(TypeFlags
::HAS_ERROR
),
104 self.add_flags(TypeFlags
::HAS_TY_PARAM
);
105 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
108 ty
::Generator(_
, args
, _
) => {
109 let args
= args
.as_generator();
110 let should_remove_further_specializable
=
111 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
112 self.add_args(args
.parent_args());
113 if should_remove_further_specializable
{
114 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
117 self.add_ty(args
.resume_ty());
118 self.add_ty(args
.return_ty());
119 self.add_ty(args
.witness());
120 self.add_ty(args
.yield_ty());
121 self.add_ty(args
.tupled_upvars_ty());
124 &ty
::GeneratorWitness(ts
) => {
125 self.bound_computation(ts
, |flags
, ts
| flags
.add_tys(ts
));
128 ty
::GeneratorWitnessMIR(_
, args
) => {
129 let should_remove_further_specializable
=
130 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
132 if should_remove_further_specializable
{
133 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
135 self.add_flags(TypeFlags
::HAS_TY_GENERATOR
);
138 &ty
::Closure(_
, args
) => {
139 let args
= args
.as_closure();
140 let should_remove_further_specializable
=
141 !self.flags
.contains(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
142 self.add_args(args
.parent_args());
143 if should_remove_further_specializable
{
144 self.flags
-= TypeFlags
::STILL_FURTHER_SPECIALIZABLE
;
147 self.add_ty(args
.sig_as_fn_ptr_ty());
148 self.add_ty(args
.kind_ty());
149 self.add_ty(args
.tupled_upvars_ty());
152 &ty
::Bound(debruijn
, _
) => {
153 self.add_bound_var(debruijn
);
154 self.add_flags(TypeFlags
::HAS_TY_LATE_BOUND
);
157 &ty
::Placeholder(..) => {
158 self.add_flags(TypeFlags
::HAS_TY_PLACEHOLDER
);
159 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
162 &ty
::Infer(infer
) => {
163 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
165 ty
::FreshTy(_
) | ty
::FreshIntTy(_
) | ty
::FreshFloatTy(_
) => {
166 self.add_flags(TypeFlags
::HAS_TY_FRESH
)
169 ty
::TyVar(_
) | ty
::IntVar(_
) | ty
::FloatVar(_
) => {
170 self.add_flags(TypeFlags
::HAS_TY_INFER
)
175 &ty
::Adt(_
, args
) => {
179 &ty
::Alias(kind
, data
) => {
180 self.add_flags(match kind
{
181 ty
::Weak
| ty
::Projection
=> TypeFlags
::HAS_TY_PROJECTION
,
182 ty
::Inherent
=> TypeFlags
::HAS_TY_INHERENT
,
183 ty
::Opaque
=> TypeFlags
::HAS_TY_OPAQUE
,
186 self.add_alias_ty(data
);
189 &ty
::Dynamic(obj
, r
, _
) => {
190 for predicate
in obj
.iter() {
191 self.bound_computation(predicate
, |computation
, predicate
| match predicate
{
192 ty
::ExistentialPredicate
::Trait(tr
) => computation
.add_args(tr
.args
),
193 ty
::ExistentialPredicate
::Projection(p
) => {
194 computation
.add_existential_projection(&p
);
196 ty
::ExistentialPredicate
::AutoTrait(_
) => {}
203 &ty
::Array(tt
, len
) => {
208 &ty
::Slice(tt
) => self.add_ty(tt
),
214 &ty
::Ref(r
, ty
, _
) => {
219 &ty
::Tuple(types
) => {
223 &ty
::FnDef(_
, args
) => {
227 &ty
::FnPtr(fn_sig
) => self.bound_computation(fn_sig
, |computation
, fn_sig
| {
228 computation
.add_tys(fn_sig
.inputs());
229 computation
.add_ty(fn_sig
.output());
234 fn add_predicate(&mut self, binder
: ty
::Binder
<'_
, ty
::PredicateKind
<'_
>>) {
235 self.bound_computation(binder
, |computation
, atom
| computation
.add_predicate_atom(atom
));
238 fn add_predicate_atom(&mut self, atom
: ty
::PredicateKind
<'_
>) {
240 ty
::PredicateKind
::Clause(ty
::ClauseKind
::Trait(trait_pred
)) => {
241 self.add_args(trait_pred
.trait_ref
.args
);
243 ty
::PredicateKind
::Clause(ty
::ClauseKind
::RegionOutlives(ty
::OutlivesPredicate(
250 ty
::PredicateKind
::Clause(ty
::ClauseKind
::TypeOutlives(ty
::OutlivesPredicate(
255 self.add_region(region
);
257 ty
::PredicateKind
::Clause(ty
::ClauseKind
::ConstArgHasType(ct
, ty
)) => {
261 ty
::PredicateKind
::Subtype(ty
::SubtypePredicate { a_is_expected: _, a, b }
) => {
265 ty
::PredicateKind
::Coerce(ty
::CoercePredicate { a, b }
) => {
269 ty
::PredicateKind
::Clause(ty
::ClauseKind
::Projection(ty
::ProjectionPredicate
{
273 self.add_alias_ty(projection_ty
);
276 ty
::PredicateKind
::Clause(ty
::ClauseKind
::WellFormed(arg
)) => {
277 self.add_args(slice
::from_ref(&arg
));
279 ty
::PredicateKind
::ObjectSafe(_def_id
) => {}
280 ty
::PredicateKind
::ClosureKind(_def_id
, args
, _kind
) => {
283 ty
::PredicateKind
::Clause(ty
::ClauseKind
::ConstEvaluatable(uv
)) => {
286 ty
::PredicateKind
::ConstEquate(expected
, found
) => {
287 self.add_const(expected
);
288 self.add_const(found
);
290 ty
::PredicateKind
::Ambiguous
=> {}
291 ty
::PredicateKind
::AliasRelate(t1
, t2
, _
) => {
298 fn add_ty(&mut self, ty
: Ty
<'_
>) {
299 self.add_flags(ty
.flags());
300 self.add_exclusive_binder(ty
.outer_exclusive_binder());
303 fn add_tys(&mut self, tys
: &[Ty
<'_
>]) {
309 fn add_region(&mut self, r
: ty
::Region
<'_
>) {
310 self.add_flags(r
.type_flags());
311 if let ty
::ReLateBound(debruijn
, _
) = *r
{
312 self.add_bound_var(debruijn
);
316 fn add_const(&mut self, c
: ty
::Const
<'_
>) {
319 ty
::ConstKind
::Unevaluated(uv
) => {
320 self.add_args(uv
.args
);
321 self.add_flags(TypeFlags
::HAS_CT_PROJECTION
);
323 ty
::ConstKind
::Infer(infer
) => {
324 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
326 InferConst
::Fresh(_
) => self.add_flags(TypeFlags
::HAS_CT_FRESH
),
327 InferConst
::Var(_
) => self.add_flags(TypeFlags
::HAS_CT_INFER
),
330 ty
::ConstKind
::Bound(debruijn
, _
) => {
331 self.add_bound_var(debruijn
);
332 self.add_flags(TypeFlags
::HAS_CT_LATE_BOUND
);
334 ty
::ConstKind
::Param(_
) => {
335 self.add_flags(TypeFlags
::HAS_CT_PARAM
);
336 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
338 ty
::ConstKind
::Placeholder(_
) => {
339 self.add_flags(TypeFlags
::HAS_CT_PLACEHOLDER
);
340 self.add_flags(TypeFlags
::STILL_FURTHER_SPECIALIZABLE
);
342 ty
::ConstKind
::Value(_
) => {}
343 ty
::ConstKind
::Expr(e
) => {
346 Expr
::Binop(_
, l
, r
) => {
350 Expr
::UnOp(_
, v
) => self.add_const(v
),
351 Expr
::FunctionCall(f
, args
) => {
357 Expr
::Cast(_
, c
, t
) => {
363 ty
::ConstKind
::Error(_
) => self.add_flags(TypeFlags
::HAS_ERROR
),
367 fn add_existential_projection(&mut self, projection
: &ty
::ExistentialProjection
<'_
>) {
368 self.add_args(projection
.args
);
369 match projection
.term
.unpack() {
370 ty
::TermKind
::Ty(ty
) => self.add_ty(ty
),
371 ty
::TermKind
::Const(ct
) => self.add_const(ct
),
375 fn add_alias_ty(&mut self, alias_ty
: ty
::AliasTy
<'_
>) {
376 self.add_args(alias_ty
.args
);
379 fn add_args(&mut self, args
: &[GenericArg
<'_
>]) {
381 match kind
.unpack() {
382 GenericArgKind
::Type(ty
) => self.add_ty(ty
),
383 GenericArgKind
::Lifetime(lt
) => self.add_region(lt
),
384 GenericArgKind
::Const(ct
) => self.add_const(ct
),
389 fn add_term(&mut self, term
: ty
::Term
<'_
>) {
390 match term
.unpack() {
391 ty
::TermKind
::Ty(ty
) => self.add_ty(ty
),
392 ty
::TermKind
::Const(ct
) => self.add_const(ct
),