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