]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ty_utils/src/consts.rs
Auto merge of #98827 - aDotInTheVoid:suggest-extern-block, r=nagisa
[rust.git] / compiler / rustc_ty_utils / src / consts.rs
1 use rustc_middle::ty::{self, TyCtxt};
2 use rustc_target::abi::VariantIdx;
3
4 use std::iter;
5
6 /// Destructures array, ADT or tuple constants into the constants
7 /// of their fields.
8 pub(crate) fn destructure_const<'tcx>(
9     tcx: TyCtxt<'tcx>,
10     const_: ty::Const<'tcx>,
11 ) -> ty::DestructuredConst<'tcx> {
12     let ty::ConstKind::Value(valtree) = const_.kind() else {
13         bug!("cannot destructure constant {:?}", const_)
14     };
15
16     let branches = match valtree {
17         ty::ValTree::Branch(b) => b,
18         _ => bug!("cannot destructure constant {:?}", const_),
19     };
20
21     let (fields, variant) = match const_.ty().kind() {
22         ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
23             // construct the consts for the elements of the array/slice
24             let field_consts = branches
25                 .iter()
26                 .map(|b| tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty }))
27                 .collect::<Vec<_>>();
28             debug!(?field_consts);
29
30             (field_consts, None)
31         }
32         ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
33         ty::Adt(def, substs) => {
34             let (variant_idx, branches) = if def.is_enum() {
35                 let (head, rest) = branches.split_first().unwrap();
36                 (VariantIdx::from_u32(head.unwrap_leaf().try_to_u32().unwrap()), rest)
37             } else {
38                 (VariantIdx::from_u32(0), branches)
39             };
40             let fields = &def.variant(variant_idx).fields;
41             let mut field_consts = Vec::with_capacity(fields.len());
42
43             for (field, field_valtree) in iter::zip(fields, branches) {
44                 let field_ty = field.ty(tcx, substs);
45                 let field_const = tcx.mk_const(ty::ConstS {
46                     kind: ty::ConstKind::Value(*field_valtree),
47                     ty: field_ty,
48                 });
49                 field_consts.push(field_const);
50             }
51             debug!(?field_consts);
52
53             (field_consts, Some(variant_idx))
54         }
55         ty::Tuple(elem_tys) => {
56             let fields = iter::zip(*elem_tys, branches)
57                 .map(|(elem_ty, elem_valtree)| {
58                     tcx.mk_const(ty::ConstS {
59                         kind: ty::ConstKind::Value(*elem_valtree),
60                         ty: elem_ty,
61                     })
62                 })
63                 .collect::<Vec<_>>();
64
65             (fields, None)
66         }
67         _ => bug!("cannot destructure constant {:?}", const_),
68     };
69
70     let fields = tcx.arena.alloc_from_iter(fields.into_iter());
71
72     ty::DestructuredConst { variant, fields }
73 }
74
75 pub fn provide(providers: &mut ty::query::Providers) {
76     *providers = ty::query::Providers { destructure_const, ..*providers };
77 }