|
1 | 1 | use super::Const;
|
2 | 2 | use crate::mir;
|
3 | 3 | use crate::ty::abstract_const::CastKind;
|
4 |
| -use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt}; |
| 4 | +use crate::ty::{self, visit::TypeVisitableExt as _, Ty, TyCtxt}; |
5 | 5 | use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
6 | 6 |
|
7 | 7 | #[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
|
@@ -40,14 +40,125 @@ impl<'tcx> ty::UnevaluatedConst<'tcx> {
|
40 | 40 | }
|
41 | 41 | }
|
42 | 42 |
|
| 43 | +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| 44 | +#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] |
| 45 | +pub enum ExprKind { |
| 46 | + Binop(mir::BinOp), |
| 47 | + UnOp(mir::UnOp), |
| 48 | + FunctionCall, |
| 49 | + Cast(CastKind), |
| 50 | +} |
43 | 51 | #[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
44 | 52 | #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
45 |
| -pub enum Expr<'tcx> { |
46 |
| - Binop(mir::BinOp, Const<'tcx>, Const<'tcx>), |
47 |
| - UnOp(mir::UnOp, Const<'tcx>), |
48 |
| - FunctionCall(Const<'tcx>, &'tcx List<Const<'tcx>>), |
49 |
| - Cast(CastKind, Const<'tcx>, Ty<'tcx>), |
| 53 | +pub struct Expr<'tcx> { |
| 54 | + pub kind: ExprKind, |
| 55 | + args: ty::GenericArgsRef<'tcx>, |
| 56 | +} |
| 57 | +impl<'tcx> Expr<'tcx> { |
| 58 | + pub fn new_binop( |
| 59 | + tcx: TyCtxt<'tcx>, |
| 60 | + binop: mir::BinOp, |
| 61 | + lhs_ty: Ty<'tcx>, |
| 62 | + rhs_ty: Ty<'tcx>, |
| 63 | + lhs_ct: Const<'tcx>, |
| 64 | + rhs_ct: Const<'tcx>, |
| 65 | + ) -> Self { |
| 66 | + let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>( |
| 67 | + [lhs_ty.into(), rhs_ty.into(), lhs_ct.into(), rhs_ct.into()].into_iter(), |
| 68 | + ); |
| 69 | + |
| 70 | + Self { kind: ExprKind::Binop(binop), args } |
| 71 | + } |
| 72 | + |
| 73 | + pub fn binop_args(self) -> (Ty<'tcx>, Ty<'tcx>, Const<'tcx>, Const<'tcx>) { |
| 74 | + assert!(matches!(self.kind, ExprKind::Binop(_))); |
| 75 | + |
| 76 | + match self.args().as_slice() { |
| 77 | + [lhs_ty, rhs_ty, lhs_ct, rhs_ct] => ( |
| 78 | + lhs_ty.expect_ty(), |
| 79 | + rhs_ty.expect_ty(), |
| 80 | + lhs_ct.expect_const(), |
| 81 | + rhs_ct.expect_const(), |
| 82 | + ), |
| 83 | + _ => bug!("Invalid args for `Binop` expr {self:?}"), |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + pub fn new_unop(tcx: TyCtxt<'tcx>, unop: mir::UnOp, ty: Ty<'tcx>, ct: Const<'tcx>) -> Self { |
| 88 | + let args = |
| 89 | + tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>([ty.into(), ct.into()].into_iter()); |
| 90 | + |
| 91 | + Self { kind: ExprKind::UnOp(unop), args } |
| 92 | + } |
| 93 | + |
| 94 | + pub fn unop_args(self) -> (Ty<'tcx>, Const<'tcx>) { |
| 95 | + assert!(matches!(self.kind, ExprKind::UnOp(_))); |
| 96 | + |
| 97 | + match self.args().as_slice() { |
| 98 | + [ty, ct] => (ty.expect_ty(), ct.expect_const()), |
| 99 | + _ => bug!("Invalid args for `UnOp` expr {self:?}"), |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + pub fn new_call( |
| 104 | + tcx: TyCtxt<'tcx>, |
| 105 | + func_ty: Ty<'tcx>, |
| 106 | + func_expr: Const<'tcx>, |
| 107 | + arguments: impl Iterator<Item = Const<'tcx>>, |
| 108 | + ) -> Self { |
| 109 | + let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>( |
| 110 | + [func_ty.into(), func_expr.into()].into_iter().chain(arguments.map(|ct| ct.into())), |
| 111 | + ); |
| 112 | + |
| 113 | + Self { kind: ExprKind::FunctionCall, args } |
| 114 | + } |
| 115 | + |
| 116 | + pub fn call_args(self) -> (Ty<'tcx>, Const<'tcx>, impl Iterator<Item = Const<'tcx>>) { |
| 117 | + assert!(matches!(self.kind, ExprKind::FunctionCall)); |
| 118 | + |
| 119 | + match self.args().as_slice() { |
| 120 | + [func_ty, func, rest @ ..] => ( |
| 121 | + func_ty.expect_ty(), |
| 122 | + func.expect_const(), |
| 123 | + rest.iter().map(|arg| arg.expect_const()), |
| 124 | + ), |
| 125 | + _ => bug!("Invalid args for `Call` expr {self:?}"), |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + pub fn new_cast( |
| 130 | + tcx: TyCtxt<'tcx>, |
| 131 | + cast: CastKind, |
| 132 | + value_ty: Ty<'tcx>, |
| 133 | + value: Const<'tcx>, |
| 134 | + to_ty: Ty<'tcx>, |
| 135 | + ) -> Self { |
| 136 | + let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>( |
| 137 | + [value_ty.into(), value.into(), to_ty.into()].into_iter(), |
| 138 | + ); |
| 139 | + |
| 140 | + Self { kind: ExprKind::Cast(cast), args } |
| 141 | + } |
| 142 | + |
| 143 | + pub fn cast_args(self) -> (Ty<'tcx>, Const<'tcx>, Ty<'tcx>) { |
| 144 | + assert!(matches!(self.kind, ExprKind::Cast(_))); |
| 145 | + |
| 146 | + match self.args().as_slice() { |
| 147 | + [value_ty, value, to_ty] => { |
| 148 | + (value_ty.expect_ty(), value.expect_const(), to_ty.expect_ty()) |
| 149 | + } |
| 150 | + _ => bug!("Invalid args for `Cast` expr {self:?}"), |
| 151 | + } |
| 152 | + } |
| 153 | + |
| 154 | + pub fn new(kind: ExprKind, args: ty::GenericArgsRef<'tcx>) -> Self { |
| 155 | + Self { kind, args } |
| 156 | + } |
| 157 | + |
| 158 | + pub fn args(&self) -> ty::GenericArgsRef<'tcx> { |
| 159 | + self.args |
| 160 | + } |
50 | 161 | }
|
51 | 162 |
|
52 | 163 | #[cfg(target_pointer_width = "64")]
|
53 |
| -rustc_data_structures::static_assert_size!(Expr<'_>, 24); |
| 164 | +rustc_data_structures::static_assert_size!(Expr<'_>, 16); |
0 commit comments