|
1 | 1 | use rustc_middle::ty::{self, TyCtxt};
|
2 | 2 | use rustc_target::abi::VariantIdx;
|
3 | 3 |
|
4 |
| -/// Tries to destructure constants of type Array or Adt into the constants |
| 4 | +use std::iter; |
| 5 | + |
| 6 | +/// Tries to destructure array, ADT or tuple constants into the constants |
5 | 7 | /// of its fields.
|
6 | 8 | pub(crate) fn destructure_const<'tcx>(
|
7 | 9 | tcx: TyCtxt<'tcx>,
|
8 | 10 | const_: ty::Const<'tcx>,
|
9 | 11 | ) -> ty::DestructuredConst<'tcx> {
|
10 |
| - if let ty::ConstKind::Value(valtree) = const_.kind() { |
11 |
| - let branches = match valtree { |
12 |
| - ty::ValTree::Branch(b) => b, |
13 |
| - _ => bug!("cannot destructure constant {:?}", const_), |
14 |
| - }; |
| 12 | + let ty::ConstKind::Value(valtree) = const_.kind() else { |
| 13 | + bug!("cannot destructure constant {:?}", const_) |
| 14 | + }; |
15 | 15 |
|
16 |
| - let (fields, variant) = match const_.ty().kind() { |
17 |
| - ty::Array(inner_ty, _) | ty::Slice(inner_ty) => { |
18 |
| - // construct the consts for the elements of the array/slice |
19 |
| - let field_consts = branches |
20 |
| - .iter() |
21 |
| - .map(|b| { |
22 |
| - tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty }) |
23 |
| - }) |
24 |
| - .collect::<Vec<_>>(); |
25 |
| - debug!(?field_consts); |
| 16 | + let branches = match valtree { |
| 17 | + ty::ValTree::Branch(b) => b, |
| 18 | + _ => bug!("cannot destructure constant {:?}", const_), |
| 19 | + }; |
26 | 20 |
|
27 |
| - (field_consts, None) |
28 |
| - } |
29 |
| - ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"), |
30 |
| - ty::Adt(def, substs) => { |
31 |
| - let variant_idx = if def.is_enum() { |
32 |
| - VariantIdx::from_u32(branches[0].unwrap_leaf().try_to_u32().unwrap()) |
33 |
| - } else { |
34 |
| - VariantIdx::from_u32(0) |
35 |
| - }; |
36 |
| - let fields = &def.variant(variant_idx).fields; |
37 |
| - let mut field_consts = Vec::with_capacity(fields.len()); |
| 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); |
38 | 29 |
|
39 |
| - // Note: First element inValTree corresponds to variant of enum |
40 |
| - let mut valtree_idx = if def.is_enum() { 1 } else { 0 }; |
41 |
| - for field in fields { |
42 |
| - let field_ty = field.ty(tcx, substs); |
43 |
| - let field_valtree = branches[valtree_idx]; // first element of branches is variant |
44 |
| - let field_const = tcx.mk_const(ty::ConstS { |
45 |
| - kind: ty::ConstKind::Value(field_valtree), |
46 |
| - ty: field_ty, |
47 |
| - }); |
48 |
| - field_consts.push(field_const); |
49 |
| - valtree_idx += 1; |
50 |
| - } |
51 |
| - debug!(?field_consts); |
| 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()); |
52 | 42 |
|
53 |
| - (field_consts, Some(variant_idx)) |
| 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); |
54 | 50 | }
|
55 |
| - ty::Tuple(elem_tys) => { |
56 |
| - let fields = elem_tys |
57 |
| - .iter() |
58 |
| - .enumerate() |
59 |
| - .map(|(i, elem_ty)| { |
60 |
| - let elem_valtree = branches[i]; |
61 |
| - tcx.mk_const(ty::ConstS { |
62 |
| - kind: ty::ConstKind::Value(elem_valtree), |
63 |
| - ty: elem_ty, |
64 |
| - }) |
| 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, |
65 | 61 | })
|
66 |
| - .collect::<Vec<_>>(); |
| 62 | + }) |
| 63 | + .collect::<Vec<_>>(); |
67 | 64 |
|
68 |
| - (fields, None) |
69 |
| - } |
70 |
| - _ => bug!("cannot destructure constant {:?}", const_), |
71 |
| - }; |
| 65 | + (fields, None) |
| 66 | + } |
| 67 | + _ => bug!("cannot destructure constant {:?}", const_), |
| 68 | + }; |
72 | 69 |
|
73 |
| - let fields = tcx.arena.alloc_from_iter(fields.into_iter()); |
| 70 | + let fields = tcx.arena.alloc_from_iter(fields.into_iter()); |
74 | 71 |
|
75 |
| - ty::DestructuredConst { variant, fields } |
76 |
| - } else { |
77 |
| - bug!("cannot destructure constant {:?}", const_) |
78 |
| - } |
| 72 | + ty::DestructuredConst { variant, fields } |
79 | 73 | }
|
80 | 74 |
|
81 | 75 | pub fn provide(providers: &mut ty::query::Providers) {
|
82 |
| - *providers = |
83 |
| - ty::query::Providers { destructure_const, ..*providers }; |
| 76 | + *providers = ty::query::Providers { destructure_const, ..*providers }; |
84 | 77 | }
|
0 commit comments