1 use crate::mir::interpret::ErrorHandled; 2 use crate::ty; 3 use crate::ty::util::{Discr, IntTypeExt}; 4 use rustc_data_structures::captures::Captures; 5 use rustc_data_structures::fingerprint::Fingerprint; 6 use rustc_data_structures::fx::FxHashMap; 7 use rustc_data_structures::intern::Interned; 8 use rustc_data_structures::stable_hasher::HashingControls; 9 use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; 10 use rustc_hir as hir; 11 use rustc_hir::def::{CtorKind, DefKind, Res}; 12 use rustc_hir::def_id::DefId; 13 use rustc_index::{IndexSlice, IndexVec}; 14 use rustc_query_system::ich::StableHashingContext; 15 use rustc_session::DataTypeKind; 16 use rustc_span::symbol::sym; 17 use rustc_target::abi::{ReprOptions, VariantIdx, FIRST_VARIANT}; 18 19 use std::cell::RefCell; 20 use std::cmp::Ordering; 21 use std::hash::{Hash, Hasher}; 22 use std::ops::Range; 23 use std::str; 24 25 use super::{Destructor, FieldDef, GenericPredicates, Ty, TyCtxt, VariantDef, VariantDiscr}; 26 27 bitflags! { 28 #[derive(HashStable, TyEncodable, TyDecodable)] 29 pub struct AdtFlags: u16 { 30 const NO_ADT_FLAGS = 0; 31 /// Indicates whether the ADT is an enum. 32 const IS_ENUM = 1 << 0; 33 /// Indicates whether the ADT is a union. 34 const IS_UNION = 1 << 1; 35 /// Indicates whether the ADT is a struct. 36 const IS_STRUCT = 1 << 2; 37 /// Indicates whether the ADT is a struct and has a constructor. 38 const HAS_CTOR = 1 << 3; 39 /// Indicates whether the type is `PhantomData`. 40 const IS_PHANTOM_DATA = 1 << 4; 41 /// Indicates whether the type has a `#[fundamental]` attribute. 42 const IS_FUNDAMENTAL = 1 << 5; 43 /// Indicates whether the type is `Box`. 44 const IS_BOX = 1 << 6; 45 /// Indicates whether the type is `ManuallyDrop`. 46 const IS_MANUALLY_DROP = 1 << 7; 47 /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`. 48 /// (i.e., this flag is never set unless this ADT is an enum). 49 const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8; 50 /// Indicates whether the type is `UnsafeCell`. 51 const IS_UNSAFE_CELL = 1 << 9; 52 } 53 } 54 55 /// The definition of a user-defined type, e.g., a `struct`, `enum`, or `union`. 56 /// 57 /// These are all interned (by `mk_adt_def`) into the global arena. 58 /// 59 /// The initialism *ADT* stands for an [*algebraic data type (ADT)*][adt]. 60 /// This is slightly wrong because `union`s are not ADTs. 61 /// Moreover, Rust only allows recursive data types through indirection. 62 /// 63 /// [adt]: https://en.wikipedia.org/wiki/Algebraic_data_type 64 /// 65 /// # Recursive types 66 /// 67 /// It may seem impossible to represent recursive types using [`Ty`], 68 /// since [`TyKind::Adt`] includes [`AdtDef`], which includes its fields, 69 /// creating a cycle. However, `AdtDef` does not actually include the *types* 70 /// of its fields; it includes just their [`DefId`]s. 71 /// 72 /// [`TyKind::Adt`]: ty::TyKind::Adt 73 /// 74 /// For example, the following type: 75 /// 76 /// ``` 77 /// struct S { x: Box<S> } 78 /// ``` 79 /// 80 /// is essentially represented with [`Ty`] as the following pseudocode: 81 /// 82 /// ```ignore (illustrative) 83 /// struct S { x } 84 /// ``` 85 /// 86 /// where `x` here represents the `DefId` of `S.x`. Then, the `DefId` 87 /// can be used with [`TyCtxt::type_of()`] to get the type of the field. 88 #[derive(TyEncodable, TyDecodable)] 89 pub struct AdtDefData { 90 /// The `DefId` of the struct, enum or union item. 91 pub did: DefId, 92 /// Variants of the ADT. If this is a struct or union, then there will be a single variant. 93 variants: IndexVec<VariantIdx, VariantDef>, 94 /// Flags of the ADT (e.g., is this a struct? is this non-exhaustive?). 95 flags: AdtFlags, 96 /// Repr options provided by the user. 97 repr: ReprOptions, 98 } 99 100 impl PartialOrd for AdtDefData { partial_cmp(&self, other: &AdtDefData) -> Option<Ordering>101 fn partial_cmp(&self, other: &AdtDefData) -> Option<Ordering> { 102 Some(self.cmp(&other)) 103 } 104 } 105 106 /// There should be only one AdtDef for each `did`, therefore 107 /// it is fine to implement `Ord` only based on `did`. 108 impl Ord for AdtDefData { cmp(&self, other: &AdtDefData) -> Ordering109 fn cmp(&self, other: &AdtDefData) -> Ordering { 110 self.did.cmp(&other.did) 111 } 112 } 113 114 impl PartialEq for AdtDefData { 115 #[inline] eq(&self, other: &Self) -> bool116 fn eq(&self, other: &Self) -> bool { 117 // There should be only one `AdtDefData` for each `def_id`, therefore 118 // it is fine to implement `PartialEq` only based on `def_id`. 119 // 120 // Below, we exhaustively destructure `self` and `other` so that if the 121 // definition of `AdtDefData` changes, a compile-error will be produced, 122 // reminding us to revisit this assumption. 123 124 let Self { did: self_def_id, variants: _, flags: _, repr: _ } = self; 125 let Self { did: other_def_id, variants: _, flags: _, repr: _ } = other; 126 127 let res = self_def_id == other_def_id; 128 129 // Double check that implicit assumption detailed above. 130 if cfg!(debug_assertions) && res { 131 let deep = self.flags == other.flags 132 && self.repr == other.repr 133 && self.variants == other.variants; 134 assert!(deep, "AdtDefData for the same def-id has differing data"); 135 } 136 137 res 138 } 139 } 140 141 impl Eq for AdtDefData {} 142 143 /// There should be only one AdtDef for each `did`, therefore 144 /// it is fine to implement `Hash` only based on `did`. 145 impl Hash for AdtDefData { 146 #[inline] hash<H: Hasher>(&self, s: &mut H)147 fn hash<H: Hasher>(&self, s: &mut H) { 148 self.did.hash(s) 149 } 150 } 151 152 impl<'a> HashStable<StableHashingContext<'a>> for AdtDefData { hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher)153 fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { 154 thread_local! { 155 static CACHE: RefCell<FxHashMap<(usize, HashingControls), Fingerprint>> = Default::default(); 156 } 157 158 let hash: Fingerprint = CACHE.with(|cache| { 159 let addr = self as *const AdtDefData as usize; 160 let hashing_controls = hcx.hashing_controls(); 161 *cache.borrow_mut().entry((addr, hashing_controls)).or_insert_with(|| { 162 let ty::AdtDefData { did, ref variants, ref flags, ref repr } = *self; 163 164 let mut hasher = StableHasher::new(); 165 did.hash_stable(hcx, &mut hasher); 166 variants.hash_stable(hcx, &mut hasher); 167 flags.hash_stable(hcx, &mut hasher); 168 repr.hash_stable(hcx, &mut hasher); 169 170 hasher.finish() 171 }) 172 }); 173 174 hash.hash_stable(hcx, hasher); 175 } 176 } 177 178 #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, HashStable)] 179 #[rustc_pass_by_value] 180 pub struct AdtDef<'tcx>(pub Interned<'tcx, AdtDefData>); 181 182 impl<'tcx> AdtDef<'tcx> { 183 #[inline] did(self) -> DefId184 pub fn did(self) -> DefId { 185 self.0.0.did 186 } 187 188 #[inline] variants(self) -> &'tcx IndexSlice<VariantIdx, VariantDef>189 pub fn variants(self) -> &'tcx IndexSlice<VariantIdx, VariantDef> { 190 &self.0.0.variants 191 } 192 193 #[inline] variant(self, idx: VariantIdx) -> &'tcx VariantDef194 pub fn variant(self, idx: VariantIdx) -> &'tcx VariantDef { 195 &self.0.0.variants[idx] 196 } 197 198 #[inline] flags(self) -> AdtFlags199 pub fn flags(self) -> AdtFlags { 200 self.0.0.flags 201 } 202 203 #[inline] repr(self) -> ReprOptions204 pub fn repr(self) -> ReprOptions { 205 self.0.0.repr 206 } 207 } 208 209 #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)] 210 pub enum AdtKind { 211 Struct, 212 Union, 213 Enum, 214 } 215 216 impl Into<DataTypeKind> for AdtKind { into(self) -> DataTypeKind217 fn into(self) -> DataTypeKind { 218 match self { 219 AdtKind::Struct => DataTypeKind::Struct, 220 AdtKind::Union => DataTypeKind::Union, 221 AdtKind::Enum => DataTypeKind::Enum, 222 } 223 } 224 } 225 226 impl AdtDefData { 227 /// Creates a new `AdtDefData`. new( tcx: TyCtxt<'_>, did: DefId, kind: AdtKind, variants: IndexVec<VariantIdx, VariantDef>, repr: ReprOptions, ) -> Self228 pub(super) fn new( 229 tcx: TyCtxt<'_>, 230 did: DefId, 231 kind: AdtKind, 232 variants: IndexVec<VariantIdx, VariantDef>, 233 repr: ReprOptions, 234 ) -> Self { 235 debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); 236 let mut flags = AdtFlags::NO_ADT_FLAGS; 237 238 if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) { 239 debug!("found non-exhaustive variant list for {:?}", did); 240 flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE; 241 } 242 243 flags |= match kind { 244 AdtKind::Enum => AdtFlags::IS_ENUM, 245 AdtKind::Union => AdtFlags::IS_UNION, 246 AdtKind::Struct => AdtFlags::IS_STRUCT, 247 }; 248 249 if kind == AdtKind::Struct && variants[FIRST_VARIANT].ctor.is_some() { 250 flags |= AdtFlags::HAS_CTOR; 251 } 252 253 if tcx.has_attr(did, sym::fundamental) { 254 flags |= AdtFlags::IS_FUNDAMENTAL; 255 } 256 if Some(did) == tcx.lang_items().phantom_data() { 257 flags |= AdtFlags::IS_PHANTOM_DATA; 258 } 259 if Some(did) == tcx.lang_items().owned_box() { 260 flags |= AdtFlags::IS_BOX; 261 } 262 if Some(did) == tcx.lang_items().manually_drop() { 263 flags |= AdtFlags::IS_MANUALLY_DROP; 264 } 265 if Some(did) == tcx.lang_items().unsafe_cell_type() { 266 flags |= AdtFlags::IS_UNSAFE_CELL; 267 } 268 269 AdtDefData { did, variants, flags, repr } 270 } 271 } 272 273 impl<'tcx> AdtDef<'tcx> { 274 /// Returns `true` if this is a struct. 275 #[inline] is_struct(self) -> bool276 pub fn is_struct(self) -> bool { 277 self.flags().contains(AdtFlags::IS_STRUCT) 278 } 279 280 /// Returns `true` if this is a union. 281 #[inline] is_union(self) -> bool282 pub fn is_union(self) -> bool { 283 self.flags().contains(AdtFlags::IS_UNION) 284 } 285 286 /// Returns `true` if this is an enum. 287 #[inline] is_enum(self) -> bool288 pub fn is_enum(self) -> bool { 289 self.flags().contains(AdtFlags::IS_ENUM) 290 } 291 292 /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`. 293 #[inline] is_variant_list_non_exhaustive(self) -> bool294 pub fn is_variant_list_non_exhaustive(self) -> bool { 295 self.flags().contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) 296 } 297 298 /// Returns the kind of the ADT. 299 #[inline] adt_kind(self) -> AdtKind300 pub fn adt_kind(self) -> AdtKind { 301 if self.is_enum() { 302 AdtKind::Enum 303 } else if self.is_union() { 304 AdtKind::Union 305 } else { 306 AdtKind::Struct 307 } 308 } 309 310 /// Returns a description of this abstract data type. descr(self) -> &'static str311 pub fn descr(self) -> &'static str { 312 match self.adt_kind() { 313 AdtKind::Struct => "struct", 314 AdtKind::Union => "union", 315 AdtKind::Enum => "enum", 316 } 317 } 318 319 /// Returns a description of a variant of this abstract data type. 320 #[inline] variant_descr(self) -> &'static str321 pub fn variant_descr(self) -> &'static str { 322 match self.adt_kind() { 323 AdtKind::Struct => "struct", 324 AdtKind::Union => "union", 325 AdtKind::Enum => "variant", 326 } 327 } 328 329 /// If this function returns `true`, it implies that `is_struct` must return `true`. 330 #[inline] has_ctor(self) -> bool331 pub fn has_ctor(self) -> bool { 332 self.flags().contains(AdtFlags::HAS_CTOR) 333 } 334 335 /// Returns `true` if this type is `#[fundamental]` for the purposes 336 /// of coherence checking. 337 #[inline] is_fundamental(self) -> bool338 pub fn is_fundamental(self) -> bool { 339 self.flags().contains(AdtFlags::IS_FUNDAMENTAL) 340 } 341 342 /// Returns `true` if this is `PhantomData<T>`. 343 #[inline] is_phantom_data(self) -> bool344 pub fn is_phantom_data(self) -> bool { 345 self.flags().contains(AdtFlags::IS_PHANTOM_DATA) 346 } 347 348 /// Returns `true` if this is `Box<T>`. 349 #[inline] is_box(self) -> bool350 pub fn is_box(self) -> bool { 351 self.flags().contains(AdtFlags::IS_BOX) 352 } 353 354 /// Returns `true` if this is `UnsafeCell<T>`. 355 #[inline] is_unsafe_cell(self) -> bool356 pub fn is_unsafe_cell(self) -> bool { 357 self.flags().contains(AdtFlags::IS_UNSAFE_CELL) 358 } 359 360 /// Returns `true` if this is `ManuallyDrop<T>`. 361 #[inline] is_manually_drop(self) -> bool362 pub fn is_manually_drop(self) -> bool { 363 self.flags().contains(AdtFlags::IS_MANUALLY_DROP) 364 } 365 366 /// Returns `true` if this type has a destructor. has_dtor(self, tcx: TyCtxt<'tcx>) -> bool367 pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool { 368 self.destructor(tcx).is_some() 369 } 370 has_non_const_dtor(self, tcx: TyCtxt<'tcx>) -> bool371 pub fn has_non_const_dtor(self, tcx: TyCtxt<'tcx>) -> bool { 372 matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. })) 373 } 374 375 /// Asserts this is a struct or union and returns its unique variant. non_enum_variant(self) -> &'tcx VariantDef376 pub fn non_enum_variant(self) -> &'tcx VariantDef { 377 assert!(self.is_struct() || self.is_union()); 378 &self.variant(FIRST_VARIANT) 379 } 380 381 #[inline] predicates(self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx>382 pub fn predicates(self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> { 383 tcx.predicates_of(self.did()) 384 } 385 386 /// Returns an iterator over all fields contained 387 /// by this ADT. 388 #[inline] all_fields(self) -> impl Iterator<Item = &'tcx FieldDef> + Clone389 pub fn all_fields(self) -> impl Iterator<Item = &'tcx FieldDef> + Clone { 390 self.variants().iter().flat_map(|v| v.fields.iter()) 391 } 392 393 /// Whether the ADT lacks fields. Note that this includes uninhabited enums, 394 /// e.g., `enum Void {}` is considered payload free as well. is_payloadfree(self) -> bool395 pub fn is_payloadfree(self) -> bool { 396 // Treat the ADT as not payload-free if arbitrary_enum_discriminant is used (#88621). 397 // This would disallow the following kind of enum from being casted into integer. 398 // ``` 399 // enum Enum { 400 // Foo() = 1, 401 // Bar{} = 2, 402 // Baz = 3, 403 // } 404 // ``` 405 if self.variants().iter().any(|v| { 406 matches!(v.discr, VariantDiscr::Explicit(_)) && v.ctor_kind() != Some(CtorKind::Const) 407 }) { 408 return false; 409 } 410 self.variants().iter().all(|v| v.fields.is_empty()) 411 } 412 413 /// Return a `VariantDef` given a variant id. variant_with_id(self, vid: DefId) -> &'tcx VariantDef414 pub fn variant_with_id(self, vid: DefId) -> &'tcx VariantDef { 415 self.variants().iter().find(|v| v.def_id == vid).expect("variant_with_id: unknown variant") 416 } 417 418 /// Return a `VariantDef` given a constructor id. variant_with_ctor_id(self, cid: DefId) -> &'tcx VariantDef419 pub fn variant_with_ctor_id(self, cid: DefId) -> &'tcx VariantDef { 420 self.variants() 421 .iter() 422 .find(|v| v.ctor_def_id() == Some(cid)) 423 .expect("variant_with_ctor_id: unknown variant") 424 } 425 426 /// Return the index of `VariantDef` given a variant id. 427 #[inline] variant_index_with_id(self, vid: DefId) -> VariantIdx428 pub fn variant_index_with_id(self, vid: DefId) -> VariantIdx { 429 self.variants() 430 .iter_enumerated() 431 .find(|(_, v)| v.def_id == vid) 432 .expect("variant_index_with_id: unknown variant") 433 .0 434 } 435 436 /// Return the index of `VariantDef` given a constructor id. variant_index_with_ctor_id(self, cid: DefId) -> VariantIdx437 pub fn variant_index_with_ctor_id(self, cid: DefId) -> VariantIdx { 438 self.variants() 439 .iter_enumerated() 440 .find(|(_, v)| v.ctor_def_id() == Some(cid)) 441 .expect("variant_index_with_ctor_id: unknown variant") 442 .0 443 } 444 variant_of_res(self, res: Res) -> &'tcx VariantDef445 pub fn variant_of_res(self, res: Res) -> &'tcx VariantDef { 446 match res { 447 Res::Def(DefKind::Variant, vid) => self.variant_with_id(vid), 448 Res::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid), 449 Res::Def(DefKind::Struct, _) 450 | Res::Def(DefKind::Union, _) 451 | Res::Def(DefKind::TyAlias, _) 452 | Res::Def(DefKind::AssocTy, _) 453 | Res::SelfTyParam { .. } 454 | Res::SelfTyAlias { .. } 455 | Res::SelfCtor(..) => self.non_enum_variant(), 456 _ => bug!("unexpected res {:?} in variant_of_res", res), 457 } 458 } 459 460 #[inline] eval_explicit_discr(self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>>461 pub fn eval_explicit_discr(self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> { 462 assert!(self.is_enum()); 463 let param_env = tcx.param_env(expr_did); 464 let repr_type = self.repr().discr_type(); 465 match tcx.const_eval_poly(expr_did) { 466 Ok(val) => { 467 let ty = repr_type.to_ty(tcx); 468 if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) { 469 trace!("discriminants: {} ({:?})", b, repr_type); 470 Some(Discr { val: b, ty }) 471 } else { 472 info!("invalid enum discriminant: {:#?}", val); 473 tcx.sess.emit_err(crate::error::ConstEvalNonIntError { 474 span: tcx.def_span(expr_did), 475 }); 476 None 477 } 478 } 479 Err(err) => { 480 let msg = match err { 481 ErrorHandled::Reported(_) => "enum discriminant evaluation failed", 482 ErrorHandled::TooGeneric => "enum discriminant depends on generics", 483 }; 484 tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg); 485 None 486 } 487 } 488 } 489 490 #[inline] discriminants( self, tcx: TyCtxt<'tcx>, ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx>491 pub fn discriminants( 492 self, 493 tcx: TyCtxt<'tcx>, 494 ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> { 495 assert!(self.is_enum()); 496 let repr_type = self.repr().discr_type(); 497 let initial = repr_type.initial_discriminant(tcx); 498 let mut prev_discr = None::<Discr<'tcx>>; 499 self.variants().iter_enumerated().map(move |(i, v)| { 500 let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); 501 if let VariantDiscr::Explicit(expr_did) = v.discr { 502 if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) { 503 discr = new_discr; 504 } 505 } 506 prev_discr = Some(discr); 507 508 (i, discr) 509 }) 510 } 511 512 #[inline] variant_range(self) -> Range<VariantIdx>513 pub fn variant_range(self) -> Range<VariantIdx> { 514 FIRST_VARIANT..self.variants().next_index() 515 } 516 517 /// Computes the discriminant value used by a specific variant. 518 /// Unlike `discriminants`, this is (amortized) constant-time, 519 /// only doing at most one query for evaluating an explicit 520 /// discriminant (the last one before the requested variant), 521 /// assuming there are no constant-evaluation errors there. 522 #[inline] discriminant_for_variant( self, tcx: TyCtxt<'tcx>, variant_index: VariantIdx, ) -> Discr<'tcx>523 pub fn discriminant_for_variant( 524 self, 525 tcx: TyCtxt<'tcx>, 526 variant_index: VariantIdx, 527 ) -> Discr<'tcx> { 528 assert!(self.is_enum()); 529 let (val, offset) = self.discriminant_def_for_variant(variant_index); 530 let explicit_value = val 531 .and_then(|expr_did| self.eval_explicit_discr(tcx, expr_did)) 532 .unwrap_or_else(|| self.repr().discr_type().initial_discriminant(tcx)); 533 explicit_value.checked_add(tcx, offset as u128).0 534 } 535 536 /// Yields a `DefId` for the discriminant and an offset to add to it 537 /// Alternatively, if there is no explicit discriminant, returns the 538 /// inferred discriminant directly. discriminant_def_for_variant(self, variant_index: VariantIdx) -> (Option<DefId>, u32)539 pub fn discriminant_def_for_variant(self, variant_index: VariantIdx) -> (Option<DefId>, u32) { 540 assert!(!self.variants().is_empty()); 541 let mut explicit_index = variant_index.as_u32(); 542 let expr_did; 543 loop { 544 match self.variant(VariantIdx::from_u32(explicit_index)).discr { 545 ty::VariantDiscr::Relative(0) => { 546 expr_did = None; 547 break; 548 } 549 ty::VariantDiscr::Relative(distance) => { 550 explicit_index -= distance; 551 } 552 ty::VariantDiscr::Explicit(did) => { 553 expr_did = Some(did); 554 break; 555 } 556 } 557 } 558 (expr_did, variant_index.as_u32() - explicit_index) 559 } 560 destructor(self, tcx: TyCtxt<'tcx>) -> Option<Destructor>561 pub fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<Destructor> { 562 tcx.adt_destructor(self.did()) 563 } 564 565 /// Returns a list of types such that `Self: Sized` if and only 566 /// if that type is `Sized`, or `TyErr` if this type is recursive. 567 /// 568 /// Oddly enough, checking that the sized-constraint is `Sized` is 569 /// actually more expressive than checking all members: 570 /// the `Sized` trait is inductive, so an associated type that references 571 /// `Self` would prevent its containing ADT from being `Sized`. 572 /// 573 /// Due to normalization being eager, this applies even if 574 /// the associated type is behind a pointer (e.g., issue #31299). sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]>575 pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> { 576 ty::EarlyBinder::bind(tcx.adt_sized_constraint(self.did())) 577 } 578 } 579 580 #[derive(Clone, Copy, Debug)] 581 #[derive(HashStable)] 582 pub enum Representability { 583 Representable, 584 Infinite, 585 } 586