Downsize ty::Expr
This commit is contained in:
parent
27529d5c25
commit
f076dec336
9 changed files with 232 additions and 162 deletions
|
@ -24,7 +24,7 @@ pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
|
||||||
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
|
pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst<TyCtxt<'tcx>>;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
rustc_data_structures::static_assert_size!(ConstKind<'_>, 32);
|
rustc_data_structures::static_assert_size!(ConstKind<'_>, 24);
|
||||||
|
|
||||||
/// Use this rather than `ConstData`, whenever possible.
|
/// Use this rather than `ConstData`, whenever possible.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)]
|
||||||
|
@ -58,7 +58,7 @@ pub struct ConstData<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
rustc_data_structures::static_assert_size!(ConstData<'_>, 40);
|
rustc_data_structures::static_assert_size!(ConstData<'_>, 32);
|
||||||
|
|
||||||
impl<'tcx> Const<'tcx> {
|
impl<'tcx> Const<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::Const;
|
use super::Const;
|
||||||
use crate::mir;
|
use crate::mir;
|
||||||
use crate::ty::abstract_const::CastKind;
|
use crate::ty::abstract_const::CastKind;
|
||||||
use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt};
|
use crate::ty::{self, visit::TypeVisitableExt as _, Ty, TyCtxt};
|
||||||
use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||||
|
|
||||||
#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
|
#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
|
||||||
|
@ -40,14 +40,125 @@ impl<'tcx> ty::UnevaluatedConst<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
|
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
||||||
|
pub enum ExprKind {
|
||||||
|
Binop(mir::BinOp),
|
||||||
|
UnOp(mir::UnOp),
|
||||||
|
FunctionCall,
|
||||||
|
Cast(CastKind),
|
||||||
|
}
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
#[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
|
||||||
pub enum Expr<'tcx> {
|
pub struct Expr<'tcx> {
|
||||||
Binop(mir::BinOp, Const<'tcx>, Const<'tcx>),
|
pub kind: ExprKind,
|
||||||
UnOp(mir::UnOp, Const<'tcx>),
|
args: ty::GenericArgsRef<'tcx>,
|
||||||
FunctionCall(Const<'tcx>, &'tcx List<Const<'tcx>>),
|
}
|
||||||
Cast(CastKind, Const<'tcx>, Ty<'tcx>),
|
impl<'tcx> Expr<'tcx> {
|
||||||
|
pub fn new_binop(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
binop: mir::BinOp,
|
||||||
|
lhs_ty: Ty<'tcx>,
|
||||||
|
rhs_ty: Ty<'tcx>,
|
||||||
|
lhs_ct: Const<'tcx>,
|
||||||
|
rhs_ct: Const<'tcx>,
|
||||||
|
) -> Self {
|
||||||
|
let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
|
||||||
|
[lhs_ty.into(), rhs_ty.into(), lhs_ct.into(), rhs_ct.into()].into_iter(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { kind: ExprKind::Binop(binop), args }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn binop_args(self) -> (Ty<'tcx>, Ty<'tcx>, Const<'tcx>, Const<'tcx>) {
|
||||||
|
assert!(matches!(self.kind, ExprKind::Binop(_)));
|
||||||
|
|
||||||
|
match self.args().as_slice() {
|
||||||
|
[lhs_ty, rhs_ty, lhs_ct, rhs_ct] => (
|
||||||
|
lhs_ty.expect_ty(),
|
||||||
|
rhs_ty.expect_ty(),
|
||||||
|
lhs_ct.expect_const(),
|
||||||
|
rhs_ct.expect_const(),
|
||||||
|
),
|
||||||
|
_ => bug!("Invalid args for `Binop` expr {self:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_unop(tcx: TyCtxt<'tcx>, unop: mir::UnOp, ty: Ty<'tcx>, ct: Const<'tcx>) -> Self {
|
||||||
|
let args =
|
||||||
|
tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>([ty.into(), ct.into()].into_iter());
|
||||||
|
|
||||||
|
Self { kind: ExprKind::UnOp(unop), args }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unop_args(self) -> (Ty<'tcx>, Const<'tcx>) {
|
||||||
|
assert!(matches!(self.kind, ExprKind::UnOp(_)));
|
||||||
|
|
||||||
|
match self.args().as_slice() {
|
||||||
|
[ty, ct] => (ty.expect_ty(), ct.expect_const()),
|
||||||
|
_ => bug!("Invalid args for `UnOp` expr {self:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_call(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
func_ty: Ty<'tcx>,
|
||||||
|
func_expr: Const<'tcx>,
|
||||||
|
arguments: impl Iterator<Item = Const<'tcx>>,
|
||||||
|
) -> Self {
|
||||||
|
let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
|
||||||
|
[func_ty.into(), func_expr.into()].into_iter().chain(arguments.map(|ct| ct.into())),
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { kind: ExprKind::FunctionCall, args }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call_args(self) -> (Ty<'tcx>, Const<'tcx>, impl Iterator<Item = Const<'tcx>>) {
|
||||||
|
assert!(matches!(self.kind, ExprKind::FunctionCall));
|
||||||
|
|
||||||
|
match self.args().as_slice() {
|
||||||
|
[func_ty, func, rest @ ..] => (
|
||||||
|
func_ty.expect_ty(),
|
||||||
|
func.expect_const(),
|
||||||
|
rest.iter().map(|arg| arg.expect_const()),
|
||||||
|
),
|
||||||
|
_ => bug!("Invalid args for `Call` expr {self:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_cast(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
cast: CastKind,
|
||||||
|
value_ty: Ty<'tcx>,
|
||||||
|
value: Const<'tcx>,
|
||||||
|
to_ty: Ty<'tcx>,
|
||||||
|
) -> Self {
|
||||||
|
let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>(
|
||||||
|
[value_ty.into(), value.into(), to_ty.into()].into_iter(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Self { kind: ExprKind::Cast(cast), args }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cast_args(self) -> (Ty<'tcx>, Const<'tcx>, Ty<'tcx>) {
|
||||||
|
assert!(matches!(self.kind, ExprKind::Cast(_)));
|
||||||
|
|
||||||
|
match self.args().as_slice() {
|
||||||
|
[value_ty, value, to_ty] => {
|
||||||
|
(value_ty.expect_ty(), value.expect_const(), to_ty.expect_ty())
|
||||||
|
}
|
||||||
|
_ => bug!("Invalid args for `Cast` expr {self:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(kind: ExprKind, args: ty::GenericArgsRef<'tcx>) -> Self {
|
||||||
|
Self { kind, args }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn args(&self) -> ty::GenericArgsRef<'tcx> {
|
||||||
|
self.args
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
rustc_data_structures::static_assert_size!(Expr<'_>, 24);
|
rustc_data_structures::static_assert_size!(Expr<'_>, 16);
|
||||||
|
|
|
@ -374,26 +374,7 @@ impl FlagComputation {
|
||||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(_) => {}
|
ty::ConstKind::Value(_) => {}
|
||||||
ty::ConstKind::Expr(e) => {
|
ty::ConstKind::Expr(e) => self.add_args(e.args()),
|
||||||
use ty::Expr;
|
|
||||||
match e {
|
|
||||||
Expr::Binop(_, l, r) => {
|
|
||||||
self.add_const(l);
|
|
||||||
self.add_const(r);
|
|
||||||
}
|
|
||||||
Expr::UnOp(_, v) => self.add_const(v),
|
|
||||||
Expr::FunctionCall(f, args) => {
|
|
||||||
self.add_const(f);
|
|
||||||
for arg in args {
|
|
||||||
self.add_const(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expr::Cast(_, c, t) => {
|
|
||||||
self.add_ty(t);
|
|
||||||
self.add_const(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
|
ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ pub use self::closure::{
|
||||||
CAPTURE_STRUCT_LOCAL,
|
CAPTURE_STRUCT_LOCAL,
|
||||||
};
|
};
|
||||||
pub use self::consts::{
|
pub use self::consts::{
|
||||||
Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree,
|
Const, ConstData, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree,
|
||||||
};
|
};
|
||||||
pub use self::context::{
|
pub use self::context::{
|
||||||
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift,
|
||||||
|
|
|
@ -1533,8 +1533,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
print_ty: bool,
|
print_ty: bool,
|
||||||
) -> Result<(), PrintError> {
|
) -> Result<(), PrintError> {
|
||||||
define_scoped_cx!(self);
|
define_scoped_cx!(self);
|
||||||
match expr {
|
match expr.kind {
|
||||||
Expr::Binop(op, c1, c2) => {
|
ty::ExprKind::Binop(op) => {
|
||||||
|
let (_, _, c1, c2) = expr.binop_args();
|
||||||
|
|
||||||
let precedence = |binop: rustc_middle::mir::BinOp| {
|
let precedence = |binop: rustc_middle::mir::BinOp| {
|
||||||
use rustc_ast::util::parser::AssocOp;
|
use rustc_ast::util::parser::AssocOp;
|
||||||
AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence()
|
AssocOp::from_ast_binop(binop.to_hir_binop().into()).precedence()
|
||||||
|
@ -1543,22 +1545,26 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
let formatted_op = op.to_hir_binop().as_str();
|
let formatted_op = op.to_hir_binop().as_str();
|
||||||
let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
|
let (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) {
|
||||||
(
|
(
|
||||||
ty::ConstKind::Expr(Expr::Binop(lhs_op, _, _)),
|
ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
|
||||||
ty::ConstKind::Expr(Expr::Binop(rhs_op, _, _)),
|
ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
|
||||||
) => (precedence(lhs_op) < op_precedence, precedence(rhs_op) < op_precedence),
|
) => (precedence(lhs_op) < op_precedence, precedence(rhs_op) < op_precedence),
|
||||||
(ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), ty::ConstKind::Expr(_)) => {
|
(
|
||||||
(precedence(lhs_op) < op_precedence, true)
|
ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
|
||||||
}
|
ty::ConstKind::Expr(_),
|
||||||
(ty::ConstKind::Expr(_), ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
|
) => (precedence(lhs_op) < op_precedence, true),
|
||||||
(true, precedence(rhs_op) < op_precedence)
|
(
|
||||||
}
|
ty::ConstKind::Expr(_),
|
||||||
|
ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
|
||||||
|
) => (true, precedence(rhs_op) < op_precedence),
|
||||||
(ty::ConstKind::Expr(_), ty::ConstKind::Expr(_)) => (true, true),
|
(ty::ConstKind::Expr(_), ty::ConstKind::Expr(_)) => (true, true),
|
||||||
(ty::ConstKind::Expr(Expr::Binop(lhs_op, ..)), _) => {
|
(
|
||||||
(precedence(lhs_op) < op_precedence, false)
|
ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }),
|
||||||
}
|
_,
|
||||||
(_, ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => {
|
) => (precedence(lhs_op) < op_precedence, false),
|
||||||
(false, precedence(rhs_op) < op_precedence)
|
(
|
||||||
}
|
_,
|
||||||
|
ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }),
|
||||||
|
) => (false, precedence(rhs_op) < op_precedence),
|
||||||
(ty::ConstKind::Expr(_), _) => (true, false),
|
(ty::ConstKind::Expr(_), _) => (true, false),
|
||||||
(_, ty::ConstKind::Expr(_)) => (false, true),
|
(_, ty::ConstKind::Expr(_)) => (false, true),
|
||||||
_ => (false, false),
|
_ => (false, false),
|
||||||
|
@ -1574,7 +1580,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
rhs_parenthesized,
|
rhs_parenthesized,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Expr::UnOp(op, ct) => {
|
ty::ExprKind::UnOp(op) => {
|
||||||
|
let (_, ct) = expr.unop_args();
|
||||||
|
|
||||||
use rustc_middle::mir::UnOp;
|
use rustc_middle::mir::UnOp;
|
||||||
let formatted_op = match op {
|
let formatted_op = match op {
|
||||||
UnOp::Not => "!",
|
UnOp::Not => "!",
|
||||||
|
@ -1583,7 +1591,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
};
|
};
|
||||||
let parenthesized = match ct.kind() {
|
let parenthesized = match ct.kind() {
|
||||||
_ if op == UnOp::PtrMetadata => true,
|
_ if op == UnOp::PtrMetadata => true,
|
||||||
ty::ConstKind::Expr(Expr::UnOp(c_op, ..)) => c_op != op,
|
ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::UnOp(c_op), .. }) => {
|
||||||
|
c_op != op
|
||||||
|
}
|
||||||
ty::ConstKind::Expr(_) => true,
|
ty::ConstKind::Expr(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
@ -1593,61 +1603,37 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||||
parenthesized,
|
parenthesized,
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
Expr::FunctionCall(fn_def, fn_args) => {
|
ty::ExprKind::FunctionCall => {
|
||||||
use ty::TyKind;
|
let (_, fn_def, fn_args) = expr.call_args();
|
||||||
match fn_def.ty().kind() {
|
|
||||||
TyKind::FnDef(def_id, gen_args) => {
|
|
||||||
p!(print_value_path(*def_id, gen_args), "(");
|
|
||||||
if print_ty {
|
|
||||||
let tcx = self.tcx();
|
|
||||||
let sig = tcx.fn_sig(def_id).instantiate(tcx, gen_args).skip_binder();
|
|
||||||
|
|
||||||
let mut args_with_ty = fn_args.iter().map(|ct| (ct, ct.ty()));
|
write!(self, "(")?;
|
||||||
let output_ty = sig.output();
|
self.pretty_print_const(fn_def, print_ty)?;
|
||||||
|
p!(")(", comma_sep(fn_args), ")");
|
||||||
if let Some((ct, ty)) = args_with_ty.next() {
|
|
||||||
self.typed_value(
|
|
||||||
|this| this.pretty_print_const(ct, print_ty),
|
|
||||||
|this| this.pretty_print_type(ty),
|
|
||||||
": ",
|
|
||||||
)?;
|
|
||||||
for (ct, ty) in args_with_ty {
|
|
||||||
p!(", ");
|
|
||||||
self.typed_value(
|
|
||||||
|this| this.pretty_print_const(ct, print_ty),
|
|
||||||
|this| this.pretty_print_type(ty),
|
|
||||||
": ",
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p!(write(") -> {output_ty}"));
|
|
||||||
} else {
|
|
||||||
p!(comma_sep(fn_args.iter()), ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => bug!("unexpected type of fn def"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Expr::Cast(kind, ct, ty) => {
|
ty::ExprKind::Cast(kind) => {
|
||||||
|
let (_, value, to_ty) = expr.cast_args();
|
||||||
|
|
||||||
use ty::abstract_const::CastKind;
|
use ty::abstract_const::CastKind;
|
||||||
if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) {
|
if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) {
|
||||||
let parenthesized = match ct.kind() {
|
let parenthesized = match value.kind() {
|
||||||
ty::ConstKind::Expr(Expr::Cast(_, _, _)) => false,
|
ty::ConstKind::Expr(ty::Expr {
|
||||||
|
kind: ty::ExprKind::Cast { .. }, ..
|
||||||
|
}) => false,
|
||||||
ty::ConstKind::Expr(_) => true,
|
ty::ConstKind::Expr(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
self.maybe_parenthesized(
|
self.maybe_parenthesized(
|
||||||
|this| {
|
|this| {
|
||||||
this.typed_value(
|
this.typed_value(
|
||||||
|this| this.pretty_print_const(ct, print_ty),
|
|this| this.pretty_print_const(value, print_ty),
|
||||||
|this| this.pretty_print_type(ty),
|
|this| this.pretty_print_type(to_ty),
|
||||||
" as ",
|
" as ",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
parenthesized,
|
parenthesized,
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
self.pretty_print_const(ct, print_ty)?
|
self.pretty_print_const(value, print_ty)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
|
|
||||||
use crate::ty::error::{ExpectedFound, TypeError};
|
use crate::ty::error::{ExpectedFound, TypeError};
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg,
|
self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, GenericArg, GenericArgKind,
|
||||||
GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
|
GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
@ -665,46 +665,18 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
a.ty(),
|
a.ty(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// Before calling relate on exprs, it is necessary to ensure that the nested consts
|
|
||||||
// have identical types.
|
|
||||||
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
|
(ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => {
|
||||||
let r = relation;
|
match (ae.kind, be.kind) {
|
||||||
|
(ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop))
|
||||||
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
|
if a_binop == b_binop => {}
|
||||||
// exprs? Should we care about that?
|
(ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {}
|
||||||
// FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
|
(ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {}
|
||||||
// ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
|
(ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {}
|
||||||
// of as being generic over the argument types, however this is implicit so these types don't get
|
|
||||||
// related when we relate the args of the item this const arg is for.
|
|
||||||
let expr = match (ae, be) {
|
|
||||||
(Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
|
|
||||||
r.relate(al.ty(), bl.ty())?;
|
|
||||||
r.relate(ar.ty(), br.ty())?;
|
|
||||||
Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
|
|
||||||
}
|
|
||||||
(Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
|
|
||||||
r.relate(av.ty(), bv.ty())?;
|
|
||||||
Expr::UnOp(a_op, r.consts(av, bv)?)
|
|
||||||
}
|
|
||||||
(Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
|
|
||||||
r.relate(av.ty(), bv.ty())?;
|
|
||||||
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
|
|
||||||
}
|
|
||||||
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
|
|
||||||
if aa.len() == ba.len() =>
|
|
||||||
{
|
|
||||||
r.relate(af.ty(), bf.ty())?;
|
|
||||||
let func = r.consts(af, bf)?;
|
|
||||||
let mut related_args = Vec::with_capacity(aa.len());
|
|
||||||
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
|
|
||||||
related_args.push(r.consts(a_arg, b_arg)?);
|
|
||||||
}
|
|
||||||
let related_args = tcx.mk_const_list(&related_args);
|
|
||||||
Expr::FunctionCall(func, related_args)
|
|
||||||
}
|
|
||||||
_ => return Err(TypeError::ConstMismatch(expected_found(a, b))),
|
_ => return Err(TypeError::ConstMismatch(expected_found(a, b))),
|
||||||
};
|
}
|
||||||
return Ok(ty::Const::new_expr(tcx, expr, a.ty()));
|
|
||||||
|
let args = relation.relate(ae.args(), be.args())?;
|
||||||
|
return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args), a.ty()));
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -147,14 +147,27 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
|
||||||
this: WithInfcx<'_, Infcx, &Self>,
|
this: WithInfcx<'_, Infcx, &Self>,
|
||||||
f: &mut core::fmt::Formatter<'_>,
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
) -> core::fmt::Result {
|
) -> core::fmt::Result {
|
||||||
match this.data {
|
match this.data.kind {
|
||||||
ty::Expr::Binop(op, lhs, rhs) => {
|
ty::ExprKind::Binop(op) => {
|
||||||
write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
|
let (lhs_ty, rhs_ty, lhs, rhs) = this.data.binop_args();
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"({op:?}: ({:?}: {:?}), ({:?}: {:?}))",
|
||||||
|
&this.wrap(lhs),
|
||||||
|
&this.wrap(lhs_ty),
|
||||||
|
&this.wrap(rhs),
|
||||||
|
&this.wrap(rhs_ty),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ty::Expr::UnOp(op, rhs) => write!(f, "({op:?}: {:?})", &this.wrap(rhs)),
|
ty::ExprKind::UnOp(op) => {
|
||||||
ty::Expr::FunctionCall(func, args) => {
|
let (rhs_ty, rhs) = this.data.unop_args();
|
||||||
write!(f, "{:?}(", &this.wrap(func))?;
|
write!(f, "({op:?}: ({:?}: {:?}))", &this.wrap(rhs), &this.wrap(rhs_ty))
|
||||||
for arg in args.as_slice().iter().rev().skip(1).rev() {
|
}
|
||||||
|
ty::ExprKind::FunctionCall => {
|
||||||
|
let (func_ty, func, args) = this.data.call_args();
|
||||||
|
let args = args.collect::<Vec<_>>();
|
||||||
|
write!(f, "({:?}: {:?})(", &this.wrap(func), &this.wrap(func_ty))?;
|
||||||
|
for arg in args.iter().rev().skip(1).rev() {
|
||||||
write!(f, "{:?}, ", &this.wrap(arg))?;
|
write!(f, "{:?}, ", &this.wrap(arg))?;
|
||||||
}
|
}
|
||||||
if let Some(arg) = args.last() {
|
if let Some(arg) = args.last() {
|
||||||
|
@ -163,8 +176,15 @@ impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
|
||||||
|
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
ty::Expr::Cast(cast_kind, lhs, rhs) => {
|
ty::ExprKind::Cast(kind) => {
|
||||||
write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
|
let (value_ty, value, to_ty) = this.data.cast_args();
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"({kind:?}: ({:?}: {:?}), {:?})",
|
||||||
|
&this.wrap(value),
|
||||||
|
&this.wrap(value_ty),
|
||||||
|
&this.wrap(to_ty)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,24 +222,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
|
||||||
| ty::ConstKind::Value(_)
|
| ty::ConstKind::Value(_)
|
||||||
| ty::ConstKind::Error(_) => {}
|
| ty::ConstKind::Error(_) => {}
|
||||||
|
|
||||||
ty::ConstKind::Expr(expr) => match expr {
|
ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()),
|
||||||
ty::Expr::UnOp(_, v) => push_inner(stack, v.into()),
|
|
||||||
ty::Expr::Binop(_, l, r) => {
|
|
||||||
push_inner(stack, r.into());
|
|
||||||
push_inner(stack, l.into())
|
|
||||||
}
|
|
||||||
ty::Expr::FunctionCall(func, args) => {
|
|
||||||
for a in args.iter().rev() {
|
|
||||||
push_inner(stack, a.into());
|
|
||||||
}
|
|
||||||
push_inner(stack, func.into());
|
|
||||||
}
|
|
||||||
ty::Expr::Cast(_, c, t) => {
|
|
||||||
push_inner(stack, t.into());
|
|
||||||
push_inner(stack, c.into());
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ty::ConstKind::Unevaluated(ct) => {
|
ty::ConstKind::Unevaluated(ct) => {
|
||||||
stack.extend(ct.args.iter().rev());
|
stack.extend(ct.args.iter().rev());
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,17 +148,24 @@ fn recurse_build<'tcx>(
|
||||||
for &id in args.iter() {
|
for &id in args.iter() {
|
||||||
new_args.push(recurse_build(tcx, body, id, root_span)?);
|
new_args.push(recurse_build(tcx, body, id, root_span)?);
|
||||||
}
|
}
|
||||||
let new_args = tcx.mk_const_list(&new_args);
|
ty::Const::new_expr(
|
||||||
ty::Const::new_expr(tcx, Expr::FunctionCall(fun, new_args), node.ty)
|
tcx,
|
||||||
|
Expr::new_call(tcx, fun.ty(), fun, new_args.into_iter()),
|
||||||
|
node.ty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
|
&ExprKind::Binary { op, lhs, rhs } if check_binop(op) => {
|
||||||
let lhs = recurse_build(tcx, body, lhs, root_span)?;
|
let lhs = recurse_build(tcx, body, lhs, root_span)?;
|
||||||
let rhs = recurse_build(tcx, body, rhs, root_span)?;
|
let rhs = recurse_build(tcx, body, rhs, root_span)?;
|
||||||
ty::Const::new_expr(tcx, Expr::Binop(op, lhs, rhs), node.ty)
|
ty::Const::new_expr(
|
||||||
|
tcx,
|
||||||
|
Expr::new_binop(tcx, op, lhs.ty(), rhs.ty(), lhs, rhs),
|
||||||
|
node.ty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&ExprKind::Unary { op, arg } if check_unop(op) => {
|
&ExprKind::Unary { op, arg } if check_unop(op) => {
|
||||||
let arg = recurse_build(tcx, body, arg, root_span)?;
|
let arg = recurse_build(tcx, body, arg, root_span)?;
|
||||||
ty::Const::new_expr(tcx, Expr::UnOp(op, arg), node.ty)
|
ty::Const::new_expr(tcx, Expr::new_unop(tcx, op, arg.ty(), arg), node.ty)
|
||||||
}
|
}
|
||||||
// This is necessary so that the following compiles:
|
// This is necessary so that the following compiles:
|
||||||
//
|
//
|
||||||
|
@ -178,12 +185,22 @@ fn recurse_build<'tcx>(
|
||||||
// "coercion cast" i.e. using a coercion or is a no-op.
|
// "coercion cast" i.e. using a coercion or is a no-op.
|
||||||
// This is important so that `N as usize as usize` doesn't unify with `N as usize`. (untested)
|
// This is important so that `N as usize as usize` doesn't unify with `N as usize`. (untested)
|
||||||
&ExprKind::Use { source } => {
|
&ExprKind::Use { source } => {
|
||||||
let arg = recurse_build(tcx, body, source, root_span)?;
|
let value_ty = body.exprs[source].ty;
|
||||||
ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty)
|
let value = recurse_build(tcx, body, source, root_span)?;
|
||||||
|
ty::Const::new_expr(
|
||||||
|
tcx,
|
||||||
|
Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty),
|
||||||
|
node.ty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
&ExprKind::Cast { source } => {
|
&ExprKind::Cast { source } => {
|
||||||
let arg = recurse_build(tcx, body, source, root_span)?;
|
let value_ty = body.exprs[source].ty;
|
||||||
ty::Const::new_expr(tcx, Expr::Cast(CastKind::As, arg, node.ty), node.ty)
|
let value = recurse_build(tcx, body, source, root_span)?;
|
||||||
|
ty::Const::new_expr(
|
||||||
|
tcx,
|
||||||
|
Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty),
|
||||||
|
node.ty,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ExprKind::Borrow { arg, .. } => {
|
ExprKind::Borrow { arg, .. } => {
|
||||||
let arg_node = &body.exprs[*arg];
|
let arg_node = &body.exprs[*arg];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue