diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 6416bbbe889cb..384a4e7009d84 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -24,7 +24,7 @@ pub type ConstKind<'tcx> = ir::ConstKind>; pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst>; #[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. #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] @@ -58,7 +58,7 @@ pub struct ConstData<'tcx> { } #[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> { #[inline] diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index d7ae050ed4d02..5f29acf5ed274 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,7 +1,7 @@ use super::Const; use crate::mir; 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}; #[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(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] -pub enum Expr<'tcx> { - Binop(mir::BinOp, Const<'tcx>, Const<'tcx>), - UnOp(mir::UnOp, Const<'tcx>), - FunctionCall(Const<'tcx>, &'tcx List>), - Cast(CastKind, Const<'tcx>, Ty<'tcx>), +pub struct Expr<'tcx> { + pub kind: ExprKind, + args: ty::GenericArgsRef<'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>, + ) -> 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>) { + 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")] -rustc_data_structures::static_assert_size!(Expr<'_>, 24); +rustc_data_structures::static_assert_size!(Expr<'_>, 16); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 4de7d532c967c..93a51d3a33408 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -374,26 +374,7 @@ impl FlagComputation { self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Value(_) => {} - ty::ConstKind::Expr(e) => { - 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::Expr(e) => self.add_args(e.args()), ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3fdcb96696022..c6028ef74a9f7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -87,7 +87,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; 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::{ tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index af7784d6b8ed9..1b37078e703d2 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1533,8 +1533,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { print_ty: bool, ) -> Result<(), PrintError> { define_scoped_cx!(self); - match expr { - Expr::Binop(op, c1, c2) => { + match expr.kind { + ty::ExprKind::Binop(op) => { + let (_, _, c1, c2) = expr.binop_args(); + let precedence = |binop: rustc_middle::mir::BinOp| { use rustc_ast::util::parser::AssocOp; 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 (lhs_parenthesized, rhs_parenthesized) = match (c1.kind(), c2.kind()) { ( - ty::ConstKind::Expr(Expr::Binop(lhs_op, _, _)), - ty::ConstKind::Expr(Expr::Binop(rhs_op, _, _)), + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }), + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(rhs_op), .. }), ) => (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::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => { - (true, precedence(rhs_op) < op_precedence) - } + ( + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }), + ty::ConstKind::Expr(_), + ) => (precedence(lhs_op) < op_precedence, true), + ( + 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(Expr::Binop(lhs_op, ..)), _) => { - (precedence(lhs_op) < op_precedence, false) - } - (_, ty::ConstKind::Expr(Expr::Binop(rhs_op, ..))) => { - (false, precedence(rhs_op) < op_precedence) - } + ( + ty::ConstKind::Expr(ty::Expr { kind: ty::ExprKind::Binop(lhs_op), .. }), + _, + ) => (precedence(lhs_op) < op_precedence, false), + ( + _, + 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(_)) => (false, true), _ => (false, false), @@ -1574,7 +1580,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { rhs_parenthesized, )?; } - Expr::UnOp(op, ct) => { + ty::ExprKind::UnOp(op) => { + let (_, ct) = expr.unop_args(); + use rustc_middle::mir::UnOp; let formatted_op = match op { UnOp::Not => "!", @@ -1583,7 +1591,9 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { }; let parenthesized = match ct.kind() { _ 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, _ => false, }; @@ -1593,61 +1603,37 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { parenthesized, )? } - Expr::FunctionCall(fn_def, fn_args) => { - use ty::TyKind; - 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())); - let output_ty = sig.output(); - - 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"), - } + ty::ExprKind::FunctionCall => { + let (_, fn_def, fn_args) = expr.call_args(); + + write!(self, "(")?; + self.pretty_print_const(fn_def, print_ty)?; + p!(")(", comma_sep(fn_args), ")"); } - Expr::Cast(kind, ct, ty) => { + ty::ExprKind::Cast(kind) => { + let (_, value, to_ty) = expr.cast_args(); + use ty::abstract_const::CastKind; if kind == CastKind::As || (kind == CastKind::Use && self.should_print_verbose()) { - let parenthesized = match ct.kind() { - ty::ConstKind::Expr(Expr::Cast(_, _, _)) => false, + let parenthesized = match value.kind() { + ty::ConstKind::Expr(ty::Expr { + kind: ty::ExprKind::Cast { .. }, .. + }) => false, ty::ConstKind::Expr(_) => true, _ => false, }; self.maybe_parenthesized( |this| { this.typed_value( - |this| this.pretty_print_const(ct, print_ty), - |this| this.pretty_print_type(ty), + |this| this.pretty_print_const(value, print_ty), + |this| this.pretty_print_type(to_ty), " as ", ) }, parenthesized, )?; } else { - self.pretty_print_const(ct, print_ty)? + self.pretty_print_const(value, print_ty)? } } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index b417985889094..a621d255a03ec 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -6,8 +6,8 @@ use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::{ - self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg, - GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable, + self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, GenericArg, GenericArgKind, + GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -665,46 +665,18 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( 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)) => { - let r = relation; - - // FIXME(generic_const_exprs): is it possible to relate two consts which are not identical - // exprs? Should we care about that? - // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to - // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought - // 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) - } + match (ae.kind, be.kind) { + (ty::ExprKind::Binop(a_binop), ty::ExprKind::Binop(b_binop)) + if a_binop == b_binop => {} + (ty::ExprKind::UnOp(a_unop), ty::ExprKind::UnOp(b_unop)) if a_unop == b_unop => {} + (ty::ExprKind::FunctionCall, ty::ExprKind::FunctionCall) => {} + (ty::ExprKind::Cast(a_kind), ty::ExprKind::Cast(b_kind)) if a_kind == b_kind => {} _ => 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, }; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 90791bdd20dcd..7a291b4dbff63 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -147,14 +147,27 @@ impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { - match this.data { - ty::Expr::Binop(op, lhs, rhs) => { - write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) + match this.data.kind { + ty::ExprKind::Binop(op) => { + 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::Expr::FunctionCall(func, args) => { - write!(f, "{:?}(", &this.wrap(func))?; - for arg in args.as_slice().iter().rev().skip(1).rev() { + ty::ExprKind::UnOp(op) => { + let (rhs_ty, rhs) = this.data.unop_args(); + write!(f, "({op:?}: ({:?}: {:?}))", &this.wrap(rhs), &this.wrap(rhs_ty)) + } + ty::ExprKind::FunctionCall => { + let (func_ty, func, args) = this.data.call_args(); + let args = args.collect::>(); + write!(f, "({:?}: {:?})(", &this.wrap(func), &this.wrap(func_ty))?; + for arg in args.iter().rev().skip(1).rev() { write!(f, "{:?}, ", &this.wrap(arg))?; } if let Some(arg) = args.last() { @@ -163,8 +176,15 @@ impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { write!(f, ")") } - ty::Expr::Cast(cast_kind, lhs, rhs) => { - write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs)) + ty::ExprKind::Cast(kind) => { + let (value_ty, value, to_ty) = this.data.cast_args(); + write!( + f, + "({kind:?}: ({:?}: {:?}), {:?})", + &this.wrap(value), + &this.wrap(value_ty), + &this.wrap(to_ty) + ) } } } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index a9421aacff839..58f69d772ecb7 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -222,24 +222,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {} - ty::ConstKind::Expr(expr) => match expr { - 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::Expr(expr) => stack.extend(expr.args().iter().rev()), ty::ConstKind::Unevaluated(ct) => { stack.extend(ct.args.iter().rev()); } diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index e9112d232cbd6..8a42298f21646 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -148,17 +148,24 @@ fn recurse_build<'tcx>( for &id in args.iter() { new_args.push(recurse_build(tcx, body, id, root_span)?); } - let new_args = tcx.mk_const_list(&new_args); - ty::Const::new_expr(tcx, Expr::FunctionCall(fun, new_args), node.ty) + ty::Const::new_expr( + tcx, + Expr::new_call(tcx, fun.ty(), fun, new_args.into_iter()), + node.ty, + ) } &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => { let lhs = recurse_build(tcx, body, lhs, 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) => { 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: // @@ -178,12 +185,22 @@ fn recurse_build<'tcx>( // "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) &ExprKind::Use { source } => { - let arg = recurse_build(tcx, body, source, root_span)?; - ty::Const::new_expr(tcx, Expr::Cast(CastKind::Use, arg, node.ty), node.ty) + let value_ty = body.exprs[source].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 } => { - let arg = recurse_build(tcx, body, source, root_span)?; - ty::Const::new_expr(tcx, Expr::Cast(CastKind::As, arg, node.ty), node.ty) + let value_ty = body.exprs[source].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, .. } => { let arg_node = &body.exprs[*arg]; diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs index 8023b998a4099..af17a37bf23a4 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs @@ -15,6 +15,7 @@ where { type AssocTy = Const<{ my_const_fn(U) }>; //~^ ERROR private type + //~| ERROR private type fn assoc_fn() -> Self::AssocTy { Const } diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr index 043fa34d605ab..df0d43bef876c 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -7,6 +7,17 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to 1 previous error +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/eval-privacy.rs:16:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs index cd9cce7ec3e8d..a62feace2da26 100644 --- a/tests/ui/privacy/where-priv-type.rs +++ b/tests/ui/privacy/where-priv-type.rs @@ -74,6 +74,7 @@ where { type AssocTy = Const<{ my_const_fn(U) }>; //~^ ERROR private type + //~| ERROR private type fn assoc_fn() -> Self::AssocTy { Const } diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr index 126330b14a63f..8ea2e17c4361b 100644 --- a/tests/ui/privacy/where-priv-type.stderr +++ b/tests/ui/privacy/where-priv-type.stderr @@ -77,6 +77,17 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to 1 previous error; 5 warnings emitted +error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface + --> $DIR/where-priv-type.rs:75:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ can't leak private type +... +LL | const fn my_const_fn(val: u8) -> u8 { + | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors; 5 warnings emitted For more information about this error, try `rustc --explain E0446`.