about summary refs log tree commit diff
path: root/compiler/rustc_middle
diff options
context:
space:
mode:
authorBoxy <rust@boxyuwu.dev>2024-11-12 02:54:03 +0000
committerBoxy <rust@boxyuwu.dev>2024-11-12 02:54:03 +0000
commitbea0148ac62758a99dcc2ac2cc2efedacb8881bf (patch)
tree1e3cf15272da0fb53f45fc9521b626509467af14 /compiler/rustc_middle
parent81eef2d362a6f03db6f8928f82d94298d31eb81b (diff)
downloadrust-bea0148ac62758a99dcc2ac2cc2efedacb8881bf.tar.gz
rust-bea0148ac62758a99dcc2ac2cc2efedacb8881bf.zip
Consolidate type system const evaluation under `traits::evaluate_const`
mew
Diffstat (limited to 'compiler/rustc_middle')
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs20
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs59
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs36
3 files changed, 12 insertions, 103 deletions
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 1ae0bd6740d..757034fe30a 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -1,17 +1,17 @@
 use std::fmt::{self, Debug, Display, Formatter};
 
-use either::Either;
 use rustc_abi::{HasDataLayout, Size};
 use rustc_hir::def_id::DefId;
 use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 use rustc_session::RemapFileNameExt;
 use rustc_session::config::RemapPathScopeComponents;
 use rustc_span::{DUMMY_SP, Span};
+use rustc_type_ir::visit::TypeVisitableExt;
 
 use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range};
 use crate::mir::{Promoted, pretty_print_const_value};
 use crate::ty::print::{pretty_print_const, with_no_trimmed_paths};
-use crate::ty::{self, GenericArgsRef, ScalarInt, Ty, TyCtxt};
+use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt};
 
 ///////////////////////////////////////////////////////////////////////////
 /// Evaluated Constants
@@ -319,15 +319,13 @@ impl<'tcx> Const<'tcx> {
     ) -> Result<ConstValue<'tcx>, ErrorHandled> {
         match self {
             Const::Ty(_, c) => {
-                // We want to consistently have a "clean" value for type system constants (i.e., no
-                // data hidden in the padding), so we always go through a valtree here.
-                match c.eval_valtree(tcx, param_env, span) {
-                    Ok((ty, val)) => Ok(tcx.valtree_to_const_val((ty, val))),
-                    Err(Either::Left(_bad_ty)) => Err(tcx
-                        .dcx()
-                        .delayed_bug("`mir::Const::eval` called on a non-valtree-compatible type")
-                        .into()),
-                    Err(Either::Right(e)) => Err(e),
+                if c.has_non_region_param() {
+                    return Err(ErrorHandled::TooGeneric(span));
+                }
+
+                match c.kind() {
+                    ConstKind::Value(ty, val) => Ok(tcx.valtree_to_const_val((ty, val))),
+                    _ => Err(tcx.dcx().delayed_bug("Unevaluated `ty::Const` in MIR body").into()),
                 }
             }
             Const::Unevaluated(uneval, _) => {
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 5ab85a69ce6..5689f3d4265 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,4 +1,3 @@
-use either::Either;
 use rustc_data_structures::intern::Interned;
 use rustc_error_messages::MultiSpan;
 use rustc_hir::def::{DefKind, Res};
@@ -9,7 +8,7 @@ use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
 use tracing::{debug, instrument};
 
 use crate::middle::resolve_bound_vars as rbv;
-use crate::mir::interpret::{ErrorHandled, LitToConstInput, Scalar};
+use crate::mir::interpret::{LitToConstInput, Scalar};
 use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
 
 mod int;
@@ -18,7 +17,7 @@ mod valtree;
 
 pub use int::*;
 pub use kind::*;
-use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed};
 pub use valtree::*;
 
 pub type ConstKind<'tcx> = ir::ConstKind<TyCtxt<'tcx>>;
@@ -363,60 +362,6 @@ impl<'tcx> Const<'tcx> {
         Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize))
     }
 
