1 #![allow(rustc::untranslatable_diagnostic, rustc::diagnostic_outside_of_impl)]
3 use rustc_hir::def::DefKind;
4 use rustc_index::bit_set::BitSet;
5 use rustc_middle::ty::query::Providers;
6 use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
7 use rustc_span::def_id::{DefId, LocalDefId};
9 pub fn provide(providers: &mut Providers) {
11 Providers { representability, representability_adt_ty, params_in_repr, ..*providers };
17 e @ Representability::Infinite => return e,
18 Representability::Representable => {}
23 fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
24 match tcx.def_kind(def_id) {
25 DefKind::Struct | DefKind::Union | DefKind::Enum => {
26 let adt_def = tcx.adt_def(def_id);
27 for variant in adt_def.variants() {
28 for field in variant.fields.iter() {
29 rtry!(tcx.representability(field.did.expect_local()));
32 Representability::Representable
34 DefKind::Field => representability_ty(tcx, tcx.type_of(def_id)),
35 def_kind => bug!("unexpected {def_kind:?}"),
39 fn representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
41 ty::Adt(..) => tcx.representability_adt_ty(ty),
42 // FIXME(#11924) allow zero-length arrays?
43 ty::Array(ty, _) => representability_ty(tcx, ty),
46 rtry!(representability_ty(tcx, ty));
48 Representability::Representable
50 _ => Representability::Representable,
55 The reason for this being a separate query is very subtle:
56 Consider this infinitely sized struct: `struct Foo(Box<Foo>, Bar<Foo>)`:
57 When calling representability(Foo), a query cycle will occur:
59 -> representability_adt_ty(Bar<Foo>)
60 -> representability(Foo)
61 For the diagnostic output (in `Value::from_cycle_error`), we want to detect that
62 the `Foo` in the *second* field of the struct is culpable. This requires
63 traversing the HIR of the struct and calling `params_in_repr(Bar)`. But we can't
64 call params_in_repr for a given type unless it is known to be representable.
65 params_in_repr will cycle/panic on infinitely sized types. Looking at the query
66 cycle above, we know that `Bar` is representable because
67 representability_adt_ty(Bar<..>) is in the cycle and representability(Bar) is
70 fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
71 let ty::Adt(adt, substs) = ty.kind() else { bug!("expected adt") };
72 if let Some(def_id) = adt.did().as_local() {
73 rtry!(tcx.representability(def_id));
75 // At this point, we know that the item of the ADT type is representable;
76 // but the type parameters may cause a cycle with an upstream type
77 let params_in_repr = tcx.params_in_repr(adt.did());
78 for (i, subst) in substs.iter().enumerate() {
79 if let ty::GenericArgKind::Type(ty) = subst.unpack() {
80 if params_in_repr.contains(i as u32) {
81 rtry!(representability_ty(tcx, ty));
85 Representability::Representable
88 fn params_in_repr(tcx: TyCtxt<'_>, def_id: DefId) -> BitSet<u32> {
89 let adt_def = tcx.adt_def(def_id);
90 let generics = tcx.generics_of(def_id);
91 let mut params_in_repr = BitSet::new_empty(generics.params.len());
92 for variant in adt_def.variants() {
93 for field in variant.fields.iter() {
94 params_in_repr_ty(tcx, tcx.type_of(field.did), &mut params_in_repr);
100 fn params_in_repr_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, params_in_repr: &mut BitSet<u32>) {
102 ty::Adt(adt, substs) => {
103 let inner_params_in_repr = tcx.params_in_repr(adt.did());
104 for (i, subst) in substs.iter().enumerate() {
105 if let ty::GenericArgKind::Type(ty) = subst.unpack() {
106 if inner_params_in_repr.contains(i as u32) {
107 params_in_repr_ty(tcx, ty, params_in_repr);
112 ty::Array(ty, _) => params_in_repr_ty(tcx, ty, params_in_repr),
113 ty::Tuple(tys) => tys.iter().for_each(|ty| params_in_repr_ty(tcx, ty, params_in_repr)),
114 ty::Param(param) => {
115 params_in_repr.insert(param.index);