1 use crate::ty::subst::{GenericArg, GenericArgKind}; 2 use crate::ty::{self, InferConst, Ty, TypeFlags}; 3 use std::slice; 4 5 #[derive(Debug)] 6 pub struct FlagComputation { 7 pub flags: TypeFlags, 8 9 // see `TyS::outer_exclusive_binder` for details 10 pub outer_exclusive_binder: ty::DebruijnIndex, 11 } 12 13 impl FlagComputation { new() -> FlagComputation14 fn new() -> FlagComputation { 15 FlagComputation { flags: TypeFlags::empty(), outer_exclusive_binder: ty::INNERMOST } 16 } 17 18 #[allow(rustc::usage_of_ty_tykind)] for_kind(kind: &ty::TyKind<'_>) -> FlagComputation19 pub fn for_kind(kind: &ty::TyKind<'_>) -> FlagComputation { 20 let mut result = FlagComputation::new(); 21 result.add_kind(kind); 22 result 23 } 24 for_predicate(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation25 pub fn for_predicate(binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) -> FlagComputation { 26 let mut result = FlagComputation::new(); 27 result.add_predicate(binder); 28 result 29 } 30 for_const(c: &ty::Const<'_>) -> TypeFlags31 pub fn for_const(c: &ty::Const<'_>) -> TypeFlags { 32 let mut result = FlagComputation::new(); 33 result.add_const(c); 34 result.flags 35 } 36 for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags37 pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags { 38 let mut result = FlagComputation::new(); 39 result.add_unevaluated_const(uv); 40 result.flags 41 } 42 add_flags(&mut self, flags: TypeFlags)43 fn add_flags(&mut self, flags: TypeFlags) { 44 self.flags = self.flags | flags; 45 } 46 47 /// indicates that `self` refers to something at binding level `binder` add_bound_var(&mut self, binder: ty::DebruijnIndex)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); 51 } 52 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 add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex)56 fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) { 57 self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder); 58 } 59 60 /// Adds the flags/depth from a set of types that appear within the current type, but within a 61 /// region binder. bound_computation<T, F>(&mut self, value: ty::Binder<'_, T>, f: F) where F: FnOnce(&mut Self, T),62 fn bound_computation<T, F>(&mut self, value: ty::Binder<'_, T>, f: F) 63 where 64 F: FnOnce(&mut Self, T), 65 { 66 let mut computation = FlagComputation::new(); 67 68 if !value.bound_vars().is_empty() { 69 computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND; 70 } 71 72 f(&mut computation, value.skip_binder()); 73 74 self.add_flags(computation.flags); 75 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 83 } 84 85 #[allow(rustc::usage_of_ty_tykind)] add_kind(&mut self, kind: &ty::TyKind<'_>)86 fn add_kind(&mut self, kind: &ty::TyKind<'_>) { 87 match kind { 88 &ty::Bool 89 | &ty::Char 90 | &ty::Int(_) 91 | &ty::Float(_) 92 | &ty::Uint(_) 93 | &ty::Never 94 | &ty::Str 95 | &ty::Foreign(..) => {} 96 97 &ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), 98 99 &ty::Param(_) => { 100 self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM); 101 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); 102 } 103 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; 111 } 112 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()); 118 } 119 120 &ty::GeneratorWitness(ts) => { 121 self.bound_computation(ts, |flags, ts| flags.add_tys(ts)); 122 } 123 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; 131 } 132 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()); 136 } 137 138 &ty::Bound(debruijn, _) => { 139 self.add_bound_var(debruijn); 140 } 141 142 &ty::Placeholder(..) => { 143 self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER); 144 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); 145 } 146 147 &ty::Infer(infer) => { 148 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); 149 match infer { 150 ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { 151 self.add_flags(TypeFlags::HAS_TY_FRESH) 152 } 153 154 ty::TyVar(_) | ty::IntVar(_) | ty::FloatVar(_) => { 155 self.add_flags(TypeFlags::HAS_TY_INFER) 156 } 157 } 158 } 159 160 &ty::Adt(_, substs) => { 161 self.add_substs(substs); 162 } 163 164 &ty::Projection(data) => { 165 self.add_flags(TypeFlags::HAS_TY_PROJECTION); 166 self.add_projection_ty(data); 167 } 168 169 &ty::Opaque(_, substs) => { 170 self.add_flags(TypeFlags::HAS_TY_OPAQUE); 171 self.add_substs(substs); 172 } 173 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); 180 } 181 ty::ExistentialPredicate::AutoTrait(_) => {} 182 }); 183 } 184 185 self.add_region(r); 186 } 187 188 &ty::Array(tt, len) => { 189 self.add_ty(tt); 190 self.add_const(len); 191 } 192 193 &ty::Slice(tt) => self.add_ty(tt), 194 195 &ty::RawPtr(ref m) => { 196 self.add_ty(m.ty); 197 } 198 199 &ty::Ref(r, ty, _) => { 200 self.add_region(r); 201 self.add_ty(ty); 202 } 203 204 &ty::Tuple(ref substs) => { 205 self.add_substs(substs); 206 } 207 208 &ty::FnDef(_, substs) => { 209 self.add_substs(substs); 210 } 211 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()); 215 }), 216 } 217 } 218 add_predicate(&mut self, binder: ty::Binder<'tcx, ty::PredicateKind<'_>>)219 fn add_predicate(&mut self, binder: ty::Binder<'tcx, ty::PredicateKind<'_>>) { 220 self.bound_computation(binder, |computation, atom| computation.add_predicate_atom(atom)); 221 } 222 add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>)223 fn add_predicate_atom(&mut self, atom: ty::PredicateKind<'_>) { 224 match atom { 225 ty::PredicateKind::Trait(trait_pred) => { 226 self.add_substs(trait_pred.trait_ref.substs); 227 } 228 ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => { 229 self.add_region(a); 230 self.add_region(b); 231 } 232 ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, region)) => { 233 self.add_ty(ty); 234 self.add_region(region); 235 } 236 ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => { 237 self.add_ty(a); 238 self.add_ty(b); 239 } 240 ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => { 241 self.add_ty(a); 242 self.add_ty(b); 243 } 244 ty::PredicateKind::Projection(ty::ProjectionPredicate { projection_ty, ty }) => { 245 self.add_projection_ty(projection_ty); 246 self.add_ty(ty); 247 } 248 ty::PredicateKind::WellFormed(arg) => { 249 self.add_substs(slice::from_ref(&arg)); 250 } 251 ty::PredicateKind::ObjectSafe(_def_id) => {} 252 ty::PredicateKind::ClosureKind(_def_id, substs, _kind) => { 253 self.add_substs(substs); 254 } 255 ty::PredicateKind::ConstEvaluatable(uv) => { 256 self.add_unevaluated_const(uv); 257 } 258 ty::PredicateKind::ConstEquate(expected, found) => { 259 self.add_const(expected); 260 self.add_const(found); 261 } 262 ty::PredicateKind::TypeWellFormedFromEnv(ty) => { 263 self.add_ty(ty); 264 } 265 } 266 } 267 add_ty(&mut self, ty: Ty<'_>)268 fn add_ty(&mut self, ty: Ty<'_>) { 269 self.add_flags(ty.flags()); 270 self.add_exclusive_binder(ty.outer_exclusive_binder); 271 } 272 add_tys(&mut self, tys: &[Ty<'_>])273 fn add_tys(&mut self, tys: &[Ty<'_>]) { 274 for &ty in tys { 275 self.add_ty(ty); 276 } 277 } 278 add_region(&mut self, r: ty::Region<'_>)279 fn add_region(&mut self, r: ty::Region<'_>) { 280 self.add_flags(r.type_flags()); 281 if let ty::ReLateBound(debruijn, _) = *r { 282 self.add_bound_var(debruijn); 283 } 284 } 285 add_const(&mut self, c: &ty::Const<'_>)286 fn add_const(&mut self, c: &ty::Const<'_>) { 287 self.add_ty(c.ty); 288 match c.val { 289 ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated), 290 ty::ConstKind::Infer(infer) => { 291 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); 292 match infer { 293 InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), 294 InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER), 295 } 296 } 297 ty::ConstKind::Bound(debruijn, _) => { 298 self.add_bound_var(debruijn); 299 } 300 ty::ConstKind::Param(_) => { 301 self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM); 302 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); 303 } 304 ty::ConstKind::Placeholder(_) => { 305 self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); 306 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); 307 } 308 ty::ConstKind::Value(_) => {} 309 ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), 310 } 311 } 312 add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'tcx, P>)313 fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'tcx, P>) { 314 // The generic arguments of unevaluated consts are a bit special, 315 // see the `rustc-dev-guide` for more information. 316 // 317 // FIXME(@lcnr): Actually add a link here. 318 if let Some(substs) = ct.substs_ { 319 // If they are available, we treat them as ordinary generic arguments. 320 self.add_substs(substs); 321 } else { 322 // Otherwise, we add `HAS_UNKNOWN_DEFAULT_CONST_SUBSTS` to signify 323 // that our const may potentially refer to generic parameters. 324 // 325 // Note that depending on which generic parameters are actually 326 // used in this constant, we may not actually refer to any generic 327 // parameters at all. 328 self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); 329 self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS); 330 } 331 self.add_flags(TypeFlags::HAS_CT_PROJECTION); 332 } 333 add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>)334 fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) { 335 self.add_substs(projection.substs); 336 self.add_ty(projection.ty); 337 } 338 add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>)339 fn add_projection_ty(&mut self, projection_ty: ty::ProjectionTy<'_>) { 340 self.add_substs(projection_ty.substs); 341 } 342 add_substs(&mut self, substs: &[GenericArg<'_>])343 fn add_substs(&mut self, substs: &[GenericArg<'_>]) { 344 for kind in substs { 345 match kind.unpack() { 346 GenericArgKind::Type(ty) => self.add_ty(ty), 347 GenericArgKind::Lifetime(lt) => self.add_region(lt), 348 GenericArgKind::Const(ct) => self.add_const(ct), 349 } 350 } 351 } 352 } 353