-    /// Returns the evaluated constant as a valtree;
-    /// if that fails due to a valtree-incompatible type, indicate which type that is
-    /// by returning `Err(Left(bad_type))`.
-    #[inline]
-    pub fn eval_valtree(
-        self,
-        tcx: TyCtxt<'tcx>,
-        param_env: ParamEnv<'tcx>,
-        span: Span,
-    ) -> Result<(Ty<'tcx>, ValTree<'tcx>), Either<Ty<'tcx>, ErrorHandled>> {
-        assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}");
-        match self.kind() {
-            ConstKind::Unevaluated(unevaluated) => {
-                // FIXME(eddyb) maybe the `const_eval_*` methods should take
-                // `ty::ParamEnvAnd` instead of having them separate.
-                let (param_env, unevaluated) = unevaluated.prepare_for_eval(tcx, param_env);
-                // try to resolve e.g. associated constants to their definition on an impl, and then
-                // evaluate the const.
-                match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, span) {
-                    Ok(Ok(c)) => {
-                        Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c))
-                    }
-                    Ok(Err(bad_ty)) => Err(Either::Left(bad_ty)),
-                    Err(err) => Err(Either::Right(err)),
-                }
-            }
-            ConstKind::Value(ty, val) => Ok((ty, val)),
-            ConstKind::Error(g) => Err(Either::Right(g.into())),
-            ConstKind::Param(_)
-            | ConstKind::Infer(_)
-            | ConstKind::Bound(_, _)
-            | ConstKind::Placeholder(_)
-            | ConstKind::Expr(_) => Err(Either::Right(ErrorHandled::TooGeneric(span))),
-        }
-    }
-
-    /// Normalizes the constant to a value or an error if possible.
-    #[inline]
-    pub fn normalize_internal(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
-        match self.eval_valtree(tcx, param_env, DUMMY_SP) {
-            Ok((ty, val)) => Self::new_value(tcx, val, ty),
-            Err(Either::Left(_bad_ty)) => {
-                // This can happen when we run on ill-typed code.
-                Self::new_error(
-                    tcx,
-                    tcx.dcx()
-                        .delayed_bug("`ty::Const::eval` called on a non-valtree-compatible type"),
-                )
-            }
-            Err(Either::Right(ErrorHandled::Reported(r, _span))) => Self::new_error(tcx, r.into()),
-            Err(Either::Right(ErrorHandled::TooGeneric(_span))) => self,
-        }
-    }
-
     /// Panics if self.kind != ty::ConstKind::Value
     pub fn to_valtree(self) -> (ty::ValTree<'tcx>, Ty<'tcx>) {
         match self.kind() {
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 91b764ae1d4..b3436550e8e 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,46 +1,12 @@
 use std::assert_matches::assert_matches;
 
-use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, extension};
+use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 
 use super::Const;
 use crate::mir;
 use crate::ty::abstract_const::CastKind;
-use crate::ty::visit::TypeVisitableExt as _;
 use crate::ty::{self, Ty, TyCtxt};
 
-#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)]
-impl<'tcx> ty::UnevaluatedConst<'tcx> {
-    /// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this
-    /// hurts performance.
-    #[inline]
-    fn prepare_for_eval(
-        self,
-        tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> (ty::ParamEnv<'tcx>, Self) {
-        // HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
-        // also does later, but we want to do it before checking for
-        // inference variables.
-        // Note that we erase regions *before* calling `with_reveal_all_normalized`,
-        // so that we don't try to invoke this query with
-        // any region variables.
-
-        // HACK(eddyb) when the query key would contain inference variables,
-        // attempt using identity args and `ParamEnv` instead, that will succeed
-        // when the expression doesn't depend on any parameters.
-        // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that
-        // we can call `infcx.const_eval_resolve` which handles inference variables.
-        if (param_env, self).has_non_region_infer() {
-            (tcx.param_env(self.def), ty::UnevaluatedConst {
-                def: self.def,
-                args: ty::GenericArgs::identity_for_item(tcx, self.def),
-            })
-        } else {
-            (tcx.erase_regions(param_env).with_reveal_all_normalized(tcx), tcx.erase_regions(self))
-        }
-    }
-}
-
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
 #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
 pub enum ExprKind {