rustc_ty_utils/
representability.rs
1use rustc_hir::def::DefKind;
2use rustc_index::bit_set::DenseBitSet;
3use rustc_middle::bug;
4use rustc_middle::query::Providers;
5use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
6use rustc_span::def_id::LocalDefId;
7
8pub(crate) fn provide(providers: &mut Providers) {
9 *providers =
10 Providers { representability, representability_adt_ty, params_in_repr, ..*providers };
11}
12
13macro_rules! rtry {
14 ($e:expr) => {
15 match $e {
16 e @ Representability::Infinite(_) => return e,
17 Representability::Representable => {}
18 }
19 };
20}
21
22fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
23 match tcx.def_kind(def_id) {
24 DefKind::Struct | DefKind::Union | DefKind::Enum => {
25 for variant in tcx.adt_def(def_id).variants() {
26 for field in variant.fields.iter() {
27 rtry!(tcx.representability(field.did.expect_local()));
28 }
29 }
30 Representability::Representable
31 }
32 DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()),
33 def_kind => bug!("unexpected {def_kind:?}"),
34 }
35}
36
37fn representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
38 match *ty.kind() {
39 ty::Adt(..) => tcx.representability_adt_ty(ty),
40 ty::Array(ty, _) => representability_ty(tcx, ty),
42 ty::Tuple(tys) => {
43 for ty in tys {
44 rtry!(representability_ty(tcx, ty));
45 }
46 Representability::Representable
47 }
48 _ => Representability::Representable,
49 }
50}
51
52fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
69 let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") };
70 if let Some(def_id) = adt.did().as_local() {
71 rtry!(tcx.representability(def_id));
72 }
73 let params_in_repr = tcx.params_in_repr(adt.did());
76 for (i, arg) in args.iter().enumerate() {
77 if let ty::GenericArgKind::Type(ty) = arg.unpack() {
78 if params_in_repr.contains(i as u32) {
79 rtry!(representability_ty(tcx, ty));
80 }
81 }
82 }
83 Representability::Representable
84}
85
86fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DenseBitSet<u32> {
87 let adt_def = tcx.adt_def(def_id);
88 let generics = tcx.generics_of(def_id);
89 let mut params_in_repr = DenseBitSet::new_empty(generics.own_params.len());
90 for variant in adt_def.variants() {
91 for field in variant.fields.iter() {
92 params_in_repr_ty(
93 tcx,
94 tcx.type_of(field.did).instantiate_identity(),
95 &mut params_in_repr,
96 );
97 }
98 }
99 params_in_repr
100}
101
102fn params_in_repr_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, params_in_repr: &mut DenseBitSet<u32>) {
103 match *ty.kind() {
104 ty::Adt(adt, args) => {
105 let inner_params_in_repr = tcx.params_in_repr(adt.did());
106 for (i, arg) in args.iter().enumerate() {
107 if let ty::GenericArgKind::Type(ty) = arg.unpack() {
108 if inner_params_in_repr.contains(i as u32) {
109 params_in_repr_ty(tcx, ty, params_in_repr);
110 }
111 }
112 }
113 }
114 ty::Array(ty, _) => params_in_repr_ty(tcx, ty, params_in_repr),
115 ty::Tuple(tys) => tys.iter().for_each(|ty| params_in_repr_ty(tcx, ty, params_in_repr)),
116 ty::Param(param) => {
117 params_in_repr.insert(param.index);
118 }
119 _ => {}
120 }
121}