]> git.lizzy.rs Git - rust.git/commitdiff
implement valtrees as the type-system representation for constant values
authorb-naber <bn263@gmx.de>
Wed, 16 Feb 2022 09:56:01 +0000 (10:56 +0100)
committerb-naber <bn263@gmx.de>
Tue, 14 Jun 2022 14:07:11 +0000 (16:07 +0200)
116 files changed:
compiler/rustc_codegen_cranelift/src/constant.rs
compiler/rustc_codegen_ssa/src/mir/constant.rs
compiler/rustc_const_eval/src/const_eval/eval_queries.rs
compiler/rustc_const_eval/src/const_eval/mod.rs
compiler/rustc_const_eval/src/const_eval/valtrees.rs
compiler/rustc_const_eval/src/interpret/operand.rs
compiler/rustc_const_eval/src/lib.rs
compiler/rustc_const_eval/src/transform/promote_consts.rs
compiler/rustc_infer/src/infer/mod.rs
compiler/rustc_middle/src/mir/interpret/queries.rs
compiler/rustc_middle/src/mir/interpret/value.rs
compiler/rustc_middle/src/mir/mod.rs
compiler/rustc_middle/src/mir/pretty.rs
compiler/rustc_middle/src/mir/query.rs
compiler/rustc_middle/src/mir/terminator.rs
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/traits/chalk.rs
compiler/rustc_middle/src/ty/consts.rs
compiler/rustc_middle/src/ty/consts/kind.rs
compiler/rustc_middle/src/ty/consts/valtree.rs
compiler/rustc_middle/src/ty/context.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_mir_build/src/build/expr/as_constant.rs
compiler/rustc_mir_build/src/build/mod.rs
compiler/rustc_mir_build/src/thir/constant.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
compiler/rustc_mir_build/src/thir/pattern/mod.rs
compiler/rustc_mir_dataflow/src/elaborate_drops.rs
compiler/rustc_mir_transform/src/const_debuginfo.rs
compiler/rustc_mir_transform/src/const_prop.rs
compiler/rustc_mir_transform/src/elaborate_drops.rs
compiler/rustc_mir_transform/src/generator.rs
compiler/rustc_mir_transform/src/instcombine.rs
compiler/rustc_mir_transform/src/lib.rs
compiler/rustc_mir_transform/src/lower_intrinsics.rs
compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
compiler/rustc_mir_transform/src/shim.rs
compiler/rustc_monomorphize/src/collector.rs
compiler/rustc_symbol_mangling/src/legacy.rs
compiler/rustc_symbol_mangling/src/v0.rs
compiler/rustc_trait_selection/src/traits/auto_trait.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/project.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_trait_selection/src/traits/select/mod.rs
compiler/rustc_traits/src/normalize_erasing_regions.rs
compiler/rustc_ty_utils/src/instance.rs
src/librustdoc/clean/utils.rs
src/test/incremental/issue-54242.rs
src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir
src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
src/test/mir-opt/derefer_inline_test.main.Derefer.diff
src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff
src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir
src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir
src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir
src/test/ui/associated-consts/defaults-cyclic-fail.rs
src/test/ui/associated-consts/defaults-cyclic-fail.stderr
src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
src/test/ui/borrowck/issue-81899.rs
src/test/ui/borrowck/issue-81899.stderr
src/test/ui/borrowck/issue-88434-minimal-example.rs
src/test/ui/borrowck/issue-88434-minimal-example.stderr
src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
src/test/ui/const-generics/different_generic_args_array.stderr
src/test/ui/const-generics/issues/issue-83765.stderr
src/test/ui/const-ptr/out_of_bounds_read.stderr
src/test/ui/consts/const-eval/const-eval-query-stack.rs
src/test/ui/consts/const-eval/const-eval-query-stack.stderr
src/test/ui/consts/const-float-bits-reject-conv.rs
src/test/ui/consts/const-float-bits-reject-conv.stderr
src/test/ui/consts/const-integer-bool-ops.rs
src/test/ui/consts/const-integer-bool-ops.stderr
src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
src/test/ui/consts/const-mut-refs/issue-76510.rs
src/test/ui/consts/const-size_of-cycle.stderr
src/test/ui/consts/const-tup-index-span.rs
src/test/ui/consts/const-tup-index-span.stderr
src/test/ui/consts/invalid-union.64bit.stderr
src/test/ui/consts/issue-36163.stderr
src/test/ui/consts/issue-44415.rs
src/test/ui/consts/issue-44415.stderr
src/test/ui/consts/issue-77062-large-zst-array.rs
src/test/ui/issues/issue-17252.stderr
src/test/ui/issues/issue-23302-1.stderr
src/test/ui/issues/issue-23302-2.stderr
src/test/ui/issues/issue-23302-3.stderr
src/test/ui/issues/issue-41394.rs
src/test/ui/issues/issue-41394.stderr
src/test/ui/issues/issue-54954.rs
src/test/ui/issues/issue-54954.stderr
src/test/ui/issues/issue-68010-large-zst-consts.rs
src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs
src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr
src/test/ui/resolve/issue-50599.rs
src/test/ui/resolve/issue-50599.stderr
src/test/ui/type/type-dependent-def-issue-49241.rs
src/test/ui/type/type-dependent-def-issue-49241.stderr
src/tools/clippy/clippy_lints/src/enum_clike.rs
src/tools/clippy/clippy_lints/src/large_const_arrays.rs
src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
src/tools/clippy/clippy_lints/src/non_copy_const.rs
src/tools/clippy/clippy_utils/src/consts.rs

index 3d14a0eca52bb31ce2a620d5c0f3732f058a9b01..ef72e6efb946b3cabe8a9881ea9ab2438018791e 100644 (file)
@@ -127,7 +127,7 @@ pub(crate) fn codegen_constant<'tcx>(
         ConstantKind::Val(val, ty) => return codegen_const_value(fx, val, ty),
     };
     let const_val = match const_.kind() {
-        ConstKind::Value(const_val) => const_val,
+        ConstKind::Value(valtree) => fx.tcx.valtree_to_const_val((const_.ty(), valtree)),
         ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
             if fx.tcx.is_static(def.did) =>
         {
@@ -468,9 +468,10 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
 ) -> Option<ConstValue<'tcx>> {
     match operand {
         Operand::Constant(const_) => match const_.literal {
-            ConstantKind::Ty(const_) => {
-                fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).kind().try_to_value()
-            }
+            ConstantKind::Ty(const_) => fx
+                .monomorphize(const_)
+                .eval_for_mir(fx.tcx, ParamEnv::reveal_all())
+                .try_to_value(fx.tcx),
             ConstantKind::Val(val, _) => Some(val),
         },
         // FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
index 7e0d3f9adaa28f004bd2d83c0550549df6bda55e..9a995fbf65ca25429a2ef91dbdaacf628d04479f 100644 (file)
@@ -38,7 +38,7 @@ pub fn eval_mir_constant(
                     self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered");
                     err
                 }),
-            ty::ConstKind::Value(value) => Ok(value),
+            ty::ConstKind::Value(val) => Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val))),
             err => span_bug!(
                 constant.span,
                 "encountered bad ConstKind after monomorphizing: {:?}",
@@ -58,14 +58,14 @@ pub fn simd_shuffle_indices(
         constant
             .map(|val| {
                 let field_ty = ty.builtin_index().unwrap();
-                let c = ty::Const::from_value(bx.tcx(), val, ty);
+                let c = mir::ConstantKind::from_value(val, ty);
                 let values: Vec<_> = bx
                     .tcx()
-                    .destructure_const(ty::ParamEnv::reveal_all().and(c))
+                    .destructure_mir_constant(ty::ParamEnv::reveal_all(), c)
                     .fields
                     .iter()
                     .map(|field| {
-                        if let Some(prim) = field.kind().try_to_scalar() {
+                        if let Some(prim) = field.try_to_scalar() {
                             let layout = bx.layout_of(field_ty);
                             let Abi::Scalar(scalar) = layout.abi else {
                                 bug!("from_const: invalid ByVal layout: {:#?}", layout);
index 0c20324e4523902ae3fd7df3439950669eee3287..b7e5e7aea49ce5a1cdf544db80be81b02bb79d5e 100644 (file)
@@ -196,7 +196,7 @@ pub(super) fn op_to_const<'tcx>(
 }
 
 #[instrument(skip(tcx), level = "debug")]
-fn turn_into_const_value<'tcx>(
+pub(crate) fn turn_into_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     constant: ConstAlloc<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
@@ -222,6 +222,7 @@ fn turn_into_const_value<'tcx>(
     const_val
 }
 
+#[instrument(skip(tcx), level = "debug")]
 pub fn eval_to_const_value_raw_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
@@ -256,6 +257,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
     tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key))
 }
 
+#[instrument(skip(tcx), level = "debug")]
 pub fn eval_to_allocation_raw_provider<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
index 6ee77db4017ea3626f38ef7f00dc4c3c44c3f4b2..51edf64de802a8c831c508d8881fa1e6af0ea0aa 100644 (file)
@@ -1,12 +1,11 @@
 // Not in interpret to make sure we do not use private implementation details
 
-use std::convert::TryFrom;
-
 use rustc_hir::Mutability;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{source_map::DUMMY_SP, symbol::Symbol};
+use rustc_target::abi::VariantIdx;
 
 use crate::interpret::{
     intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
 pub use machine::*;
 pub(crate) use valtrees::{const_to_valtree_inner, valtree_to_const_value};
 
+pub(crate) enum ValTreeCreationError {
+    NonSupportedType,
+    Other,
+}
+pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
+
 pub(crate) fn const_caller_location(
     tcx: TyCtxt<'_>,
     (file, line, col): (Symbol, u32, u32),
@@ -39,16 +44,6 @@ pub(crate) fn const_caller_location(
     ConstValue::Scalar(Scalar::from_maybe_pointer(loc_place.ptr, &tcx))
 }
 
-// We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes.
-const VALTREE_MAX_NODES: usize = 1000;
-
-pub(crate) enum ValTreeCreationError {
-    NodesOverflow,
-    NonSupportedType,
-    Other,
-}
-pub(crate) type ValTreeCreationResult<'tcx> = Result<ty::ValTree<'tcx>, ValTreeCreationError>;
-
 /// Evaluates a constant and turns it into a type-level constant value.
 pub(crate) fn eval_to_valtree<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -56,6 +51,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
     cid: GlobalId<'tcx>,
 ) -> EvalToValTreeResult<'tcx> {
     let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?;
+
+    // FIXME Need to provide a span to `eval_to_valtree`
     let ecx = mk_eval_cx(
         tcx, DUMMY_SP, param_env,
         // It is absolutely crucial for soundness that
@@ -65,65 +62,89 @@ pub(crate) fn eval_to_valtree<'tcx>(
     let place = ecx.raw_const_to_mplace(const_alloc).unwrap();
     debug!(?place);
 
-    let mut num_nodes = 0;
-    let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes);
+    let valtree_result = const_to_valtree_inner(&ecx, &place);
 
     match valtree_result {
         Ok(valtree) => Ok(Some(valtree)),
-        Err(err) => {
-            let did = cid.instance.def_id();
-            let s = cid.display(tcx);
-            match err {
-                ValTreeCreationError::NodesOverflow => {
-                    let msg = format!("maximum number of nodes exceeded in constant {}", &s);
-                    let mut diag = match tcx.hir().span_if_local(did) {
-                        Some(span) => tcx.sess.struct_span_err(span, &msg),
-                        None => tcx.sess.struct_err(&msg),
-                    };
-                    diag.emit();
-
-                    Ok(None)
-                }
-                ValTreeCreationError::NonSupportedType | ValTreeCreationError::Other => Ok(None),
-            }
-        }
+        Err(_) => Ok(None),
     }
 }
 
-/// This function should never fail for validated constants. However, it is also invoked from the
-/// pretty printer which might attempt to format invalid constants and in that case it might fail.
+/// Tries to destructure constants of type Array or Adt into the constants
+/// of its fields.
 pub(crate) fn try_destructure_const<'tcx>(
     tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    val: ty::Const<'tcx>,
-) -> InterpResult<'tcx, mir::DestructuredConst<'tcx>> {
-    trace!("destructure_const: {:?}", val);
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
-    let op = ecx.const_to_op(val, None)?;
-    // We go to `usize` as we cannot allocate anything bigger anyway.
-    let (field_count, variant, down) = match val.ty().kind() {
-        ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
-        // Checks if we have any variants, to avoid downcasting to a non-existing variant (when
-        // there are no variants `read_discriminant` successfully returns a non-existing variant
-        // index).
-        ty::Adt(def, _) if def.variants().is_empty() => throw_ub!(Unreachable),
-        ty::Adt(def, _) => {
-            let variant = ecx.read_discriminant(&op)?.1;
-            let down = ecx.operand_downcast(&op, variant)?;
-            (def.variant(variant).fields.len(), Some(variant), down)
-        }
-        ty::Tuple(substs) => (substs.len(), None, op),
-        _ => bug!("cannot destructure constant {:?}", val),
-    };
-    let fields = (0..field_count)
-        .map(|i| {
-            let field_op = ecx.operand_field(&down, i)?;
-            let val = op_to_const(&ecx, &field_op);
-            Ok(ty::Const::from_value(tcx, val, field_op.layout.ty))
-        })
-        .collect::<InterpResult<'tcx, Vec<_>>>()?;
-    let fields = tcx.arena.alloc_from_iter(fields);
-    Ok(mir::DestructuredConst { variant, fields })
+    const_: ty::Const<'tcx>,
+) -> Option<mir::DestructuredConst<'tcx>> {
+    if let ty::ConstKind::Value(valtree) = const_.val() {
+        let branches = match valtree {
+            ty::ValTree::Branch(b) => b,
+            _ => return None,
+        };
+
+        let (fields, variant) = match const_.ty().kind() {
+            ty::Array(inner_ty, _) | ty::Slice(inner_ty) => {
+                // construct the consts for the elements of the array/slice
+                let field_consts = branches
+                    .iter()
+                    .map(|b| {
+                        tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(*b), ty: *inner_ty })
+                    })
+                    .collect::<Vec<_>>();
+                debug!(?field_consts);
+
+                (field_consts, None)
+            }
+            ty::Adt(def, _) if def.variants().is_empty() => bug!("unreachable"),
+            ty::Adt(def, substs) => {
+                let variant_idx = if def.is_enum() {
+                    VariantIdx::from_u32(branches[0].unwrap_leaf().try_to_u32().ok()?)
+                } else {
+                    VariantIdx::from_u32(0)
+                };
+                let fields = &def.variant(variant_idx).fields;
+                let mut field_consts = Vec::with_capacity(fields.len());
+
+                // Note: First element inValTree corresponds to variant of enum
+                let mut valtree_idx = if def.is_enum() { 1 } else { 0 };
+                for field in fields {
+                    let field_ty = field.ty(tcx, substs);
+                    let field_valtree = branches[valtree_idx]; // first element of branches is variant
+                    let field_const = tcx.mk_const(ty::ConstS {
+                        kind: ty::ConstKind::Value(field_valtree),
+                        ty: field_ty,
+                    });
+                    field_consts.push(field_const);
+                    valtree_idx += 1;
+                }
+                debug!(?field_consts);
+
+                (field_consts, Some(variant_idx))
+            }
+            ty::Tuple(elem_tys) => {
+                let fields = elem_tys
+                    .iter()
+                    .enumerate()
+                    .map(|(i, elem_ty)| {
+                        let elem_valtree = branches[i];
+                        tcx.mk_const(ty::ConstS {
+                            kind: ty::ConstKind::Value(elem_valtree),
+                            ty: elem_ty,
+                        })
+                    })
+                    .collect::<Vec<_>>();
+
+                (fields, None)
+            }
+            _ => bug!("cannot destructure constant {:?}", const_),
+        };
+
+        let fields = tcx.arena.alloc_from_iter(fields.into_iter());
+
+        Some(mir::DestructuredConst { variant, fields })
+    } else {
+        None
+    }
 }
 
 #[instrument(skip(tcx), level = "debug")]
@@ -143,8 +164,8 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
             throw_ub!(Unreachable)
         }
         ty::Adt(def, _) => {
-            let variant = ecx.read_discriminant(&op).unwrap().1;
-            let down = ecx.operand_downcast(&op, variant).unwrap();
+            let variant = ecx.read_discriminant(&op)?.1;
+            let down = ecx.operand_downcast(&op, variant)?;
             (def.variants()[variant].fields.len(), Some(variant), down)
         }
         ty::Tuple(substs) => (substs.len(), None, op),
@@ -163,43 +184,6 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
     Ok(mir::DestructuredMirConstant { variant, fields })
 }
 
-#[instrument(skip(tcx), level = "debug")]
-pub(crate) fn deref_const<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    val: ty::Const<'tcx>,
-) -> ty::Const<'tcx> {
-    trace!("deref_const: {:?}", val);
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
-    let op = ecx.const_to_op(val, None).unwrap();
-    let mplace = ecx.deref_operand(&op).unwrap();
-    if let Some(alloc_id) = mplace.ptr.provenance {
-        assert_eq!(
-            tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().inner().mutability,
-            Mutability::Not,
-            "deref_const cannot be used with mutable allocations as \
-            that could allow pattern matching to observe mutable statics",
-        );
-    }
-
-    let ty = match mplace.meta {
-        MemPlaceMeta::None => mplace.layout.ty,
-        MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
-        // In case of unsized types, figure out the real type behind.
-        MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
-            ty::Str => bug!("there's no sized equivalent of a `str`"),
-            ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
-            _ => bug!(
-                "type {} should not have metadata, but had {:?}",
-                mplace.layout.ty,
-                mplace.meta
-            ),
-        },
-    };
-
-    tcx.mk_const(ty::ConstS { kind: ty::ConstKind::Value(op_to_const(&ecx, &mplace.into())), ty })
-}
-
 #[instrument(skip(tcx), level = "debug")]
 pub(crate) fn deref_mir_constant<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -211,16 +195,16 @@ pub(crate) fn deref_mir_constant<'tcx>(
     let mplace = ecx.deref_operand(&op).unwrap();
     if let Some(alloc_id) = mplace.ptr.provenance {
         assert_eq!(
-            tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().0.0.mutability,
+            tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().0 .0.mutability,
             Mutability::Not,
-            "deref_const cannot be used with mutable allocations as \
+            "deref_mir_constant cannot be used with mutable allocations as \
             that could allow pattern matching to observe mutable statics",
         );
     }
 
     let ty = match mplace.meta {
         MemPlaceMeta::None => mplace.layout.ty,
-        MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
+        MemPlaceMeta::Poison => bug!("poison metadata in `deref_mir_constant`: {:#?}", mplace),
         // In case of unsized types, figure out the real type behind.
         MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
             ty::Str => bug!("there's no sized equivalent of a `str`"),
index 7346d69bb5de3f11c1d9429765ba47a82d703a8d..080133275a606cd864b33776c7ecf3bae7aa95ad 100644 (file)
@@ -1,24 +1,21 @@
 use super::eval_queries::{mk_eval_cx, op_to_const};
 use super::machine::CompileTimeEvalContext;
-use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
+use super::{ValTreeCreationError, ValTreeCreationResult};
 use crate::interpret::{
     intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
     MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit,
 };
+use crate::interpret::{MPlaceTy, Value};
+use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_span::source_map::DUMMY_SP;
 use rustc_target::abi::{Align, VariantIdx};
 
-use crate::interpret::MPlaceTy;
-use crate::interpret::Value;
-use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
-
 #[instrument(skip(ecx), level = "debug")]
 fn branches<'tcx>(
     ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
     place: &MPlaceTy<'tcx>,
     n: usize,
     variant: Option<VariantIdx>,
-    num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
     let place = match variant {
         Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(),
@@ -30,7 +27,7 @@ fn branches<'tcx>(
     let mut fields = Vec::with_capacity(n);
     for i in 0..n {
         let field = ecx.mplace_field(&place, i).unwrap();
-        let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?;
+        let valtree = const_to_valtree_inner(ecx, &field)?;
         fields.push(Some(valtree));
     }
 
@@ -42,11 +39,6 @@ fn branches<'tcx>(
         .collect::<Option<Vec<_>>>()
         .expect("should have already checked for errors in ValTree creation");
 
-    // Have to account for ZSTs here
-    if branches.len() == 0 {
-        *num_nodes += 1;
-    }
-
     Ok(ty::ValTree::Branch(ecx.tcx.arena.alloc_from_iter(branches)))
 }
 
@@ -54,7 +46,6 @@ fn branches<'tcx>(
 fn slice_branches<'tcx>(
     ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
     place: &MPlaceTy<'tcx>,
-    num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
     let n = place
         .len(&ecx.tcx.tcx)
@@ -63,7 +54,7 @@ fn slice_branches<'tcx>(
     let mut elems = Vec::with_capacity(n as usize);
     for i in 0..n {
         let place_elem = ecx.mplace_index(place, i).unwrap();
-        let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?;
+        let valtree = const_to_valtree_inner(ecx, &place_elem)?;
         elems.push(valtree);
     }
 
@@ -74,18 +65,12 @@ fn slice_branches<'tcx>(
 pub(crate) fn const_to_valtree_inner<'tcx>(
     ecx: &CompileTimeEvalContext<'tcx, 'tcx>,
     place: &MPlaceTy<'tcx>,
-    num_nodes: &mut usize,
 ) -> ValTreeCreationResult<'tcx> {
-    if *num_nodes >= VALTREE_MAX_NODES {
-        return Err(ValTreeCreationError::NodesOverflow);
-    }
-
     let ty = place.layout.ty;
     debug!("ty kind: {:?}", ty.kind());
 
     match ty.kind() {
         ty::FnDef(..) => {
-            *num_nodes += 1;
             Ok(ty::ValTree::zst())
         }
         ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
@@ -93,7 +78,6 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
                 return Err(ValTreeCreationError::Other);
             };
             let val = val.to_scalar().unwrap();
-            *num_nodes += 1;
 
             Ok(ty::ValTree::Leaf(val.assert_int()))
         }
@@ -110,11 +94,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
             };
             debug!(?derefd_place);
 
-            const_to_valtree_inner(ecx, &derefd_place, num_nodes)
+            const_to_valtree_inner(ecx, &derefd_place)
         }
 
         ty::Str | ty::Slice(_) | ty::Array(_, _) => {
-            slice_branches(ecx, place, num_nodes)
+            slice_branches(ecx, place)
         }
         // Trait objects are not allowed in type level constants, as we have no concept for
         // resolving their backing type, even if we can do that at const eval time. We may
@@ -123,7 +107,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
         ty::Dynamic(..) => Err(ValTreeCreationError::NonSupportedType),
 
         ty::Tuple(elem_tys) => {
-            branches(ecx, place, elem_tys.len(), None, num_nodes)
+            branches(ecx, place, elem_tys.len(), None)
         }
 
         ty::Adt(def, _) => {
@@ -136,7 +120,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>(
             let Ok((_, variant)) = ecx.read_discriminant(&place.into()) else {
                 return Err(ValTreeCreationError::Other);
             };
-            branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes)
+            branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant))
         }
 
         ty::Never
@@ -234,13 +218,9 @@ fn create_pointee_place<'tcx>(
         // Get the size of the memory behind the DST
         let dst_size = unsized_inner_ty_size.checked_mul(num_elems as u64, &tcx).unwrap();
 
-        let ptr = ecx
-            .allocate_ptr(
-                size_of_sized_part.checked_add(dst_size, &tcx).unwrap(),
-                Align::from_bytes(1).unwrap(),
-                MemoryKind::Stack,
-            )
-            .unwrap();
+        let size = size_of_sized_part.checked_add(dst_size, &tcx).unwrap();
+        let align = Align::from_bytes(size.bytes().next_power_of_two()).unwrap();
+        let ptr = ecx.allocate_ptr(size, align, MemoryKind::Stack).unwrap();
         debug!(?ptr);
 
         let place = MPlaceTy::from_aligned_ptr_with_meta(
@@ -262,7 +242,7 @@ fn create_pointee_place<'tcx>(
 #[instrument(skip(tcx), level = "debug")]
 pub fn valtree_to_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
-    ty: Ty<'tcx>,
+    param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
     valtree: ty::ValTree<'tcx>,
 ) -> ConstValue<'tcx> {
     // Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
@@ -272,8 +252,8 @@ pub fn valtree_to_const_value<'tcx>(
     // create inner `MPlace`s which are filled recursively.
     // FIXME Does this need an example?
 
-    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::empty(), false);
-    let param_env_ty = ty::ParamEnv::empty().and(ty);
+    let (param_env, ty) = param_env_ty.into_parts();
+    let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
 
     match ty.kind() {
         ty::FnDef(..) => {
@@ -336,7 +316,6 @@ pub fn valtree_to_const_value<'tcx>(
     }
 }
 
-// FIXME Needs a better/correct name
 #[instrument(skip(ecx), level = "debug")]
 fn valtree_into_mplace<'tcx>(
     ecx: &mut CompileTimeEvalContext<'tcx, 'tcx>,
index 597ca4cfcdd0678b3c48631afb5b875cd5642a42..e9a9c0e171376f62182575fc98cdf7b5a2b76e86 100644 (file)
@@ -637,7 +637,11 @@ pub fn const_to_op(
             ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
                 span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
             }
-            ty::ConstKind::Value(val) => self.const_val_to_op(val, c.ty(), layout),
+            ty::ConstKind::Value(valtree) => {
+                let ty = val.ty();
+                let const_val = self.tcx.valtree_to_const_val((ty, valtree));
+                self.const_val_to_op(const_val, ty, layout)
+            }
         }
     }
 
index 04410ca382859c870bbc642e7f4874b0809636a3..64a74e9d7e206931ee3fe0f3309aaaca8ce4fdc4 100644 (file)
@@ -34,6 +34,7 @@
 pub mod transform;
 pub mod util;
 
+use rustc_middle::ty;
 use rustc_middle::ty::query::Providers;
 
 pub fn provide(providers: &mut Providers) {
@@ -41,10 +42,7 @@ pub fn provide(providers: &mut Providers) {
     providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
     providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
     providers.const_caller_location = const_eval::const_caller_location;
-    providers.try_destructure_const = |tcx, param_env_and_val| {
-        let (param_env, c) = param_env_and_val.into_parts();
-        const_eval::try_destructure_const(tcx, param_env, c).ok()
-    };
+    providers.try_destructure_const = |tcx, val| const_eval::try_destructure_const(tcx, val);
     providers.eval_to_valtree = |tcx, param_env_and_value| {
         let (param_env, raw) = param_env_and_value.into_parts();
         const_eval::eval_to_valtree(tcx, param_env, raw)
@@ -53,11 +51,8 @@ pub fn provide(providers: &mut Providers) {
         let (param_env, value) = param_env_and_value.into_parts();
         const_eval::try_destructure_mir_constant(tcx, param_env, value).ok()
     };
-    providers.valtree_to_const_val =
-        |tcx, (ty, valtree)| const_eval::valtree_to_const_value(tcx, ty, valtree);
-    providers.deref_const = |tcx, param_env_and_value| {
-        let (param_env, value) = param_env_and_value.into_parts();
-        const_eval::deref_const(tcx, param_env, value)
+    providers.valtree_to_const_val = |tcx, (ty, valtree)| {
+        const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
     };
     providers.deref_mir_constant = |tcx, param_env_and_value| {
         let (param_env, value) = param_env_and_value.into_parts();
index 67a356918d1b99b68da8c38ca0accf24716110b0..3595a488d0c5b716f3b721147e6a2f43bfbd0b03 100644 (file)
@@ -765,7 +765,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
                         let unit = Rvalue::Use(Operand::Constant(Box::new(Constant {
                             span: statement.source_info.span,
                             user_ty: None,
-                            literal: ty::Const::zero_sized(self.tcx, self.tcx.types.unit).into(),
+                            literal: ConstantKind::zero_sized(self.tcx.types.unit),
                         })));
                         mem::replace(rhs, unit)
                     },
@@ -835,26 +835,25 @@ fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) ->
             let mut promoted_operand = |ty, span| {
                 promoted.span = span;
                 promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
+                let _const = tcx.mk_const(ty::ConstS {
+                    ty,
+                    kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
+                        def,
+                        substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
+                            if let ty::GenericParamDefKind::Lifetime = param.kind {
+                                tcx.lifetimes.re_erased.into()
+                            } else {
+                                tcx.mk_param_from_def(param)
+                            }
+                        }),
+                        promoted: Some(promoted_id),
+                    }),
+                });
 
                 Operand::Constant(Box::new(Constant {
                     span,
                     user_ty: None,
-                    literal: tcx
-                        .mk_const(ty::ConstS {
-                            ty,
-                            kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
-                                def,
-                                substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
-                                    if let ty::GenericParamDefKind::Lifetime = param.kind {
-                                        tcx.lifetimes.re_erased.into()
-                                    } else {
-                                        tcx.mk_param_from_def(param)
-                                    }
-                                }),
-                                promoted: Some(promoted_id),
-                            }),
-                        })
-                        .into(),
+                    literal: ConstantKind::from_const(_const, tcx),
                 }))
             };
             let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
index 59c708fb7509ac93f5d40abc366507e70160252c..93a067cb5160633e441a632fa43e621a1cb561a1 100644 (file)
@@ -20,7 +20,7 @@
 use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues};
 use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
-use rustc_middle::mir::interpret::{ErrorHandled, EvalToConstValueResult};
+use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
 use rustc_middle::traits::select;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
@@ -1616,6 +1616,28 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex {
         u
     }
 
+    pub fn try_const_eval_resolve(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        unevaluated: ty::Unevaluated<'tcx>,
+        ty: Ty<'tcx>,
+        span: Option<Span>,
+    ) -> Result<ty::Const<'tcx>, ErrorHandled> {
+        match self.const_eval_resolve(param_env, unevaluated, span) {
+            Ok(Some(val)) => Ok(ty::Const::from_value(self.tcx, val, ty)),
+            Ok(None) => {
+                let tcx = self.tcx;
+                let def_id = unevaluated.def.did;
+                span_bug!(
+                    tcx.def_span(def_id),
+                    "unable to construct a constant value for the unevaluated constant {:?}",
+                    unevaluated
+                );
+            }
+            Err(err) => Err(err),
+        }
+    }
+
     /// Resolves and evaluates a constant.
     ///
     /// The constant can be located on a trait like `<A as B>::C`, in which case the given
@@ -1634,7 +1656,7 @@ pub fn const_eval_resolve(
         param_env: ty::ParamEnv<'tcx>,
         unevaluated: ty::Unevaluated<'tcx>,
         span: Option<Span>,
-    ) -> EvalToConstValueResult<'tcx> {
+    ) -> EvalToValTreeResult<'tcx> {
         let substs = self.resolve_vars_if_possible(unevaluated.substs);
         debug!(?substs);
 
@@ -1658,7 +1680,7 @@ pub fn const_eval_resolve(
 
         // The return value is the evaluated value which doesn't contain any reference to inference
         // variables, thus we don't need to substitute back the original values.
-        self.tcx.const_eval_resolve(param_env_erased, unevaluated, span)
+        self.tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
     }
 
     /// `ty_or_const_infer_var_changed` is equivalent to one of these two:
index 8fc957cf49c8863aab852db8026d23e5fe178693..69353232f06590d863ee4a9b2e714a0cd66b4398 100644 (file)
@@ -1,4 +1,4 @@
-use super::{ErrorHandled, EvalToConstValueResult, GlobalId};
+use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
 
 use crate::mir;
 use crate::ty::fold::TypeFoldable;
@@ -11,6 +11,10 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
     /// that can't take any generic arguments like statics, const items or enum discriminants. If a
     /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
+    ///
+    /// Note: Returns a `ConstValue`, which isn't supposed to be used in the type system. In order to
+    /// evaluate to a type-system level constant value use `const_eval_poly_for_typeck`.
+    #[instrument(skip(self), level = "debug")]
     pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
         // In some situations def_id will have substitutions within scope, but they aren't allowed
         // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
@@ -23,6 +27,22 @@ pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> {
         self.const_eval_global_id(param_env, cid, None)
     }
 
+    /// Evaluates a constant without providing any substitutions. This is useful to evaluate consts
+    /// that can't take any generic arguments like statics, const items or enum discriminants. If a
+    /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned.
+    #[instrument(skip(self), level = "debug")]
+    pub fn const_eval_poly_for_typeck(self, def_id: DefId) -> EvalToValTreeResult<'tcx> {
+        // In some situations def_id will have substitutions within scope, but they aren't allowed
+        // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions
+        // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
+        // encountered.
+        let substs = InternalSubsts::identity_for_item(self, def_id);
+        let instance = ty::Instance::new(def_id, substs);
+        let cid = GlobalId { instance, promoted: None };
+        let param_env = self.param_env(def_id).with_reveal_all_normalized(self);
+        self.const_eval_global_id_for_typeck(param_env, cid, None)
+    }
+
     /// Resolves and evaluates a constant.
     ///
     /// The constant can be located on a trait like `<A as B>::C`, in which case the given
@@ -59,6 +79,33 @@ pub fn const_eval_resolve(
         }
     }
 
+    #[instrument(level = "debug", skip(self))]
+    pub fn const_eval_resolve_for_typeck(
+        self,
+        param_env: ty::ParamEnv<'tcx>,
+        ct: ty::Unevaluated<'tcx>,
+        span: Option<Span>,
+    ) -> EvalToValTreeResult<'tcx> {
+        // Cannot resolve `Unevaluated` constants that contain inference
+        // variables. We reject those here since `resolve_opt_const_arg`
+        // would fail otherwise.
+        //
+        // When trying to evaluate constants containing inference variables,
+        // use `Infcx::const_eval_resolve` instead.
+        if ct.substs.has_infer_types_or_consts() {
+            bug!("did not expect inference variables here");
+        }
+
+        match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+            Ok(Some(instance)) => {
+                let cid = GlobalId { instance, promoted: ct.promoted };
+                self.const_eval_global_id_for_typeck(param_env, cid, span)
+            }
+            Ok(None) => Err(ErrorHandled::TooGeneric),
+            Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
+        }
+    }
+
     pub fn const_eval_instance(
         self,
         param_env: ty::ParamEnv<'tcx>,
@@ -68,7 +115,8 @@ pub fn const_eval_instance(
         self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span)
     }
 
-    /// Evaluate a constant.
+    /// Evaluate a constant to a `ConstValue`.
+    #[instrument(skip(self), level = "debug")]
     pub fn const_eval_global_id(
         self,
         param_env: ty::ParamEnv<'tcx>,
@@ -86,6 +134,27 @@ pub fn const_eval_global_id(
         }
     }
 
+    /// Evaluate a constant to a type-level constant.
+    #[instrument(skip(self), level = "debug")]
+    pub fn const_eval_global_id_for_typeck(
+        self,
+        param_env: ty::ParamEnv<'tcx>,
+        cid: GlobalId<'tcx>,
+        span: Option<Span>,
+    ) -> EvalToValTreeResult<'tcx> {
+        let param_env = param_env.with_const();
+        debug!(?param_env);
+        // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
+        // improve caching of queries.
+        let inputs = self.erase_regions(param_env.and(cid));
+        debug!(?inputs);
+        if let Some(span) = span {
+            self.at(span).eval_to_valtree(inputs)
+        } else {
+            self.eval_to_valtree(inputs)
+        }
+    }
+
     /// Evaluate a static's initializer, returning the allocation of the initializer's memory.
     #[inline(always)]
     pub fn eval_static_initializer(
@@ -125,11 +194,8 @@ fn eval_to_allocation(
 impl<'tcx> TyCtxt<'tcx> {
     /// Destructure a type-level constant ADT or array into its variant index and its field values.
     /// Panics if the destructuring fails, use `try_destructure_const` for fallible version.
-    pub fn destructure_const(
-        self,
-        param_env_and_val: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>,
-    ) -> mir::DestructuredConst<'tcx> {
-        self.try_destructure_const(param_env_and_val).unwrap()
+    pub fn destructure_const(self, const_: ty::Const<'tcx>) -> mir::DestructuredConst<'tcx> {
+        self.try_destructure_const(const_).unwrap()
     }
 
     /// Destructure a mir constant ADT or array into its variant index and its field values.
index 146ae45e46898ffaae61e9fffd9f37ebe759d50c..f566467b7ce09758f0d816a51d53bf2a720c68d0 100644 (file)
@@ -78,6 +78,7 @@ pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
         Some(self.try_to_scalar()?.assert_int())
     }
 
+    #[inline(always)]
     pub fn try_to_bits(&self, size: Size) -> Option<u128> {
         self.try_to_scalar_int()?.to_bits(size).ok()
     }
index 1511b51fa25486258b4ee331f962febe152975e4..512615ccbab8594c5081d80109142d6960cdc3cb 100644 (file)
@@ -3,7 +3,9 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
 use crate::mir::coverage::{CodeRegion, CoverageKind};
-use crate::mir::interpret::{ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar};
+use crate::mir::interpret::{
+    AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar,
+};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -1444,7 +1446,11 @@ pub fn expand_statements<F, I>(&mut self, mut f: F)
     }
 
     pub fn visitable(&self, index: usize) -> &dyn MirVisitable<'tcx> {
-        if index < self.statements.len() { &self.statements[index] } else { &self.terminator }
+        if index < self.statements.len() {
+            &self.statements[index]
+        } else {
+            &self.terminator
+        }
     }
 }
 
@@ -2465,7 +2471,11 @@ pub fn constant(&self) -> Option<&Constant<'tcx>> {
     /// find as the `func` in a [`TerminatorKind::Call`].
     pub fn const_fn_def(&self) -> Option<(DefId, SubstsRef<'tcx>)> {
         let const_ty = self.constant()?.literal.ty();
-        if let ty::FnDef(def_id, substs) = *const_ty.kind() { Some((def_id, substs)) } else { None }
+        if let ty::FnDef(def_id, substs) = *const_ty.kind() {
+            Some((def_id, substs))
+        } else {
+            None
+        }
     }
 }
 
@@ -2953,22 +2963,9 @@ pub fn ty(&self) -> Ty<'tcx> {
     }
 }
 
-impl<'tcx> From<ty::Const<'tcx>> for ConstantKind<'tcx> {
-    #[inline]
-    fn from(ct: ty::Const<'tcx>) -> Self {
-        match ct.kind() {
-            ty::ConstKind::Value(cv) => {
-                // FIXME Once valtrees are introduced we need to convert those
-                // into `ConstValue` instances here
-                Self::Val(cv, ct.ty())
-            }
-            _ => Self::Ty(ct),
-        }
-    }
-}
-
 impl<'tcx> ConstantKind<'tcx> {
     /// Returns `None` if the constant is not trivially safe for use in the type system.
+    #[inline]
     pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
         match self {
             ConstantKind::Ty(c) => Some(*c),
@@ -2976,6 +2973,7 @@ pub fn const_for_ty(&self) -> Option<ty::Const<'tcx>> {
         }
     }
 
+    #[inline(always)]
     pub fn ty(&self) -> Ty<'tcx> {
         match self {
             ConstantKind::Ty(c) => c.ty(),
@@ -2983,10 +2981,10 @@ pub fn ty(&self) -> Ty<'tcx> {
         }
     }
 
-    pub fn try_val(&self) -> Option<ConstValue<'tcx>> {
+    pub fn try_val(&self, tcx: TyCtxt<'tcx>) -> Option<ConstValue<'tcx>> {
         match self {
             ConstantKind::Ty(c) => match c.kind() {
-                ty::ConstKind::Value(v) => Some(v),
+                ty::ConstKind::Value(v) => Some(tcx.valtree_to_const_val((c.ty(), v))),
                 _ => None,
             },
             ConstantKind::Val(v, _) => Some(*v),
@@ -2994,21 +2992,33 @@ pub fn try_val(&self) -> Option<ConstValue<'tcx>> {
     }
 
     #[inline]
-    pub fn try_to_value(self) -> Option<interpret::ConstValue<'tcx>> {
+    pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option<interpret::ConstValue<'tcx>> {
         match self {
-            ConstantKind::Ty(c) => c.kind().try_to_value(),
+            ConstantKind::Ty(c) => match c.kind() {
+                ty::ConstKind::Value(valtree) => Some(tcx.valtree_to_const_val((c.ty(), valtree))),
+                _ => None,
+            },
             ConstantKind::Val(val, _) => Some(val),
         }
     }
 
     #[inline]
     pub fn try_to_scalar(self) -> Option<Scalar> {
-        self.try_to_value()?.try_to_scalar()
+        match self {
+            ConstantKind::Ty(c) => match c.val() {
+                ty::ConstKind::Value(valtree) => match valtree {
+                    ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)),
+                    ty::ValTree::Branch(_) => None,
+                },
+                _ => None,
+            },
+            ConstantKind::Val(val, _) => val.try_to_scalar(),
+        }
     }
 
     #[inline]
     pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
-        Some(self.try_to_value()?.try_to_scalar()?.assert_int())
+        Some(self.try_to_scalar()?.assert_int())
     }
 
     #[inline]
@@ -3025,9 +3035,7 @@ pub fn try_to_bool(self) -> Option<bool> {
     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
         match self {
             Self::Ty(c) => {
-                // FIXME Need to use a different evaluation function that directly returns a `ConstValue`
-                // if evaluation succeeds and does not create a ValTree first
-                if let Some(val) = c.kind().try_eval(tcx, param_env) {
+                if let Some(val) = c.kind().try_eval_for_mir(tcx, param_env) {
                     match val {
                         Ok(val) => Self::Val(val, c.ty()),
                         Err(_) => Self::Ty(tcx.const_error(self.ty())),
@@ -3081,6 +3089,11 @@ pub fn try_eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -
         }
     }
 
+    #[inline]
+    pub fn from_value(val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
+        Self::Val(val, ty)
+    }
+
     pub fn from_bits(
         tcx: TyCtxt<'tcx>,
         bits: u128,
@@ -3097,11 +3110,13 @@ pub fn from_bits(
         Self::Val(cv, param_env_ty.value)
     }
 
+    #[inline]
     pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self {
         let cv = ConstValue::from_bool(v);
         Self::Val(cv, tcx.types.bool)
     }
 
+    #[inline]
     pub fn zero_sized(ty: Ty<'tcx>) -> Self {
         let cv = ConstValue::Scalar(Scalar::ZST);
         Self::Val(cv, ty)
@@ -3112,6 +3127,12 @@ pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self {
         Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty))
     }
 
+    #[inline]
+    pub fn from_scalar(_tcx: TyCtxt<'tcx>, s: Scalar, ty: Ty<'tcx>) -> Self {
+        let val = ConstValue::Scalar(s);
+        Self::Val(val, ty)
+    }
+
     /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
     /// converted to a constant, everything else becomes `Unevaluated`.
     pub fn from_anon_const(
@@ -3199,8 +3220,10 @@ fn from_opt_const_arg_anon_const(
             }
             _ => expr,
         };
+        debug!("expr.kind: {:?}", expr.kind);
 
         let ty = tcx.type_of(def.def_id_for_type_of());
+        debug!(?ty);
 
         // FIXME(const_generics): We currently have to special case parameters because `min_const_generics`
         // does not provide the parents generics to anonymous constants. We still allow generic const
@@ -3224,6 +3247,7 @@ fn from_opt_const_arg_anon_const(
                     kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)),
                     ty,
                 });
+                debug!(?ty_const);
 
                 return Self::Ty(ty_const);
             }
@@ -3253,8 +3277,12 @@ fn from_opt_const_arg_anon_const(
         debug!(?span, ?param_env);
 
         match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
-            Ok(val) => Self::Val(val, ty),
+            Ok(val) => {
+                debug!("evaluated const value: {:?}", val);
+                Self::Val(val, ty)
+            }
             Err(_) => {
+                debug!("error encountered during evaluation");
                 // Error was handled in `const_eval_resolve`. Here we just create a
                 // new unevaluated const and error hard later in codegen
                 let ty_const = tcx.mk_const(ty::ConstS {
@@ -3265,11 +3293,22 @@ fn from_opt_const_arg_anon_const(
                     }),
                     ty,
                 });
+                debug!(?ty_const);
 
                 Self::Ty(ty_const)
             }
         }
     }
+
+    pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
+        match c.val() {
+            ty::ConstKind::Value(valtree) => {
+                let const_val = tcx.valtree_to_const_val((c.ty(), valtree));
+                Self::Val(const_val, c.ty())
+            }
+            _ => Self::Ty(c),
+        }
+    }
 }
 
 /// A collection of projections into user types.
@@ -3485,20 +3524,182 @@ fn pretty_print_const<'tcx>(
     })
 }
 
+fn pretty_print_byte_str(fmt: &mut Formatter<'_>, byte_str: &[u8]) -> fmt::Result {
+    fmt.write_str("b\"")?;
+    for &c in byte_str {
+        for e in std::ascii::escape_default(c) {
+            fmt.write_char(e as char)?;
+        }
+    }
+    fmt.write_str("\"")?;
+
+    Ok(())
+}
+
+fn comma_sep<'tcx>(fmt: &mut Formatter<'_>, elems: Vec<ConstantKind<'tcx>>) -> fmt::Result {
+    let mut first = true;
+    for elem in elems {
+        if !first {
+            fmt.write_str(", ")?;
+        }
+        fmt.write_str(&format!("{}", elem))?;
+        first = false;
+    }
+    Ok(())
+}
+
 fn pretty_print_const_value<'tcx>(
-    val: interpret::ConstValue<'tcx>,
+    ct: ConstValue<'tcx>,
     ty: Ty<'tcx>,
     fmt: &mut Formatter<'_>,
-    print_types: bool,
+    print_ty: bool,
 ) -> fmt::Result {
     use crate::ty::print::PrettyPrinter;
+
     ty::tls::with(|tcx| {
-        let val = tcx.lift(val).unwrap();
+        let ct = tcx.lift(ct).unwrap();
         let ty = tcx.lift(ty).unwrap();
-        let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
-        cx.print_alloc_ids = true;
-        let cx = cx.pretty_print_const_value(val, ty, print_types)?;
-        fmt.write_str(&cx.into_buffer())?;
+
+        if tcx.sess.verbose() {
+            fmt.write_str(&format!("ConstValue({:?}: {})", ct, ty))?;
+            return Ok(());
+        }
+
+        let u8_type = tcx.types.u8;
+        match (ct, ty.kind()) {
+            // Byte/string slices, printed as (byte) string literals.
+            (ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
+                match inner.kind() {
+                    ty::Slice(t) => {
+                        if *t == u8_type {
+                            // The `inspect` here is okay since we checked the bounds, and there are
+                            // no relocations (we have an active slice reference here). We don't use
+                            // this result to affect interpreter execution.
+                            let byte_str = data
+                                .inner()
+                                .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
+                            pretty_print_byte_str(fmt, byte_str)?;
+                            return Ok(());
+                        }
+                    }
+                    ty::Str => {
+                        // The `inspect` here is okay since we checked the bounds, and there are no
+                        // relocations (we have an active `str` reference here). We don't use this
+                        // result to affect interpreter execution.
+                        let slice = data
+                            .inner()
+                            .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
+                        fmt.write_str(&format!("{:?}", String::from_utf8_lossy(slice)))?;
+                        return Ok(());
+                    }
+                    _ => {}
+                }
+            }
+            (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
+                let n = n.val().try_to_bits(tcx.data_layout.pointer_size).unwrap();
+                // cast is ok because we already checked for pointer size (32 or 64 bit) above
+                let range = AllocRange { start: offset, size: Size::from_bytes(n) };
+                let byte_str = alloc.inner().get_bytes(&tcx, range).unwrap();
+                fmt.write_str("*")?;
+                pretty_print_byte_str(fmt, byte_str)?;
+                return Ok(());
+            }
+            // Aggregates, printed as array/tuple/struct/variant construction syntax.
+            //
+            // NB: the `has_param_types_or_consts` check ensures that we can use
+            // the `destructure_const` query with an empty `ty::ParamEnv` without
+            // introducing ICEs (e.g. via `layout_of`) from missing bounds.
+            // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
+            // to be able to destructure the tuple into `(0u8, *mut T)
+            //
+            // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
+            // correct `ty::ParamEnv` to allow printing *all* constant values.
+            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+                let ct = tcx.lift(ct).unwrap();
+                let ty = tcx.lift(ty).unwrap();
+                if let Some(contents) = tcx.try_destructure_mir_constant(
+                    ty::ParamEnv::reveal_all().and(ConstantKind::Val(ct, ty)),
+                ) {
+                    let fields = contents.fields.iter().copied().collect::<Vec<_>>();
+                    match *ty.kind() {
+                        ty::Array(..) => {
+                            fmt.write_str("[")?;
+                            comma_sep(fmt, fields)?;
+                            fmt.write_str("]")?;
+                        }
+                        ty::Tuple(..) => {
+                            fmt.write_str("(")?;
+                            comma_sep(fmt, fields)?;
+                            if contents.fields.len() == 1 {
+                                fmt.write_str(",")?;
+                            }
+                            fmt.write_str(")")?;
+                        }
+                        ty::Adt(def, _) if def.variants().is_empty() => {
+                            fmt.write_str(&format!("{{unreachable(): {}}}", ty))?;
+                        }
+                        ty::Adt(def, substs) => {
+                            let variant_idx = contents
+                                .variant
+                                .expect("destructed mir constant of adt without variant idx");
+                            let variant_def = &def.variant(variant_idx);
+                            let substs = tcx.lift(substs).unwrap();
+                            let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
+                            cx.print_alloc_ids = true;
+                            let cx = cx.print_value_path(variant_def.def_id, substs)?;
+                            fmt.write_str(&cx.into_buffer())?;
+
+                            match variant_def.ctor_kind {
+                                CtorKind::Const => {}
+                                CtorKind::Fn => {
+                                    fmt.write_str("(")?;
+                                    comma_sep(fmt, fields)?;
+                                    fmt.write_str(")")?;
+                                }
+                                CtorKind::Fictive => {
+                                    fmt.write_str(" {{ ")?;
+                                    let mut first = true;
+                                    for (field_def, field) in iter::zip(&variant_def.fields, fields)
+                                    {
+                                        if !first {
+                                            fmt.write_str(", ")?;
+                                        }
+                                        fmt.write_str(&format!("{}: {}", field_def.name, field))?;
+                                        first = false;
+                                    }
+                                    fmt.write_str(" }}")?;
+                                }
+                            }
+                        }
+                        _ => unreachable!(),
+                    }
+                    return Ok(());
+                } else {
+                    // Fall back to debug pretty printing for invalid constants.
+                    fmt.write_str(&format!("{:?}", ct))?;
+                    if print_ty {
+                        fmt.write_str(&format!(": {}", ty))?;
+                    }
+                    return Ok(());
+                };
+            }
+            (ConstValue::Scalar(scalar), _) => {
+                let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS);
+                cx.print_alloc_ids = true;
+                let ty = tcx.lift(ty).unwrap();
+                cx = cx.pretty_print_const_scalar(scalar, ty, print_ty)?;
+                fmt.write_str(&cx.into_buffer())?;
+                return Ok(());
+            }
+            // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
+            // their fields instead of just dumping the memory.
+            _ => {}
+        }
+        // fallback
+        fmt.write_str(&format!("{:?}", ct))?;
+        if print_ty {
+            fmt.write_str(&format!(": {}", ty))?;
+        }
         Ok(())
     })
 }
index 739c543dea773fd380f599c0c247e9110d448d6e..a81a60df2be8a16c77728abd4bf2d8a36641ccbb 100644 (file)
@@ -454,7 +454,12 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) {
                 ConstValue::ByRef { .. } => format!("ByRef(..)"),
             };
 
-            let kind = match literal {
+            let fmt_valtree = |valtree: &ty::ValTree<'tcx>| match valtree {
+                ty::ValTree::Leaf(leaf) => format!("ValTree::Leaf({:?})", leaf),
+                ty::ValTree::Branch(_) => format!("ValTree::Branch(..)"),
+            };
+
+            let val = match literal {
                 ConstantKind::Ty(ct) => match ct.kind() {
                     ty::ConstKind::Param(p) => format!("Param({})", p),
                     ty::ConstKind::Unevaluated(uv) => format!(
@@ -463,7 +468,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) {
                         uv.substs,
                         uv.promoted,
                     ),
-                    ty::ConstKind::Value(val) => format!("Value({})", fmt_val(&val)),
+                    ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
                     ty::ConstKind::Error(_) => "Error".to_string(),
                     // These variants shouldn't exist in the MIR.
                     ty::ConstKind::Placeholder(_)
@@ -665,7 +670,8 @@ fn alloc_ids_from_alloc(
     ) -> impl DoubleEndedIterator<Item = AllocId> + '_ {
         alloc.inner().relocations().values().map(|id| *id)
     }
-    fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
+
+    fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> + '_ {
         match val {
             ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => {
                 Either::Left(Either::Left(std::iter::once(ptr.provenance)))
@@ -681,17 +687,11 @@ fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator<Item = AllocId> +
     struct CollectAllocIds(BTreeSet<AllocId>);
 
     impl<'tcx> Visitor<'tcx> for CollectAllocIds {
-        fn visit_const(&mut self, c: ty::Const<'tcx>, _loc: Location) {
-            if let ty::ConstKind::Value(val) = c.kind() {
-                self.0.extend(alloc_ids_from_const(val));
-            }
-        }
-
         fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) {
             match c.literal {
                 ConstantKind::Ty(c) => self.visit_const(c, loc),
                 ConstantKind::Val(val, _) => {
-                    self.0.extend(alloc_ids_from_const(val));
+                    self.0.extend(alloc_ids_from_const_val(val));
                 }
             }
         }
index 01945b543b14bf6a585428bccc445cce3401b372..da4793fa039d0f36be8d16495b450ae807ab6894 100644 (file)
@@ -1,6 +1,6 @@
 //! Values computed by queries that use MIR.
 
-use crate::mir::{self, Body, Promoted};
+use crate::mir::{Body, ConstantKind, Promoted};
 use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
 use rustc_data_structures::stable_map::FxHashMap;
 use rustc_data_structures::vec_map::VecMap;
@@ -427,7 +427,7 @@ pub struct DestructuredConst<'tcx> {
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct DestructuredMirConstant<'tcx> {
     pub variant: Option<VariantIdx>,
-    pub fields: &'tcx [mir::ConstantKind<'tcx>],
+    pub fields: &'tcx [ConstantKind<'tcx>],
 }
 
 /// Coverage information summarized from a MIR if instrumented for source code coverage (see
index c859d93043e3e8c05cf18df6da753b03b2f8d123..c65e79a80fb8ebf29b28595c1913466986367eb0 100644 (file)
@@ -1,3 +1,4 @@
+use crate::mir;
 use crate::mir::interpret::Scalar;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
@@ -676,7 +677,7 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
                     .values
                     .iter()
                     .map(|&u| {
-                        ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
+                        mir::ConstantKind::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
                             .to_string()
                             .into()
                     })
index 5b48f164016f7e2ea97eab165447f32583aab378..22b1ad4190489a43a3d2f4f3d0b204987a54d89e 100644 (file)
         key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>
     ) -> EvalToValTreeResult<'tcx> {
         desc { "evaluate type-level constant" }
-        remap_env_constness
     }
 
     /// Converts a type level constant value into `ConstValue`
     /// field values or return `None` if constant is invalid.
     ///
     /// Use infallible `TyCtxt::destructure_const` when you know that constant is valid.
-    query try_destructure_const(key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>) -> Option<mir::DestructuredConst<'tcx>> {
+    query try_destructure_const(key: ty::Const<'tcx>) -> Option<mir::DestructuredConst<'tcx>> {
         desc { "destructure type level constant"}
     }
 
         remap_env_constness
     }
 
-    /// Dereference a constant reference or raw pointer and turn the result into a constant
-    /// again.
-    query deref_const(
-        key: ty::ParamEnvAnd<'tcx, ty::Const<'tcx>>
-    ) -> ty::Const<'tcx> {
-        desc { "deref constant" }
-        remap_env_constness
-    }
-
     /// Dereference a constant reference or raw pointer and turn the result into a constant
     /// again.
     query deref_mir_constant(
index 015bdb5783f36ef657d13af3cbc7ae46d70c8306..70abdb9ab4cd7be51106e777960dc5852b829c93 100644 (file)
@@ -5,7 +5,6 @@
 //! its name suggest, is to provide an abstraction boundary for creating
 //! interned Chalk types.
 
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::{self, AdtDef, TyCtxt};
 
 use rustc_hir::def_id::DefId;
@@ -62,7 +61,7 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
     type InternedType = Box<chalk_ir::TyData<Self>>;
     type InternedLifetime = Box<chalk_ir::LifetimeData<Self>>;
     type InternedConst = Box<chalk_ir::ConstData<Self>>;
-    type InternedConcreteConst = ConstValue<'tcx>;
+    type InternedConcreteConst = ty::ValTree<'tcx>;
     type InternedGenericArg = Box<chalk_ir::GenericArgData<Self>>;
     type InternedGoal = Box<chalk_ir::GoalData<Self>>;
     type InternedGoals = Vec<chalk_ir::Goal<Self>>;
index 0e87a05bade096f8bcd17cb9bf0c39a3f631e0f1..47abbb723dce1ca37c42f176b0202237423e8cf0 100644 (file)
@@ -1,5 +1,5 @@
-use crate::mir::interpret::ConstValue;
-use crate::mir::interpret::{LitToConstInput, Scalar};
+use crate::mir::interpret::LitToConstInput;
+use crate::mir::ConstantKind;
 use crate::ty::{
     self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
     TyCtxt, TypeFoldable,
@@ -195,14 +195,13 @@ pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
 
     /// Interns the given value as a constant.
     #[inline]
-    pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> Self {
+    pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Self {
         tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty })
     }
 
-    #[inline]
-    /// Interns the given scalar as a constant.
-    pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> Self {
-        Self::from_value(tcx, ConstValue::Scalar(val), ty)
+    pub fn from_scalar_int(tcx: TyCtxt<'tcx>, i: ScalarInt, ty: Ty<'tcx>) -> Self {
+        let valtree = ty::ValTree::from_scalar_int(i);
+        Self::from_value(tcx, valtree, ty)
     }
 
     #[inline]
@@ -212,13 +211,14 @@ pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>)
             .layout_of(ty)
             .unwrap_or_else(|e| panic!("could not compute layout for {:?}: {:?}", ty, e))
             .size;
-        Self::from_scalar(tcx, Scalar::from_uint(bits, size), ty.value)
+        Self::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap(), ty.value)
     }
 
     #[inline]
     /// Creates an interned zst constant.
     pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
-        Self::from_scalar(tcx, Scalar::ZST, ty)
+        let valtree = ty::ValTree::zst();
+        Self::from_value(tcx, valtree, ty)
     }
 
     #[inline]
@@ -263,16 +263,31 @@ pub fn try_eval_usize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Opt
     /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
     /// unevaluated constant.
     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Const<'tcx> {
-        if let Some(val) = self.kind().try_eval(tcx, param_env) {
+        if let Some(val) = self.kind().try_eval_for_typeck(tcx, param_env) {
             match val {
                 Ok(val) => Const::from_value(tcx, val, self.ty()),
                 Err(ErrorGuaranteed { .. }) => tcx.const_error(self.ty()),
             }
         } else {
+            // Either the constant isn't evaluatable or ValTree creation failed.
             self
         }
     }
 
+    #[inline]
+    /// Tries to evaluate the constant if it is `Unevaluated` and creates a ConstValue if the
+    /// evaluation succeeds. If it doesn't succeed, returns the unevaluated constant.
+    pub fn eval_for_mir(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> ConstantKind<'tcx> {
+        if let Some(val) = self.val().try_eval_for_mir(tcx, param_env) {
+            match val {
+                Ok(const_val) => ConstantKind::from_value(const_val, self.ty()),
+                Err(ErrorGuaranteed { .. }) => ConstantKind::Ty(tcx.const_error(self.ty())),
+            }
+        } else {
+            ConstantKind::Ty(self)
+        }
+    }
+
     #[inline]
     /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type.
     pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> u128 {
index 35d286d2c5781e607a53004969fd7e9f6956f248..10d03065c795f7e5db4838a671e757b461291177 100644 (file)
@@ -63,7 +63,7 @@ pub enum ConstKind<'tcx> {
     Unevaluated(Unevaluated<'tcx>),
 
     /// Used to hold computed value.
-    Value(ConstValue<'tcx>),
+    Value(ty::ValTree<'tcx>),
 
     /// A placeholder for a const which could not be computed; this is
     /// propagated to avoid useless error messages.
@@ -75,7 +75,7 @@ pub enum ConstKind<'tcx> {
 
 impl<'tcx> ConstKind<'tcx> {
     #[inline]
-    pub fn try_to_value(self) -> Option<ConstValue<'tcx>> {
+    pub fn try_to_value(self) -> Option<ty::ValTree<'tcx>> {
         if let ConstKind::Value(val) = self { Some(val) } else { None }
     }
 
@@ -86,7 +86,7 @@ pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
 
     #[inline]
     pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
-        Some(self.try_to_value()?.try_to_scalar()?.assert_int())
+        self.try_to_value()?.try_to_scalar_int()
     }
 
     #[inline]
@@ -115,23 +115,65 @@ pub enum InferConst<'tcx> {
     Fresh(u32),
 }
 
+enum EvalMode {
+    Typeck,
+    Mir,
+}
+
+enum EvalResult<'tcx> {
+    ValTree(ty::ValTree<'tcx>),
+    ConstVal(ConstValue<'tcx>),
+}
+
 impl<'tcx> ConstKind<'tcx> {
     #[inline]
     /// Tries to evaluate the constant if it is `Unevaluated`. If that doesn't succeed, return the
     /// unevaluated constant.
     pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self {
-        self.try_eval(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
+        self.try_eval_for_typeck(tcx, param_env).and_then(Result::ok).map_or(self, ConstKind::Value)
     }
 
     #[inline]
     /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
     /// return `None`.
     // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
-    pub fn try_eval(
+    pub fn try_eval_for_mir(
         self,
         tcx: TyCtxt<'tcx>,
         param_env: ParamEnv<'tcx>,
     ) -> Option<Result<ConstValue<'tcx>, ErrorGuaranteed>> {
+        match self.try_eval_inner(tcx, param_env, EvalMode::Mir) {
+            Some(Ok(EvalResult::ValTree(_))) => unreachable!(),
+            Some(Ok(EvalResult::ConstVal(v))) => Some(Ok(v)),
+            Some(Err(e)) => Some(Err(e)),
+            None => None,
+        }
+    }
+
+    #[inline]
+    /// Tries to evaluate the constant if it is `Unevaluated`. If that isn't possible or necessary
+    /// return `None`.
+    // FIXME(@lcnr): Completely rework the evaluation/normalization system for `ty::Const` once valtrees are merged.
+    pub fn try_eval_for_typeck(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+    ) -> Option<Result<ty::ValTree<'tcx>, ErrorGuaranteed>> {
+        match self.try_eval_inner(tcx, param_env, EvalMode::Typeck) {
+            Some(Ok(EvalResult::ValTree(v))) => Some(Ok(v)),
+            Some(Ok(EvalResult::ConstVal(_))) => unreachable!(),
+            Some(Err(e)) => Some(Err(e)),
+            None => None,
+        }
+    }
+
+    #[inline]
+    fn try_eval_inner(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+        eval_mode: EvalMode,
+    ) -> Option<Result<EvalResult<'tcx>, ErrorGuaranteed>> {
         if let ConstKind::Unevaluated(unevaluated) = self {
             use crate::mir::interpret::ErrorHandled;
 
@@ -166,14 +208,29 @@ pub fn try_eval(
             let (param_env, unevaluated) = param_env_and.into_parts();
             // try to resolve e.g. associated constants to their definition on an impl, and then
             // evaluate the const.
-            match tcx.const_eval_resolve(param_env, unevaluated, None) {
-                // NOTE(eddyb) `val` contains no lifetimes/types/consts,
-                // and we use the original type, so nothing from `substs`
-                // (which may be identity substs, see above),
-                // can leak through `val` into the const we return.
-                Ok(val) => Some(Ok(val)),
-                Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
-                Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+            match eval_mode {
+                EvalMode::Typeck => {
+                    match tcx.const_eval_resolve_for_typeck(param_env, unevaluated, None) {
+                        // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+                        // and we use the original type, so nothing from `substs`
+                        // (which may be identity substs, see above),
+                        // can leak through `val` into the const we return.
+                        Ok(val) => Some(Ok(EvalResult::ValTree(val?))),
+                        Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                    }
+                }
+                EvalMode::Mir => {
+                    match tcx.const_eval_resolve(param_env, unevaluated, None) {
+                        // NOTE(eddyb) `val` contains no lifetimes/types/consts,
+                        // and we use the original type, so nothing from `substs`
+                        // (which may be identity substs, see above),
+                        // can leak through `val` into the const we return.
+                        Ok(val) => Some(Ok(EvalResult::ConstVal(val))),
+                        Err(ErrorHandled::TooGeneric | ErrorHandled::Linted) => None,
+                        Err(ErrorHandled::Reported(e)) => Some(Err(e)),
+                    }
+                }
             }
         } else {
             None
index 418848f69d726bc731fe1cfc56c917fc29353206..973dc3dd4a10ab61e1ded24e001629b6bbf0a467 100644 (file)
@@ -1,4 +1,6 @@
 use super::ScalarInt;
+use crate::mir::interpret::{AllocId, Scalar};
+use crate::ty::{self, Ty, TyCtxt};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 
 #[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
@@ -50,4 +52,61 @@ pub fn unwrap_branch(self) -> &'tcx [Self] {
             _ => bug!("expected branch, got {:?}", self),
         }
     }
+
+    pub fn from_raw_bytes<'a>(tcx: TyCtxt<'tcx>, bytes: &'a [u8]) -> Self {
+        let branches = bytes.iter().map(|b| Self::Leaf(ScalarInt::from(*b)));
+        let interned = tcx.arena.alloc_from_iter(branches);
+
+        Self::Branch(interned)
+    }
+
+    pub fn from_scalar_int(i: ScalarInt) -> Self {
+        Self::Leaf(i)
+    }
+
+    pub fn try_to_scalar(self) -> Option<Scalar<AllocId>> {
+        self.try_to_scalar_int().map(Scalar::Int)
+    }
+
+    pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
+        match self {
+            Self::Leaf(s) => Some(s),
+            Self::Branch(_) => None,
+        }
+    }
+
+    pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
+        self.try_to_scalar_int().map(|s| s.try_to_machine_usize(tcx).ok()).flatten()
+    }
+
+    /// Get the values inside the ValTree as a slice of bytes. This only works for
+    /// constants with types &str and &[u8].
+    pub fn try_to_raw_bytes(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<&'tcx [u8]> {
+        match ty.kind() {
+            ty::Ref(_, inner_ty, _) => match inner_ty.kind() {
+                ty::Str => {
+                    let leafs = self
+                        .unwrap_branch()
+                        .into_iter()
+                        .map(|v| v.unwrap_leaf().try_to_u8().unwrap())
+                        .collect::<Vec<_>>();
+
+                    return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
+                }
+                ty::Slice(slice_ty) if *slice_ty == tcx.types.u8 => {
+                    let leafs = self
+                        .unwrap_branch()
+                        .into_iter()
+                        .map(|v| v.unwrap_leaf().try_to_u8().unwrap())
+                        .collect::<Vec<_>>();
+
+                    return Some(tcx.arena.alloc_from_iter(leafs.into_iter()));
+                }
+                _ => {}
+            },
+            _ => {}
+        }
+
+        None
+    }
 }
index 5c0cf534b80254a40bd68bab116dac1fea2472cd..0930f3edf72541e85066a704808a6326159634eb 100644 (file)
@@ -8,7 +8,7 @@
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
 use crate::middle::resolve_lifetime;
 use crate::middle::stability;
-use crate::mir::interpret::{self, Allocation, ConstAllocation, ConstValue, Scalar};
+use crate::mir::interpret::{self, Allocation, ConstAllocation};
 use crate::mir::{
     Body, BorrowCheckResult, Field, Local, Place, PlaceElem, ProjectionKind, Promoted,
 };
@@ -991,7 +991,7 @@ fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonCons
 
         CommonConsts {
             unit: mk_const(ty::ConstS {
-                kind: ty::ConstKind::Value(ConstValue::Scalar(Scalar::ZST)),
+                kind: ty::ConstKind::Value(ty::ValTree::zst()),
                 ty: types.unit,
             }),
         }
@@ -1186,11 +1186,7 @@ pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u12
             };
             debug!("layout_scalar_valid_range: attr={:?}", attr);
             if let Some(
-                &[
-                    ast::NestedMetaItem::Literal(ast::Lit {
-                        kind: ast::LitKind::Int(a, _), ..
-                    }),
-                ],
+                &[ast::NestedMetaItem::Literal(ast::Lit { kind: ast::LitKind::Int(a, _), .. })],
             ) = attr.meta_item_list().as_deref()
             {
                 Bound::Included(a)
@@ -1663,7 +1659,7 @@ macro_rules! nop_lift {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
             type Lifted = $lifted;
             fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-                if tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0.0)) {
+                if tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self.0 .0)) {
                     // SAFETY: `self` is interned and therefore valid
                     // for the entire lifetime of the `TyCtxt`.
                     Some(unsafe { mem::transmute(self) })
@@ -2248,7 +2244,11 @@ pub fn signature_unclosure(
     /// `*r == kind`.
     #[inline]
     pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind) -> Region<'tcx> {
-        if *r == kind { r } else { self.mk_region(kind) }
+        if *r == kind {
+            r
+        } else {
+            self.mk_region(kind)
+        }
     }
 
     #[allow(rustc::usage_of_ty_tykind)]
@@ -2268,7 +2268,11 @@ pub fn reuse_or_mk_predicate(
         pred: Predicate<'tcx>,
         binder: Binder<'tcx, PredicateKind<'tcx>>,
     ) -> Predicate<'tcx> {
-        if pred.kind() != binder { self.mk_predicate(binder) } else { pred }
+        if pred.kind() != binder {
+            self.mk_predicate(binder)
+        } else {
+            pred
+        }
     }
 
     pub fn mk_mach_int(self, tm: IntTy) -> Ty<'tcx> {
@@ -2413,7 +2417,11 @@ pub fn mk_unit(self) -> Ty<'tcx> {
 
     #[inline]
     pub fn mk_diverging_default(self) -> Ty<'tcx> {
-        if self.features().never_type_fallback { self.types.never } else { self.types.unit }
+        if self.features().never_type_fallback {
+            self.types.never
+        } else {
+            self.types.unit
+        }
     }
 
     #[inline]
@@ -2564,11 +2572,9 @@ pub fn intern_poly_existential_predicates(
         eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>],
     ) -> &'tcx List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
         assert!(!eps.is_empty());
-        assert!(
-            eps.array_windows()
-                .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder())
-                    != Ordering::Greater)
-        );
+        assert!(eps
+            .array_windows()
+            .all(|[a, b]| a.skip_binder().stable_cmp(self, &b.skip_binder()) != Ordering::Greater));
         self._intern_poly_existential_predicates(eps)
     }
 
@@ -2601,29 +2607,49 @@ pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
     }
 
     pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List<GenericArg<'tcx>> {
-        if ts.is_empty() { List::empty() } else { self._intern_substs(ts) }
+        if ts.is_empty() {
+            List::empty()
+        } else {
+            self._intern_substs(ts)
+        }
     }
 
     pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List<ProjectionKind> {
-        if ps.is_empty() { List::empty() } else { self._intern_projs(ps) }
+        if ps.is_empty() {
+            List::empty()
+        } else {
+            self._intern_projs(ps)
+        }
     }
 
     pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
-        if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) }
+        if ts.is_empty() {
+            List::empty()
+        } else {
+            self._intern_place_elems(ts)
+        }
     }
 
     pub fn intern_canonical_var_infos(
         self,
         ts: &[CanonicalVarInfo<'tcx>],
     ) -> CanonicalVarInfos<'tcx> {
-        if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) }
+        if ts.is_empty() {
+            List::empty()
+        } else {
+            self._intern_canonical_var_infos(ts)
+        }
     }
 
     pub fn intern_bound_variable_kinds(
         self,
         ts: &[ty::BoundVariableKind],
     ) -> &'tcx List<ty::BoundVariableKind> {
-        if ts.is_empty() { List::empty() } else { self._intern_bound_variable_kinds(ts) }
+        if ts.is_empty() {
+            List::empty()
+        } else {
+            self._intern_bound_variable_kinds(ts)
+        }
     }
 
     pub fn mk_fn_sig<I>(
index b7130e69f3501c5fd46097939d1d5518b3b3fdc0..e8dd179eac19831c92d0bb09296bb1d8852e525f 100644 (file)
@@ -369,7 +369,6 @@ pub fn resolve(
     }
 
     // This should be kept up to date with `resolve`.
-    #[instrument(level = "debug", skip(tcx))]
     pub fn resolve_opt_const_arg(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
index 7f0f3755c4b33bf501f700130d866c14d90421c2..8da447d16fbfdd2ef63a15e68a5288d03eda8126 100644 (file)
@@ -2161,22 +2161,28 @@ pub fn expect_variant_res(self, res: Res) -> &'tcx VariantDef {
     }
 
     /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
+    #[instrument(skip(self), level = "debug")]
     pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
         match instance {
-            ty::InstanceDef::Item(def) => match self.def_kind(def.did) {
-                DefKind::Const
-                | DefKind::Static(..)
-                | DefKind::AssocConst
-                | DefKind::Ctor(..)
-                | DefKind::AnonConst
-                | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
-                // If the caller wants `mir_for_ctfe` of a function they should not be using
-                // `instance_mir`, so we'll assume const fn also wants the optimized version.
-                _ => {
-                    assert_eq!(def.const_param_did, None);
-                    self.optimized_mir(def.did)
+            ty::InstanceDef::Item(def) => {
+                debug!("calling def_kind on def: {:?}", def);
+                let def_kind = self.def_kind(def.did);
+                debug!("returned from def_kind: {:?}", def_kind);
+                match def_kind {
+                    DefKind::Const
+                    | DefKind::Static(..)
+                    | DefKind::AssocConst
+                    | DefKind::Ctor(..)
+                    | DefKind::AnonConst
+                    | DefKind::InlineConst => self.mir_for_ctfe_opt_const_arg(def),
+                    // If the caller wants `mir_for_ctfe` of a function they should not be using
+                    // `instance_mir`, so we'll assume const fn also wants the optimized version.
+                    _ => {
+                        assert_eq!(def.const_param_did, None);
+                        self.optimized_mir(def.did)
+                    }
                 }
-            },
+            }
             ty::InstanceDef::VtableShim(..)
             | ty::InstanceDef::ReifyShim(..)
             | ty::InstanceDef::Intrinsic(..)
index 5ad93d778208dd1c651a619ede544dca89bb6301..7a096bbc4d96fb05456ff1d3b7d751908494fe88 100644 (file)
@@ -98,7 +98,6 @@ fn path_generic_args(
 
     // Defaults (should not be overridden):
 
-    #[instrument(skip(self), level = "debug")]
     fn default_print_def_path(
         self,
         def_id: DefId,
@@ -302,6 +301,7 @@ fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
 impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> {
     type Output = P::Type;
     type Error = P::Error;
+
     fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
         cx.print_type(*self)
     }
index 05f332cdd5fd51ce9282642dd9870c175b88c02e..3b11f7572a6403a8ab7c73ab2085c2b53bcc3305 100644 (file)
@@ -1,4 +1,4 @@
-use crate::mir::interpret::{AllocRange, ConstValue, GlobalAlloc, Pointer, Provenance, Scalar};
+use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
 use crate::ty::{
     self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable,
@@ -607,7 +607,11 @@ fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result<Self::Type, Self::Error>
                         }
                     }
                 } else {
-                    if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) }
+                    if verbose {
+                        p!(write("{:?}", infer_ty))
+                    } else {
+                        p!(write("{}", infer_ty))
+                    }
                 }
             }
             ty::Error(_) => p!("[type error]"),
@@ -1224,7 +1228,7 @@ macro_rules! print_underscore {
             }
             ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)),
             ty::ConstKind::Value(value) => {
-                return self.pretty_print_const_value(value, ct.ty(), print_ty);
+                return self.pretty_print_const_valtree(value, ct.ty(), print_ty);
             }
 
             ty::ConstKind::Bound(debruijn, bound_var) => {
@@ -1262,7 +1266,7 @@ fn pretty_print_const_scalar_ptr(
             ty::Ref(_, inner, _) => {
                 if let ty::Array(elem, len) = inner.kind() {
                     if let ty::Uint(ty::UintTy::U8) = elem.kind() {
-                        if let ty::ConstKind::Value(ConstValue::Scalar(int)) = len.kind() {
+                        if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() {
                             match self.tcx().get_global_alloc(alloc_id) {
                                 Some(GlobalAlloc::Memory(alloc)) => {
                                     let len = int.assert_bits(self.tcx().data_layout.pointer_size);
@@ -1331,7 +1335,11 @@ fn pretty_print_const_scalar_int(
             ty::Uint(_) | ty::Int(_) => {
                 let int =
                     ConstInt::new(int, matches!(ty.kind(), ty::Int(_)), ty.is_ptr_sized_integral());
-                if print_ty { p!(write("{:#?}", int)) } else { p!(write("{:?}", int)) }
+                if print_ty {
+                    p!(write("{:#?}", int))
+                } else {
+                    p!(write("{:?}", int))
+                }
             }
             // Char
             ty::Char if char::try_from(int).is_ok() => {
@@ -1408,85 +1416,64 @@ fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const,
         Ok(self)
     }
 
-    fn pretty_print_const_value(
+    fn pretty_print_const_valtree(
         mut self,
-        ct: ConstValue<'tcx>,
+        valtree: ty::ValTree<'tcx>,
         ty: Ty<'tcx>,
         print_ty: bool,
     ) -> Result<Self::Const, Self::Error> {
         define_scoped_cx!(self);
 
         if self.tcx().sess.verbose() {
-            p!(write("ConstValue({:?}: ", ct), print(ty), ")");
+            p!(write("ValTree({:?}: ", valtree), print(ty), ")");
             return Ok(self);
         }
 
         let u8_type = self.tcx().types.u8;
-
-        match (ct, ty.kind()) {
-            // Byte/string slices, printed as (byte) string literals.
-            (ConstValue::Slice { data, start, end }, ty::Ref(_, inner, _)) => {
-                match inner.kind() {
-                    ty::Slice(t) => {
-                        if *t == u8_type {
-                            // The `inspect` here is okay since we checked the bounds, and there are
-                            // no relocations (we have an active slice reference here). We don't use
-                            // this result to affect interpreter execution.
-                            let byte_str = data
-                                .inner()
-                                .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
-                            return self.pretty_print_byte_str(byte_str);
-                        }
-                    }
-                    ty::Str => {
-                        // The `inspect` here is okay since we checked the bounds, and there are no
-                        // relocations (we have an active `str` reference here). We don't use this
-                        // result to affect interpreter execution.
-                        let slice = data
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
-                        p!(write("{:?}", String::from_utf8_lossy(slice)));
-                        return Ok(self);
-                    }
-                    _ => {}
+        match (valtree, ty.kind()) {
+            (ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) => match inner_ty.kind() {
+                ty::Slice(t) if *t == u8_type => {
+                    let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                        bug!(
+                            "expected to convert valtree {:?} to raw bytes for type {:?}",
+                            valtree,
+                            t
+                        )
+                    });
+                    return self.pretty_print_byte_str(bytes);
                 }
-            }
-            (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => {
-                let n = n.kind().try_to_bits(self.tcx().data_layout.pointer_size).unwrap();
-                // cast is ok because we already checked for pointer size (32 or 64 bit) above
-                let range = AllocRange { start: offset, size: Size::from_bytes(n) };
-
-                let byte_str = alloc.inner().get_bytes(&self.tcx(), range).unwrap();
+                ty::Str => {
+                    let bytes = valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                        bug!("expected to convert valtree to raw bytes for type {:?}", ty)
+                    });
+                    p!(write("{:?}", String::from_utf8_lossy(bytes)));
+                    return Ok(self);
+                }
+                _ => {}
+            },
+            (ty::ValTree::Branch(_), ty::Array(t, _)) if *t == u8_type => {
+                let bytes = valtree.try_to_raw_bytes(self.tcx(), *t).unwrap_or_else(|| {
+                    bug!("expected to convert valtree to raw bytes for type {:?}", t)
+                });
                 p!("*");
-                p!(pretty_print_byte_str(byte_str));
+                p!(pretty_print_byte_str(bytes));
                 return Ok(self);
             }
-
             // Aggregates, printed as array/tuple/struct/variant construction syntax.
-            //
-            // NB: the `has_param_types_or_consts` check ensures that we can use
-            // the `destructure_const` query with an empty `ty::ParamEnv` without
-            // introducing ICEs (e.g. via `layout_of`) from missing bounds.
-            // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
-            // to be able to destructure the tuple into `(0u8, *mut T)
-            //
-            // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
-            // correct `ty::ParamEnv` to allow printing *all* constant values.
-            (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+            (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..))
+                if !ty.has_param_types_or_consts() =>
+            {
                 let Some(contents) = self.tcx().try_destructure_const(
-                    ty::ParamEnv::reveal_all()
-                        .and(self.tcx().mk_const(ty::ConstS { kind: ty::ConstKind::Value(ct), ty })),
+                    ty::Const::from_value(self.tcx(), valtree, ty)
                 ) else {
                     // Fall back to debug pretty printing for invalid constants.
-                    p!(write("{:?}", ct));
+                    p!(write("{:?}", valtree));
                     if print_ty {
                         p!(": ", print(ty));
                     }
                     return Ok(self);
                 };
-
                 let fields = contents.fields.iter().copied();
-
                 match *ty.kind() {
                     ty::Array(..) => {
                         p!("[", comma_sep(fields), "]");
@@ -1513,7 +1500,6 @@ fn pretty_print_const_value(
                             contents.variant.expect("destructed const of adt without variant idx");
                         let variant_def = &def.variant(variant_idx);
                         p!(print_value_path(variant_def.def_id, substs));
-
                         match variant_def.ctor_kind {
                             CtorKind::Const => {}
                             CtorKind::Fn => {
@@ -1535,21 +1521,20 @@ fn pretty_print_const_value(
                     }
                     _ => unreachable!(),
                 }
-
                 return Ok(self);
             }
-
-            (ConstValue::Scalar(scalar), _) => {
-                return self.pretty_print_const_scalar(scalar, ty, print_ty);
+            (ty::ValTree::Leaf(leaf), _) => {
+                return self.pretty_print_const_scalar_int(leaf, ty, print_ty);
             }
-
             // FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
             // their fields instead of just dumping the memory.
             _ => {}
         }
 
         // fallback
-        p!(write("{:?}", ct));
+        if valtree != ty::ValTree::zst() {
+            p!(write("{:?}", valtree));
+        }
         if print_ty {
             p!(": ", print(ty));
         }
@@ -2296,7 +2281,6 @@ pub fn pretty_wrap_binder<T, C: Fn(&T, Self) -> Result<Self, fmt::Error>>(
         Ok(inner)
     }
 
-    #[instrument(skip(self), level = "debug")]
     fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
     where
         T: TypeFoldable<'tcx>,
@@ -2309,9 +2293,8 @@ struct LateBoundRegionNameCollector<'a, 'tcx> {
         impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
             type BreakTy = ();
 
-            #[instrument(skip(self), level = "trace")]
             fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-                trace!("address: {:p}", r.0.0);
+                trace!("address: {:p}", r.0 .0);
                 if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
                     self.used_region_names.insert(name);
                 } else if let ty::RePlaceholder(ty::PlaceholderRegion {
@@ -2326,7 +2309,6 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
 
             // We collect types in order to prevent really large types from compiling for
             // a really long time. See issue #83150 for why this is necessary.
-            #[instrument(skip(self), level = "trace")]
             fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
                 let not_previously_inserted = self.type_collector.insert(ty);
                 if not_previously_inserted {
@@ -2353,6 +2335,7 @@ impl<'tcx, T, P: PrettyPrinter<'tcx>> Print<'tcx, P> for ty::Binder<'tcx, T>
 {
     type Output = P;
     type Error = P::Error;
+
     fn print(&self, cx: P) -> Result<Self::Output, Self::Error> {
         cx.in_binder(self)
     }
index 31103b8d77ea34b93ae5b52eba5921b1e3545fce..51980acd38f749d27d9923f747c6a31d2393ba05 100644 (file)
@@ -4,7 +4,6 @@
 //! types or regions but can be other things. Examples of type relations are
 //! subtyping, type equality, etc.
 
-use crate::mir::interpret::{get_slice_bytes, ConstValue, GlobalAlloc, Scalar};
 use crate::ty::error::{ExpectedFound, TypeError};
 use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
 use crate::ty::{self, ImplSubject, Term, Ty, TyCtxt, TypeFoldable};
@@ -613,9 +612,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
 
         (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index,
         (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2,
-        (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => {
-            check_const_value_eq(relation, a_val, b_val, a, b)?
-        }
+        (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val,
 
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
             if tcx.features().generic_const_exprs =>
@@ -649,66 +646,6 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
     if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) }
 }
 
-fn check_const_value_eq<'tcx, R: TypeRelation<'tcx>>(
-    relation: &mut R,
-    a_val: ConstValue<'tcx>,
-    b_val: ConstValue<'tcx>,
-    // FIXME(oli-obk): these arguments should go away with valtrees
-    a: ty::Const<'tcx>,
-    b: ty::Const<'tcx>,
-    // FIXME(oli-obk): this should just be `bool` with valtrees
-) -> RelateResult<'tcx, bool> {
-    let tcx = relation.tcx();
-    Ok(match (a_val, b_val) {
-        (ConstValue::Scalar(Scalar::Int(a_val)), ConstValue::Scalar(Scalar::Int(b_val))) => {
-            a_val == b_val
-        }
-        (
-            ConstValue::Scalar(Scalar::Ptr(a_val, _a_size)),
-            ConstValue::Scalar(Scalar::Ptr(b_val, _b_size)),
-        ) => {
-            a_val == b_val
-                || match (tcx.global_alloc(a_val.provenance), tcx.global_alloc(b_val.provenance)) {
-                    (GlobalAlloc::Function(a_instance), GlobalAlloc::Function(b_instance)) => {
-                        a_instance == b_instance
-                    }
-                    _ => false,
-                }
-        }
-
-        (ConstValue::Slice { .. }, ConstValue::Slice { .. }) => {
-            get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
-        }
-
-        (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. })
-            if a.ty().is_ref() || b.ty().is_ref() =>
-        {
-            if a.ty().is_ref() && b.ty().is_ref() {
-                alloc_a == alloc_b
-            } else {
-                false
-            }
-        }
-        (ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
-            let a_destructured = tcx.destructure_const(relation.param_env().and(a));
-            let b_destructured = tcx.destructure_const(relation.param_env().and(b));
-
-            // Both the variant and each field have to be equal.
-            if a_destructured.variant == b_destructured.variant {
-                for (a_field, b_field) in iter::zip(a_destructured.fields, b_destructured.fields) {
-                    relation.consts(*a_field, *b_field)?;
-                }
-
-                true
-            } else {
-                false
-            }
-        }
-
-        _ => false,
-    })
-}
-
 impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>> {
     fn relate<R: TypeRelation<'tcx>>(
         relation: &mut R,
index a87134d1f52e31c02c209f2daa0d1a368b161436..3d6e50f0c0622ee1869e8b0feacdeb51374c9bf7 100644 (file)
@@ -1,12 +1,16 @@
 //! See docs in build/expr/mod.rs
 
-use crate::build::{lit_to_mir_constant, Builder};
+use crate::build::{parse_float_into_constval, Builder};
+use rustc_ast as ast;
 use rustc_hir::def_id::DefId;
-use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
+use rustc_middle::mir::interpret::{
+    Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
+};
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt};
+use rustc_target::abi::Size;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
@@ -84,3 +88,54 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> {
         }
     }
 }
+
+#[instrument(skip(tcx, lit_input))]
+pub(crate) fn lit_to_mir_constant<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    lit_input: LitToConstInput<'tcx>,
+) -> Result<ConstantKind<'tcx>, LitToConstError> {
+    let LitToConstInput { lit, ty, neg } = lit_input;
+    let trunc = |n| {
+        let param_ty = ty::ParamEnv::reveal_all().and(ty);
+        let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
+        trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
+        let result = width.truncate(n);
+        trace!("trunc result: {}", result);
+        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
+    };
+
+    let value = match (lit, &ty.kind()) {
+        (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
+            let s = s.as_str();
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
+        }
+        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+            if matches!(inner_ty.kind(), ty::Slice(_)) =>
+        {
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
+        }
+        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+            let id = tcx.allocate_bytes(data);
+            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
+        }
+        (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
+            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
+        }
+        (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
+            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
+        }
+        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
+            parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
+        }
+        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
+        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
+        (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
+        _ => return Err(LitToConstError::TypeError),
+    };
+
+    Ok(ConstantKind::Val(value, ty))
+}
index 793066e43c3c79f4804a2426c67c2b87f1761be9..51f7aa642c84fefb760c52eaa94f2c10cc40da38 100644 (file)
@@ -1,7 +1,7 @@
 use crate::build;
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::scope::DropKind;
-use crate::thir::constant::parse_float;
+use crate::thir::constant::parse_float_into_scalar;
 use crate::thir::pattern::pat_from_hir;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
 use rustc_middle::middle::region;
-use rustc_middle::mir::interpret::Allocation;
-use rustc_middle::mir::interpret::{ConstValue, LitToConstError, LitToConstInput, Scalar};
+use rustc_middle::mir::interpret::{
+    Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
+};
 use rustc_middle::mir::*;
 use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_span::Symbol;
 use rustc_target::abi::Size;
 use rustc_target::spec::abi::Abi;
 
@@ -266,57 +268,6 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
     })
 }
 
-#[instrument(skip(tcx, lit_input))]
-pub(crate) fn lit_to_mir_constant<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    lit_input: LitToConstInput<'tcx>,
-) -> Result<ConstantKind<'tcx>, LitToConstError> {
-    let LitToConstInput { lit, ty, neg } = lit_input;
-    let trunc = |n| {
-        let param_ty = ty::ParamEnv::reveal_all().and(ty);
-        let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
-        trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
-        let result = width.truncate(n);
-        trace!("trunc result: {}", result);
-        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
-    };
-
-    let value = match (lit, &ty.kind()) {
-        (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
-            let s = s.as_str();
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
-        }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
-            if matches!(inner_ty.kind(), ty::Slice(_)) =>
-        {
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
-        }
-        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
-            let id = tcx.allocate_bytes(data);
-            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
-        }
-        (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
-            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
-        }
-        (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
-            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
-        }
-        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
-            parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
-        }
-        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
-        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
-        (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
-        _ => return Err(LitToConstError::TypeError),
-    };
-
-    Ok(ConstantKind::Val(value, ty))
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
 
@@ -1137,6 +1088,65 @@ fn get_unit_temp(&mut self) -> Place<'tcx> {
     }
 }
 
+fn parse_float_into_constval<'tcx>(
+    num: Symbol,
+    float_ty: ty::FloatTy,
+    neg: bool,
+) -> Option<ConstValue<'tcx>> {
+    parse_float_into_scalar(num, float_ty, neg).map(ConstValue::Scalar)
+}
+
+#[instrument(skip(tcx, lit_input))]
+pub(crate) fn lit_to_mir_constant<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    lit_input: LitToConstInput<'tcx>,
+) -> Result<ConstantKind<'tcx>, LitToConstError> {
+    let LitToConstInput { lit, ty, neg } = lit_input;
+    let trunc = |n| {
+        let param_ty = ty::ParamEnv::reveal_all().and(ty);
+        let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
+        trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
+        let result = width.truncate(n);
+        trace!("trunc result: {}", result);
+        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
+    };
+
+    let value = match (lit, &ty.kind()) {
+        (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
+            let s = s.as_str();
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
+        }
+        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
+            if matches!(inner_ty.kind(), ty::Slice(_)) =>
+        {
+            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
+            let allocation = tcx.intern_const_alloc(allocation);
+            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
+        }
+        (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
+            let id = tcx.allocate_bytes(data);
+            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
+        }
+        (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
+            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
+        }
+        (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
+            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
+        }
+        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
+            parse_float_into_constval(*n, *fty, neg).ok_or(LitToConstError::Reported)?
+        }
+        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
+        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
+        (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
+        _ => return Err(LitToConstError::TypeError),
+    };
+
+    Ok(ConstantKind::Val(value, ty))
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Builder methods are broken up into modules, depending on what kind
 // of thing is being lowered. Note that they use the `unpack` macro
index d82e6688633d01667f91a144b85fac711a41e008..cfb09ecedd635b976954d4fe578356268f211426 100644 (file)
@@ -1,13 +1,10 @@
+use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_ast as ast;
-use rustc_middle::mir::interpret::{
-    Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
-};
-use rustc_middle::ty::{self, ParamEnv, TyCtxt};
+use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput, Scalar};
+use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::Size;
 
-// FIXME Once valtrees are available, get rid of this function and the query
 pub(crate) fn lit_to_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     lit_input: LitToConstInput<'tcx>,
@@ -20,58 +17,59 @@ pub(crate) fn lit_to_const<'tcx>(
         trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
         let result = width.truncate(n);
         trace!("trunc result: {}", result);
-        Ok(ConstValue::Scalar(Scalar::from_uint(result, width)))
+
+        Ok(ScalarInt::try_from_uint(result, width)
+            .unwrap_or_else(|| bug!("expected to create ScalarInt from uint {:?}", result)))
     };
 
-    let lit = match (lit, &ty.kind()) {
+    let valtree = match (lit, &ty.kind()) {
         (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
-            let s = s.as_str();
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: s.len() }
+            let str_bytes = s.as_str().as_bytes();
+            ty::ValTree::from_raw_bytes(tcx, str_bytes)
         }
         (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _))
             if matches!(inner_ty.kind(), ty::Slice(_)) =>
         {
-            let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]);
-            let allocation = tcx.intern_const_alloc(allocation);
-            ConstValue::Slice { data: allocation, start: 0, end: data.len() }
+            let bytes = data as &[u8];
+            ty::ValTree::from_raw_bytes(tcx, bytes)
         }
         (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if inner_ty.is_array() => {
-            let id = tcx.allocate_bytes(data);
-            ConstValue::Scalar(Scalar::from_pointer(id.into(), &tcx))
+            let bytes = data as &[u8];
+            ty::ValTree::from_raw_bytes(tcx, bytes)
         }
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
-            ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
+            ty::ValTree::from_scalar_int((*n).into())
         }
         (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
-            trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
+            let scalar_int =
+                trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?;
+            ty::ValTree::from_scalar_int(scalar_int)
         }
         (ast::LitKind::Float(n, _), ty::Float(fty)) => {
-            parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)?
+            parse_float_into_valtree(*n, *fty, neg).ok_or(LitToConstError::Reported)?
         }
-        (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)),
-        (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)),
+        (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
+        (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
         (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported),
         _ => return Err(LitToConstError::TypeError),
     };
-    Ok(ty::Const::from_value(tcx, lit, ty))
+
+    Ok(ty::Const::from_value(tcx, valtree, ty))
 }
 
-// FIXME move this to rustc_mir_build::build
-pub(crate) fn parse_float<'tcx>(
+pub(crate) fn parse_float_into_scalar(
     num: Symbol,
-    fty: ty::FloatTy,
+    float_ty: ty::FloatTy,
     neg: bool,
-) -> Option<ConstValue<'tcx>> {
+) -> Option<Scalar> {
     let num = num.as_str();
-    use rustc_apfloat::ieee::{Double, Single};
-    let scalar = match fty {
+    match float_ty {
         ty::FloatTy::F32 => {
             let Ok(rust_f) = num.parse::<f32>() else { return None };
             let mut f = num.parse::<Single>().unwrap_or_else(|e| {
                 panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
             });
+
             assert!(
                 u128::from(rust_f.to_bits()) == f.to_bits(),
                 "apfloat::ieee::Single gave different result for `{}`: \
@@ -82,16 +80,19 @@ pub(crate) fn parse_float<'tcx>(
                 Single::from_bits(rust_f.to_bits().into()),
                 rust_f.to_bits()
             );
+
             if neg {
                 f = -f;
             }
-            Scalar::from_f32(f)
+
+            Some(Scalar::from_f32(f))
         }
         ty::FloatTy::F64 => {
             let Ok(rust_f) = num.parse::<f64>() else { return None };
             let mut f = num.parse::<Double>().unwrap_or_else(|e| {
                 panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e)
             });
+
             assert!(
                 u128::from(rust_f.to_bits()) == f.to_bits(),
                 "apfloat::ieee::Double gave different result for `{}`: \
@@ -102,12 +103,20 @@ pub(crate) fn parse_float<'tcx>(
                 Double::from_bits(rust_f.to_bits().into()),
                 rust_f.to_bits()
             );
+
             if neg {
                 f = -f;
             }
-            Scalar::from_f64(f)
+
+            Some(Scalar::from_f64(f))
         }
-    };
+    }
+}
 
-    Some(ConstValue::Scalar(scalar))
+fn parse_float_into_valtree<'tcx>(
+    num: Symbol,
+    float_ty: ty::FloatTy,
+    neg: bool,
+) -> Option<ty::ValTree<'tcx>> {
+    parse_float_into_scalar(num, float_ty, neg).map(|s| ty::ValTree::Leaf(s.try_to_int().unwrap()))
 }
index f694e009ab957c1ad8730734835d87891b9e07e6..b423c645447472b02be080cd0c1c10359d692b9b 100644 (file)
@@ -371,6 +371,7 @@ fn recur(
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
                 let destructured = tcx.destructure_mir_constant(param_env, cv);
+
                 PatKind::Variant {
                     adt_def: *adt_def,
                     substs,
@@ -502,7 +503,7 @@ fn recur(
                 // deref pattern.
                 _ => {
                     if !pointee_ty.is_sized(tcx.at(span), param_env) {
-                        // `tcx.deref_const()` below will ICE with an unsized type
+                        // `tcx.deref_mirconstant()` below will ICE with an unsized type
                         // (except slices, which are handled in a separate arm above).
                         let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
                         if self.include_lint_checks {
index 83175439b70fb1e0471e9d6ff46a2c18276457bb..e28cb67217c89aabf6745746832c3400854cf5d2 100644 (file)
@@ -185,11 +185,11 @@ fn normalize_range_pattern_ends(
             }
             (Some(PatKind::Constant { value: lo }), None) => {
                 let hi = ty.numeric_max_val(self.tcx)?;
-                Some((*lo, hi.into()))
+                Some((*lo, mir::ConstantKind::from_const(hi, self.tcx)))
             }
             (None, Some(PatKind::Constant { value: hi })) => {
                 let lo = ty.numeric_min_val(self.tcx)?;
-                Some((lo.into(), *hi))
+                Some((mir::ConstantKind::from_const(lo, self.tcx), *hi))
             }
             _ => None,
         }
@@ -798,11 +798,12 @@ pub(crate) fn compare_const_vals<'tcx>(
     if let ty::Str = ty.kind() && let (
         Some(a_val @ ConstValue::Slice { .. }),
         Some(b_val @ ConstValue::Slice { .. }),
-    ) = (a.try_val(), b.try_val())
+    ) = (a.try_val(tcx), b.try_val(tcx))
     {
         let a_bytes = get_slice_bytes(&tcx, a_val);
         let b_bytes = get_slice_bytes(&tcx, b_val);
         return from_bool(a_bytes == b_bytes);
     }
+
     fallback()
 }
index 027af5b9c1f2de6f4c3cc70939ada6e98482e361..8d16c5f22c3f4ab31cfccfa3bf7b6fc8c9ece0b1 100644 (file)
@@ -1032,7 +1032,7 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
         Operand::Constant(Box::new(Constant {
             span: self.source_info.span,
             user_ty: None,
-            literal: ty::Const::from_usize(self.tcx(), val.into()).into(),
+            literal: ConstantKind::from_usize(self.tcx(), val.into()),
         }))
     }
 
index 3577b3d2d80c690ef07d5e6fb34247bea409ca60..8944ebed9a70487063c2adf9c7a38779528cc768 100644 (file)
@@ -19,7 +19,7 @@ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         sess.opts.debugging_opts.unsound_mir_opts && sess.mir_opt_level() > 0
     }
 
-    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running ConstDebugInfo on {:?}", body.source);
 
         for (local, constant) in find_optimization_oportunities(body) {
index 2529a7c4232b21ec40579b2fc6553b427423b1bc..412a5b4fc9104d2d083bdd979031038ab18e6eb4 100644 (file)
@@ -67,6 +67,7 @@ fn is_enabled(&self, _sess: &rustc_session::Session) -> bool {
         true
     }
 
+    #[instrument(skip(self, tcx), level = "debug")]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         // will be evaluated by miri and produce its errors there
         if body.source.promoted.is_some() {
@@ -687,7 +688,7 @@ fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>, span: Span) -> Opera
         Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
-            literal: ty::Const::from_scalar(self.tcx, scalar, ty).into(),
+            literal: ConstantKind::from_scalar(self.tcx, scalar, ty),
         }))
     }
 
@@ -765,20 +766,12 @@ fn replace_with_const(
                             if let Some(Some(alloc)) = alloc {
                                 // Assign entire constant in a single statement.
                                 // We can't use aggregates, as we run after the aggregate-lowering `MirPhase`.
+                                let const_val = ConstValue::ByRef { alloc, offset: Size::ZERO };
+                                let literal = ConstantKind::Val(const_val, ty);
                                 *rval = Rvalue::Use(Operand::Constant(Box::new(Constant {
                                     span: source_info.span,
                                     user_ty: None,
-                                    literal: self
-                                        .ecx
-                                        .tcx
-                                        .mk_const(ty::ConstS {
-                                            ty,
-                                            kind: ty::ConstKind::Value(ConstValue::ByRef {
-                                                alloc,
-                                                offset: Size::ZERO,
-                                            }),
-                                        })
-                                        .into(),
+                                    literal,
                                 })));
                             }
                         }
index 8a9f21073165b0493edf9437d08a067629efd888..e0e27c53f1822e22b7dbb11bd3cd396ed86da5bf 100644 (file)
@@ -470,7 +470,7 @@ fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
         Rvalue::Use(Operand::Constant(Box::new(Constant {
             span,
             user_ty: None,
-            literal: ty::Const::from_bool(self.tcx, val).into(),
+            literal: ConstantKind::from_bool(self.tcx, val),
         })))
     }
 
index 89895fddd0cfabd8f6cf1847e4968f7ff5fca872..f3c67319596d14397e21e9db08fcf4b8aebdc51b 100644 (file)
@@ -991,7 +991,7 @@ fn insert_panic_block<'tcx>(
         cond: Operand::Constant(Box::new(Constant {
             span: body.span,
             user_ty: None,
-            literal: ty::Const::from_bool(tcx, false).into(),
+            literal: ConstantKind::from_bool(tcx, false),
         })),
         expected: true,
         msg: message,
index 4fbb764337863c16ec1fb72a302d40c6a1ad5b67..ea10ec5f25c1577282e45920e06ae824f9d14258 100644 (file)
@@ -3,8 +3,8 @@
 use crate::MirPass;
 use rustc_hir::Mutability;
 use rustc_middle::mir::{
-    BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
-    Statement, StatementKind, Terminator, TerminatorKind, UnOp,
+    BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
+    SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
 };
 use rustc_middle::ty::{self, TyCtxt};
 
@@ -129,8 +129,8 @@ fn combine_len(&self, source_info: &SourceInfo, rvalue: &mut Rvalue<'tcx>) {
                     return;
                 }
 
-                let constant =
-                    Constant { span: source_info.span, literal: len.into(), user_ty: None };
+                let literal = ConstantKind::from_const(len, self.tcx);
+                let constant = Constant { span: source_info.span, literal, user_ty: None };
                 *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant)));
             }
         }
index 0e52da57e60b7323706bbf48299eaad4e4532a5a..b89322514657898a84fa01274c030f4867b88ecf 100644 (file)
@@ -531,8 +531,10 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
         None => {}
         Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
     }
+    debug!("about to call mir_drops_elaborated...");
     let mut body =
         tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
+    debug!("body: {:#?}", body);
     run_optimization_passes(tcx, &mut body);
 
     debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
index 65801069560b34542e32e71c07a6e3c000e83e69..989b94b68c101443ba50c6776d270822e2eb0f7a 100644 (file)
@@ -34,7 +34,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                                     Rvalue::Use(Operand::Constant(Box::new(Constant {
                                         span: terminator.source_info.span,
                                         user_ty: None,
-                                        literal: ty::Const::zero_sized(tcx, tcx.types.unit).into(),
+                                        literal: ConstantKind::zero_sized(tcx.types.unit),
                                     }))),
                                 ))),
                             });
index f925d13b2fb91223d334e6066993080f7f526808..89808d3d4cdbd9c9056c358806eb64daf951f34c 100644 (file)
@@ -15,7 +15,7 @@ fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
         sess.panic_strategy() != PanicStrategy::Abort
     }
 
-    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("remove_noop_landing_pads({:?})", body);
         self.remove_nop_landing_pads(body)
     }
@@ -81,6 +81,8 @@ fn is_nop_landing_pad(
     }
 
     fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
+        debug!("body: {:#?}", body);
+
         // make sure there's a single resume block
         let resume_block = {
             let patch = MirPatch::new(body);
index 78a4ece2ecbb319e02b348d8e6a71311f7270f62..3be1783ae3389ad6b1061af775b473d6a38dab23 100644 (file)
@@ -430,7 +430,7 @@ fn make_clone_call(
         let func = Operand::Constant(Box::new(Constant {
             span: self.span,
             user_ty: None,
-            literal: ty::Const::zero_sized(tcx, func_ty).into(),
+            literal: ConstantKind::zero_sized(func_ty),
         }));
 
         let ref_loc = self.make_place(
@@ -630,7 +630,7 @@ fn build_call_shim<'tcx>(
                 Operand::Constant(Box::new(Constant {
                     span,
                     user_ty: None,
-                    literal: ty::Const::zero_sized(tcx, ty).into(),
+                    literal: ConstantKind::zero_sized(ty),
                 })),
                 rcvr.into_iter().collect::<Vec<_>>(),
             )
index dfaf464587be29f3701191ccaae2b116e984e576..2af22e129a5f7e67373de4020f5898bbb3c813d1 100644 (file)
@@ -323,6 +323,7 @@ pub fn iter_accesses<F>(&self, mut f: F)
     }
 }
 
+#[instrument(skip(tcx, mode), level = "debug")]
 pub fn collect_crate_mono_items(
     tcx: TyCtxt<'_>,
     mode: MonoItemCollectionMode,
@@ -362,6 +363,7 @@ pub fn collect_crate_mono_items(
 
 // Find all non-generic items by walking the HIR. These items serve as roots to
 // start monomorphizing from.
+#[instrument(skip(tcx, mode), level = "debug")]
 fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
     debug!("collecting roots");
     let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
@@ -400,6 +402,7 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
 
 /// Collect all monomorphized items reachable from `starting_point`, and emit a note diagnostic if a
 /// post-monorphization error is encountered during a collection step.
+#[instrument(skip(tcx, visited, recursion_depths, recursion_limit, inlining_map), level = "debug")]
 fn collect_items_rec<'tcx>(
     tcx: TyCtxt<'tcx>,
     starting_point: Spanned<MonoItem<'tcx>>,
@@ -752,13 +755,15 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
     /// This does not walk the constant, as it has been handled entirely here and trying
     /// to walk it would attempt to evaluate the `ty::Const` inside, which doesn't necessarily
     /// work, as some constants cannot be represented in the type system.
+    #[instrument(skip(self), level = "debug")]
     fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
         let literal = self.monomorphize(constant.literal);
         let val = match literal {
             mir::ConstantKind::Val(val, _) => val,
             mir::ConstantKind::Ty(ct) => match ct.kind() {
-                ty::ConstKind::Value(val) => val,
+                ty::ConstKind::Value(val) => self.tcx.valtree_to_const_val((ct.ty(), val)),
                 ty::ConstKind::Unevaluated(ct) => {
+                    debug!(?ct);
                     let param_env = ty::ParamEnv::reveal_all();
                     match self.tcx.const_eval_resolve(param_env, ct, None) {
                         // The `monomorphize` call should have evaluated that constant already.
@@ -778,6 +783,7 @@ fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location)
         self.visit_ty(literal.ty(), TyContext::Location(location));
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn visit_const(&mut self, constant: ty::Const<'tcx>, location: Location) {
         debug!("visiting const {:?} @ {:?}", constant, location);
 
@@ -785,7 +791,10 @@ fn visit_const(&mut self, constant: ty::Const<'tcx>, location: Location) {
         let param_env = ty::ParamEnv::reveal_all();
 
         match substituted_constant.kind() {
-            ty::ConstKind::Value(val) => collect_const_value(self.tcx, val, self.output),
+            ty::ConstKind::Value(val) => {
+                let const_val = self.tcx.valtree_to_const_val((constant.ty(), val));
+                collect_const_value(self.tcx, const_val, self.output)
+            }
             ty::ConstKind::Unevaluated(unevaluated) => {
                 match self.tcx.const_eval_resolve(param_env, unevaluated, None) {
                     // The `monomorphize` call should have evaluated that constant already.
@@ -1120,6 +1129,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
     }
 }
 
+#[instrument(skip(tcx), level = "debug")]
 fn create_fn_mono_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
@@ -1133,7 +1143,10 @@ fn create_fn_mono_item<'tcx>(
         crate::util::dump_closure_profile(tcx, instance);
     }
 
-    respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
+    let respanned = respan(source, MonoItem::Fn(instance.polymorphize(tcx)));
+    debug!(?respanned);
+
+    respanned
 }
 
 /// Creates a `MonoItem` for each method that is referenced by the vtable for
@@ -1275,6 +1288,7 @@ fn is_root(&self, def_id: LocalDefId) -> bool {
 
     /// If `def_id` represents a root, pushes it onto the list of
     /// outputs. (Note that all roots must be monomorphic.)
+    #[instrument(skip(self), level = "debug")]
     fn push_if_root(&mut self, def_id: LocalDefId) {
         if self.is_root(def_id) {
             debug!("RootCollector::push_if_root: found root def_id={:?}", def_id);
@@ -1415,17 +1429,17 @@ fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIte
 }
 
 /// Scans the MIR in order to find function calls, closures, and drop-glue.
+#[instrument(skip(tcx, output), level = "debug")]
 fn collect_neighbours<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: Instance<'tcx>,
     output: &mut MonoItems<'tcx>,
 ) {
-    debug!("collect_neighbours: {:?}", instance.def_id());
     let body = tcx.instance_mir(instance.def);
-
     MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(&body);
 }
 
+#[instrument(skip(tcx, output), level = "debug")]
 fn collect_const_value<'tcx>(
     tcx: TyCtxt<'tcx>,
     value: ConstValue<'tcx>,
index 2f7e413b087aefb1a0de83c0030c6aafcab81fc1..f67b87a6a52b8e08d0d526ffa6d4d5c0b2ca8705 100644 (file)
@@ -1,7 +1,6 @@
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::CrateNum;
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
-use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::print::{PrettyPrinter, Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
@@ -30,6 +29,7 @@ pub(super) fn mangle<'tcx>(
         match key.disambiguated_data.data {
             DefPathData::TypeNs(_) | DefPathData::ValueNs(_) => {
                 instance_ty = tcx.type_of(ty_def_id);
+                debug!(?instance_ty);
                 break;
             }
             _ => {
@@ -261,10 +261,7 @@ fn print_dyn_existential(
     fn print_const(self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
         // only print integers
         match (ct.kind(), ct.ty().kind()) {
-            (
-                ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(scalar))),
-                ty::Int(_) | ty::Uint(_),
-            ) => {
+            (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => {
                 // The `pretty_print_const` formatting depends on -Zverbose
                 // flag, so we cannot reuse it here.
                 let signed = matches!(ct.ty().kind(), ty::Int(_));
index f79f7a4ebdfc818edd6d5c9dc4629ca08f4f3490..ff07063679746392e98b8bb4e2cb0d4c893a95f5 100644 (file)
@@ -5,7 +5,6 @@
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::print::{Print, Printer};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
@@ -604,16 +603,18 @@ fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error
         if let Some(&i) = self.consts.get(&ct) {
             return self.print_backref(i);
         }
+
         let start = self.out.len();
+        let ty = ct.ty();
 
-        match ct.ty().kind() {
+        match ty.kind() {
             ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => {
-                self = ct.ty().print(self)?;
+                self = ty.print(self)?;
 
-                let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ct.ty());
+                let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all(), ty);
 
                 // Negative integer values are mangled using `n` as a "sign prefix".
-                if let ty::Int(ity) = ct.ty().kind() {
+                if let ty::Int(ity) = ty.kind() {
                     let val =
                         Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128;
                     if val < 0 {
@@ -626,45 +627,57 @@ fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error
             }
 
             // HACK(eddyb) because `ty::Const` only supports sized values (for now),
-            // we can't use `deref_const` + supporting `str`, we have to specially
+            // we can't use dereference the const + supporting `str`, we have to specially
             // handle `&str` and include both `&` ("R") and `str` ("e") prefixes.
-            ty::Ref(_, ty, hir::Mutability::Not) if *ty == self.tcx.types.str_ => {
-                self.push("R");
-                match ct.kind() {
-                    ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => {
-                        // NOTE(eddyb) the following comment was kept from `ty::print::pretty`:
-                        // The `inspect` here is okay since we checked the bounds, and there are no
-                        // relocations (we have an active `str` reference here). We don't use this
-                        // result to affect interpreter execution.
-                        let slice = data
-                            .inner()
-                            .inspect_with_uninit_and_ptr_outside_interpreter(start..end);
-                        let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
-
-                        self.push("e");
-                        // FIXME(eddyb) use a specialized hex-encoding loop.
-                        for byte in s.bytes() {
-                            let _ = write!(self.out, "{:02x}", byte);
+            ty::Ref(_, inner_ty, mutbl) => {
+                self.push(match mutbl {
+                    hir::Mutability::Not => "R",
+                    hir::Mutability::Mut => "Q",
+                });
+
+                match inner_ty.kind() {
+                    ty::Str if *mutbl == hir::Mutability::Not => {
+                        match ct.kind() {
+                            ty::ConstKind::Value(valtree) => {
+                                let slice =
+                                    valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| {
+                                        bug!(
+                                        "expected to get raw bytes from valtree {:?} for type {:}",
+                                        valtree, ty
+                                    )
+                                    });
+                                let s = std::str::from_utf8(slice).expect("non utf8 str from miri");
+
+                                self.push("e");
+
+                                // FIXME(eddyb) use a specialized hex-encoding loop.
+                                for byte in s.bytes() {
+                                    let _ = write!(self.out, "{:02x}", byte);
+                                }
+
+                                self.push("_");
+                            }
+
+                            _ => {
+                                bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
+                            }
                         }
-                        self.push("_");
                     }
-
                     _ => {
-                        bug!("symbol_names: unsupported `&str` constant: {:?}", ct);
+                        let pointee_ty = ct
+                            .ty()
+                            .builtin_deref(true)
+                            .expect("tried to dereference on non-ptr type")
+                            .ty;
+                        let dereferenced_const =
+                            self.tcx.mk_const(ty::ConstS { val: ct.val(), ty: pointee_ty });
+                        self = dereferenced_const.print(self)?;
                     }
                 }
             }
 
-            ty::Ref(_, _, mutbl) => {
-                self.push(match mutbl {
-                    hir::Mutability::Not => "R",
-                    hir::Mutability::Mut => "Q",
-                });
-                self = self.tcx.deref_const(ty::ParamEnv::reveal_all().and(ct)).print(self)?;
-            }
-
-            ty::Array(..) | ty::Tuple(..) | ty::Adt(..) => {
-                let contents = self.tcx.destructure_const(ty::ParamEnv::reveal_all().and(ct));
+            ty::Array(..) | ty::Tuple(..) | ty::Adt(..) | ty::Slice(_) => {
+                let contents = self.tcx.destructure_const(ct);
                 let fields = contents.fields.iter().copied();
 
                 let print_field_list = |mut this: Self| {
@@ -676,7 +689,7 @@ fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error
                 };
 
                 match *ct.ty().kind() {
-                    ty::Array(..) => {
+                    ty::Array(..) | ty::Slice(_) => {
                         self.push("A");
                         self = print_field_list(self)?;
                     }
@@ -723,7 +736,6 @@ fn print_const(mut self, ct: ty::Const<'tcx>) -> Result<Self::Const, Self::Error
                     _ => unreachable!(),
                 }
             }
-
             _ => {
                 bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct);
             }
index c95d43b71cf1b619edc73bfa574c97c7a91c7c79..a63790b594d83cbb982dc5418f6c305da1849d6a 100644 (file)
@@ -6,6 +6,7 @@
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
 use crate::infer::InferCtxt;
 use crate::traits::project::ProjectAndUnifyResult;
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{Region, RegionVid, Term};
 
@@ -834,7 +835,16 @@ fn evaluate_nested_obligations(
                                 unevaluated,
                                 Some(obligation.cause.span),
                             ) {
-                                Ok(val) => Ok(ty::Const::from_value(select.tcx(), val, c.ty())),
+                                Ok(Some(valtree)) => {
+                                    Ok(ty::Const::from_value(select.tcx(), valtree, c.ty()))
+                                }
+                                Ok(None) => {
+                                    let tcx = self.tcx;
+                                    let def_id = unevaluated.def.did;
+                                    let reported = tcx.sess.struct_span_err(tcx.def_span(def_id), &format!("unable to construct a constant value for the unevaluated constant {:?}", unevaluated)).emit();
+
+                                    Err(ErrorHandled::Reported(reported))
+                                }
                                 Err(err) => Err(err),
                             }
                         } else {
index 6cf39be2a9d5c2004c305755d462597d5e3df746..5d08ea99ac64a2975c3917fda763de80518eae22 100644 (file)
@@ -13,9 +13,7 @@
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{
-    ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar,
-};
+use rustc_middle::mir::interpret::{ErrorHandled, LitToConstError, LitToConstInput};
 use rustc_middle::thir;
 use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
 use rustc_middle::ty::subst::{Subst, SubstsRef};
@@ -449,9 +447,8 @@ fn recurse_build(&mut self, node: thir::ExprId) -> Result<NodeId, ErrorGuarantee
                 self.nodes.push(Node::Leaf(constant))
             }
             &ExprKind::NonHirLiteral { lit , user_ty: _} => {
-                // FIXME Construct a Valtree from this ScalarInt when introducing Valtrees
-                let const_value = ConstValue::Scalar(Scalar::Int(lit));
-                self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, const_value, node.ty)))
+                let val = ty::ValTree::from_scalar_int(lit);
+                self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
             }
             &ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
                 let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
index 50735ef048bf61a31bab1ec426ae3fa7a423c887..7c4b5decee4f499a8f4c9e395bb7a5ff66965ef7 100644 (file)
@@ -407,7 +407,7 @@ fn process_changed_obligations(
                     let pred =
                         ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
                     ProcessResult::Changed(mk_pending(vec![
-                        obligation.with(pred.to_predicate(self.selcx.tcx())),
+                        obligation.with(pred.to_predicate(self.selcx.tcx()))
                     ]))
                 }
                 ty::PredicateKind::TypeWellFormedFromEnv(..) => {
@@ -594,22 +594,24 @@ fn process_changed_obligations(
 
                     let mut evaluate = |c: Const<'tcx>| {
                         if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
-                            match self.selcx.infcx().const_eval_resolve(
+                            match self.selcx.infcx().try_const_eval_resolve(
                                 obligation.param_env,
                                 unevaluated,
+                                c.ty(),
                                 Some(obligation.cause.span),
                             ) {
-                                Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty())),
-                                Err(ErrorHandled::TooGeneric) => {
-                                    stalled_on.extend(
-                                        unevaluated
-                                            .substs
-                                            .iter()
-                                            .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
-                                    );
-                                    Err(ErrorHandled::TooGeneric)
-                                }
-                                Err(err) => Err(err),
+                                Ok(val) => Ok(val),
+                                Err(e) => match e {
+                                    ErrorHandled::TooGeneric => {
+                                        stalled_on.extend(
+                                            unevaluated.substs.iter().filter_map(
+                                                TyOrConstInferVar::maybe_from_generic_arg,
+                                            ),
+                                        );
+                                        Err(ErrorHandled::TooGeneric)
+                                    }
+                                    _ => Err(e),
+                                },
                             }
                         } else {
                             Ok(c)
index 565f3f509db3903a3ca5b32f687a5818a2579a9e..a72f90746edfa70b0d19ab18191d5da18ddcf623 100644 (file)
@@ -618,11 +618,14 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         }
     }
 
+    #[instrument(skip(self), level = "debug")]
     fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
         if self.selcx.tcx().lazy_normalization() || !self.eager_inference_replacement {
             constant
         } else {
             let constant = constant.super_fold_with(self);
+            debug!(?constant);
+            debug!("self.param_env: {:?}", self.param_env);
             constant.eval(self.selcx.tcx(), self.param_env)
         }
     }
index b00f8fe73a1de42bf69d3b3ea5e9e6ac3bc51d5d..b80a27eb07d061373d5620dc72a4b80fe24dd29c 100644 (file)
@@ -100,7 +100,7 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
     }
 }
 
-/// Visitor to find the maximum escaping bound var
+// Visitor to find the maximum escaping bound var
 struct MaxEscapingBoundVarVisitor {
     // The index which would count as escaping
     outer_index: ty::DebruijnIndex,
@@ -336,12 +336,15 @@ fn try_fold_mir_const(
     ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
         Ok(match constant {
             mir::ConstantKind::Ty(c) => {
-                let const_folded = c.try_fold_with(self)?;
+                let const_folded = c.try_super_fold_with(self)?;
                 match const_folded.kind() {
-                    ty::ConstKind::Value(cv) => {
-                        // FIXME With Valtrees we need to convert `cv: ValTree`
-                        // to a `ConstValue` here.
-                        mir::ConstantKind::Val(cv, const_folded.ty())
+                    ty::ConstKind::Value(valtree) => {
+                        let tcx = self.infcx.tcx;
+                        let ty = const_folded.ty();
+                        let const_val = tcx.valtree_to_const_val((ty, valtree));
+                        debug!(?ty, ?valtree, ?const_val);
+
+                        mir::ConstantKind::Val(const_val, ty)
                     }
                     _ => mir::ConstantKind::Ty(const_folded),
                 }
index 07e7bad6cb787838fafb01dead8b878aef9c57f9..a002006f0e67674d99910cca714a602082dd15ac 100644 (file)
@@ -636,13 +636,15 @@ fn evaluate_predicate_recursively<'o>(
 
                     let evaluate = |c: ty::Const<'tcx>| {
                         if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
-                            self.infcx
-                                .const_eval_resolve(
-                                    obligation.param_env,
-                                    unevaluated,
-                                    Some(obligation.cause.span),
-                                )
-                                .map(|val| ty::Const::from_value(self.tcx(), val, c.ty()))
+                            match self.infcx.try_const_eval_resolve(
+                                obligation.param_env,
+                                unevaluated,
+                                c.ty(),
+                                Some(obligation.cause.span),
+                            ) {
+                                Ok(val) => Ok(val),
+                                Err(e) => Err(e),
+                            }
                         } else {
                             Ok(c)
                         }
@@ -2576,7 +2578,11 @@ fn head(&self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
     }
 
     fn depth(&self) -> usize {
-        if let Some(head) = self.head { head.depth } else { 0 }
+        if let Some(head) = self.head {
+            head.depth
+        } else {
+            0
+        }
     }
 }
 
index a8a324dec97ba7045f440a3703f9f307b13e3417..5d394ed2263ffc8141c96414eb02c4675acaed62 100644 (file)
@@ -25,7 +25,6 @@ pub(crate) fn provide(p: &mut Providers) {
     };
 }
 
-#[instrument(level = "debug", skip(tcx))]
 fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + Copy>(
     tcx: TyCtxt<'tcx>,
     goal: ParamEnvAnd<'tcx, T>,
index 7c89ce125e01d771c906b0f5dcdd86d149948272..552db5406df8d3ac6c0c33f2c6dda3a71b8cf065 100644 (file)
@@ -112,7 +112,6 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 }
 
-#[instrument(level = "debug", skip(tcx))]
 fn resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
@@ -141,7 +140,6 @@ fn resolve_instance_of_const_arg<'tcx>(
     )
 }
 
-#[instrument(level = "debug", skip(tcx))]
 fn inner_resolve_instance<'tcx>(
     tcx: TyCtxt<'tcx>,
     key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
index e7da6eff51959e4d5b4721a1035294e797c7a74e..7125a7578bd8155ecaba7ac85f9d0a38cbe5f311 100644 (file)
@@ -15,7 +15,6 @@
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -264,13 +263,13 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
 }
 
 pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option<String> {
-    tcx.const_eval_poly(def_id).ok().and_then(|val| {
+    tcx.const_eval_poly_for_typeck(def_id).ok().and_then(|val| {
         let ty = tcx.type_of(def_id);
         match (val, ty.kind()) {
             (_, &ty::Ref(..)) => None,
-            (ConstValue::Scalar(_), &ty::Adt(_, _)) => None,
-            (ConstValue::Scalar(_), _) => {
-                let const_ = ty::Const::from_value(tcx, val, ty);
+            (Some(ty::ValTree::Branch(_)), &ty::Adt(_, _)) => None,
+            (Some(ty::ValTree::Leaf(_)), _) => {
+                let const_ = ty::Const::from_value(tcx, val.unwrap(), ty);
                 Some(print_const_with_custom_print_scalar(tcx, const_))
             }
             _ => None,
@@ -308,10 +307,10 @@ fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: ty::Const<'_>) -> S
     // Use a slightly different format for integer types which always shows the actual value.
     // For all other types, fallback to the original `pretty_print_const`.
     match (ct.kind(), ct.ty().kind()) {
-        (ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Uint(ui)) => {
+        (ty::ConstKind::Value(ty::ValTree::Leaf(int)), ty::Uint(ui)) => {
             format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str())
         }
-        (ty::ConstKind::Value(ConstValue::Scalar(int)), ty::Int(i)) => {
+        (ty::ConstKind::Value(ty::ValTree::Leaf(int)), ty::Int(i)) => {
             let ty = tcx.lift(ct.ty()).unwrap();
             let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
             let data = int.assert_bits(size);
index 9e449de0cf5acdf4357ea119e43b5132f2cd53cd..d32df9544997e628b9c466fb4ddabd4b67795137 100644 (file)
@@ -14,7 +14,7 @@ impl Tr for str {
     type Arr = [u8; 8];
     #[cfg(cfail)]
     type Arr = [u8; Self::C];
-    //[cfail]~^ ERROR cycle detected when simplifying constant
+    //[cfail]~^ ERROR cycle detected when evaluate type-level constant
 }
 
 fn main() {}
index 5b1ffc76fe5b3ebb1296d90935af34f4423a5543..d23203742f07be35e6b4fd48ca2e9ee1c1a68ef6 100644 (file)
@@ -19,10 +19,10 @@ fn main() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/box_expr.rs:7:9: 7:10
         _2 = SizeOf(S);                  // scope 2 at $DIR/box_expr.rs:7:13: 7:25
         _3 = AlignOf(S);                 // scope 2 at $DIR/box_expr.rs:7:13: 7:25
-        _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/box_expr.rs:7:13: 7:25
+        _4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 2 at $DIR/box_expr.rs:7:13: 7:25
                                          // mir::Constant
                                          // + span: $DIR/box_expr.rs:7:13: 7:25
-                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
     }
 
     bb1: {
index ef651f01c9b98df9f3b3c9091973dce8bdf0b81c..e2acd610b80530cf6c0e4909d089c7cd33455a19 100644 (file)
@@ -21,44 +21,44 @@ fn main() -> () {
 }
 
 alloc1 (static: FOO, size: 16, align: 8) {
-    â•¾â”€â”€â”€â”€â”€â”€â”€alloc28───────╼ 03 00 00 00 00 00 00 00 â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼........
+    â•¾â”€â”€â”€â”€â”€â”€â”€alloc22───────╼ 03 00 00 00 00 00 00 00 â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼........
 }
 
-alloc28 (size: 72, align: 8) {
-    0x00 â”‚ 00 00 00 00 __ __ __ __ â•¾â”€â”€â”€â”€â”€â”€â”€alloc13───────╼ â”‚ ....░░░░╾──────╼
+alloc22 (size: 72, align: 8) {
+    0x00 â”‚ 00 00 00 00 __ __ __ __ â•¾â”€â”€â”€â”€â”€â”€â”€alloc9────────╼ â”‚ ....░░░░╾──────╼
     0x10 â”‚ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ â”‚ ............â–‘â–‘â–‘â–‘
-    0x20 â”‚ â•¾â”€â”€â”€â”€â”€â”€â”€alloc18───────╼ 02 00 00 00 00 00 00 00 â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼........
-    0x30 â”‚ 01 00 00 00 2a 00 00 00 â•¾â”€â”€â”€â”€â”€â”€â”€alloc26───────╼ â”‚ ....*...╾──────╼
+    0x20 â”‚ â•¾â”€â”€â”€â”€â”€â”€â”€alloc14───────╼ 02 00 00 00 00 00 00 00 â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼........
+    0x30 â”‚ 01 00 00 00 2a 00 00 00 â•¾â”€â”€â”€â”€â”€â”€â”€alloc20───────╼ â”‚ ....*...╾──────╼
     0x40 â”‚ 03 00 00 00 00 00 00 00                         â”‚ ........
 }
 
-alloc13 (size: 0, align: 8) {}
+alloc9 (size: 0, align: 8) {}
 
-alloc18 (size: 16, align: 8) {
-    â•¾â”€â”€â”€â”€â”€â”€â”€alloc16───────╼ â•¾â”€â”€â”€â”€â”€â”€â”€alloc17───────╼ â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼â•¾â”€â”€â”€â”€â”€â”€â•¼
+alloc14 (size: 16, align: 8) {
+    â•¾â”€â”€â”€â”€â”€â”€â”€alloc12───────╼ â•¾â”€â”€â”€â”€â”€â”€â”€alloc13───────╼ â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼â•¾â”€â”€â”€â”€â”€â”€â•¼
 }
 
-alloc16 (size: 1, align: 1) {
+alloc12 (size: 1, align: 1) {
     05                                              â”‚ .
 }
 
-alloc17 (size: 1, align: 1) {
+alloc13 (size: 1, align: 1) {
     06                                              â”‚ .
 }
 
-alloc26 (size: 24, align: 8) {
-    0x00 â”‚ â•¾â”€â”€â”€â”€â”€alloc22+0x3─────╼ â•¾â”€â”€â”€â”€â”€â”€â”€alloc23───────╼ â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼â•¾â”€â”€â”€â”€â”€â”€â•¼
-    0x10 â”‚ â•¾â”€â”€â”€â”€â”€alloc25+0x2─────╼                         â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼
+alloc20 (size: 24, align: 8) {
+    0x00 â”‚ â•¾â”€â”€â”€â”€â”€alloc17+0x3─────╼ â•¾â”€â”€â”€â”€â”€â”€â”€alloc18───────╼ â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼â•¾â”€â”€â”€â”€â”€â”€â•¼
+    0x10 â”‚ â•¾â”€â”€â”€â”€â”€alloc19+0x2─────╼                         â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼
 }
 
-alloc22 (size: 4, align: 1) {
+alloc17 (size: 4, align: 1) {
     2a 45 15 6f                                     â”‚ *E.o
 }
 
-alloc23 (size: 1, align: 1) {
+alloc18 (size: 1, align: 1) {
     2a                                              â”‚ *
 }
 
-alloc25 (size: 4, align: 1) {
+alloc19 (size: 4, align: 1) {
     2a 45 15 6f                                     â”‚ *E.o
 }
index 342c987343eac911b82231fad01546734c2c1a35..6a490e48b8ed34c6e42fd5af27ce4cbbf3129a47 100644 (file)
           StorageLive(_3);                 // scope 0 at $DIR/boxes.rs:12:14: 12:22
 -         _4 = SizeOf(i32);                // scope 2 at $DIR/boxes.rs:12:14: 12:22
 -         _5 = AlignOf(i32);               // scope 2 at $DIR/boxes.rs:12:14: 12:22
--         _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
+-         _6 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
 +         _4 = const 4_usize;              // scope 2 at $DIR/boxes.rs:12:14: 12:22
 +         _5 = const 4_usize;              // scope 2 at $DIR/boxes.rs:12:14: 12:22
-+         _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
++         _6 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
                                            // mir::Constant
                                            // + span: $DIR/boxes.rs:12:14: 12:22
-                                           // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                           // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
       }
   
       bb1: {
index e131adae2b683c731c91f0195d5d672c71874caf..832a773777707066ab713af9810239c1c05decd8 100644 (file)
           StorageLive(_1);                 // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12
           _2 = SizeOf(std::boxed::Box<u32>); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
           _3 = AlignOf(std::boxed::Box<u32>); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
-          _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
+          _4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12
                                            // mir::Constant
                                            // + span: $DIR/derefer_inline_test.rs:10:5: 10:12
-                                           // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                           // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
       }
   
       bb1: {
       }
   
       bb7 (cleanup): {
-          _6 = alloc::alloc::box_free::<Box<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::boxed::Box<u32>>), move (_5.1: std::alloc::Global)) -> bb6; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12
+          _6 = : unsafe fn(Unique::<Box<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Box<u32>, std::alloc::Global>}(move (_5.0: std::ptr::Unique<std::boxed::Box<u32>>), move (_5.1: std::alloc::Global)) -> bb6; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12
                                            // mir::Constant
                                            // + span: $DIR/derefer_inline_test.rs:10:11: 10:12
-                                           // + literal: Const { ty: unsafe fn(Unique<Box<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Box<u32>, std::alloc::Global>}, val: Value(Scalar(<ZST>)) }
+                                           // + literal: Const { ty: unsafe fn(Unique<Box<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Box<u32>, std::alloc::Global>}, val: Value(ValTree::Branch(..)) }
       }
   
       bb8 (cleanup): {
index c19cbe3e5b0dfe75b126c0cbcbab316f9833fef9..806e7b269e249a376743d8ae77cd54ed90f2d1ff 100644 (file)
           StorageLive(_1);                 // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
           _2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
           _3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
-          _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
+          _4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
                                            // mir::Constant
                                            // + span: $DIR/inline-into-box-place.rs:8:29: 8:43
-                                           // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                           // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
       }
   
       bb1: {
@@ -36,7 +36,7 @@
 +         StorageLive(_7);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         _7 = &mut (*_5);                 // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
 +         StorageLive(_8);                 // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+         _8 = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: NonNull::<u32> { pointer: {0x4 as *const u32} }, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         _8 = const alloc::raw_vec::RawVec::<u32>::NEW; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
                                            // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:33: 8:41
 -                                          // + user_ty: UserType(1)
@@ -46,7 +46,7 @@
 -     bb2: {
 +                                          // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +                                          // + user_ty: UserType(0)
-+                                          // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef(..)) }
++                                          // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
 +         Deinit((*_7));                   // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +         ((*_7).0: alloc::raw_vec::RawVec<u32>) = move _8; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 +         ((*_7).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 -     }
 - 
 -     bb5 (cleanup): {
--         _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
+-         _6 = : unsafe fn(Unique::<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline-into-box-place.rs:8:42: 8:43
--                                          // + literal: Const { ty: unsafe fn(Unique<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}, val: Value(Scalar(<ZST>)) }
+-                                          // + literal: Const { ty: unsafe fn(Unique<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}, val: Value(ValTree::Branch(..)) }
       }
   }
   
index 4d06b91e6dc61a87733919cc49623c77a3b93ca2..0a18710b2cc6f2c3b31744f949a77f630687ab5b 100644 (file)
@@ -31,10 +31,10 @@ fn test() -> Option<Box<u32>> {
         StorageLive(_1);                 // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
         _2 = SizeOf(u32);                // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
         _3 = AlignOf(u32);               // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
-        _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
+        _4 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _2, move _3) -> bb1; // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
                                          // mir::Constant
                                          // + span: $DIR/issue-62289.rs:9:10: 9:21
-                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
     }
 
     bb1: {
index 382c89a1fb9b544c5fc568ed5fb4df3cc439d08d..c555e0441f42325c4e8654b8f387c360d6e89eaf 100644 (file)
@@ -23,7 +23,7 @@
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/region-subtyping-basic.rs:16:11: 16:11
-    let mut _1: [usize; Const { ty: usize, kind: Value(Scalar(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
+    let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x0000000000000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14
     let _3: usize;                       // in scope 0 at $DIR/region-subtyping-basic.rs:18:16: 18:17
     let mut _4: usize;                   // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
     let mut _5: bool;                    // in scope 0 at $DIR/region-subtyping-basic.rs:18:14: 18:18
@@ -63,7 +63,7 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region-subtyping-basic.rs:19:9: 19:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
         _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
-        switchInt(move _7) -> [Const(Value(Scalar(0x00)): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
+        switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region-subtyping-basic.rs:20:8: 20:12
     }
 
     bb2: {
index 09cf06cacd92085b4e10349c68cf3fe404fa206b..8ae79b660446270068eb55b0645443c5a577c4b4 100644 (file)
@@ -8,10 +8,10 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () {
     bb0: {
         Retag([raw] _1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        _3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _3 = : for<'r> fn(&'r mut Test) {<Test as Drop>::drop}(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                         // + literal: Const { ty: for<'r> fn(&'r mut Test) {<Test as Drop>::drop}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: for<'r> fn(&'r mut Test) {<Test as Drop>::drop}, val: Value(ValTree::Branch(..)) }
     }
 
     bb1: {
index d7d2cdf9b0c7577c76c0f828b9af23e2b7db1695..3b241264aacfaa7e6f647900e6f9b90cfa6c552f 100644 (file)
@@ -30,10 +30,10 @@ fn move_out_by_subslice() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
         _3 = SizeOf(i32);                // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
         _4 = AlignOf(i32);               // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
-        _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+        _5 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
                                          // mir::Constant
                                          // + span: $DIR/uniform_array_move_out.rs:11:14: 11:19
-                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
     }
 
     bb1: {
@@ -49,10 +49,10 @@ fn move_out_by_subslice() -> () {
         StorageLive(_7);                 // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
         _8 = SizeOf(i32);                // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
         _9 = AlignOf(i32);               // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
-        _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+        _10 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
                                          // mir::Constant
                                          // + span: $DIR/uniform_array_move_out.rs:11:21: 11:26
-                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
     }
 
     bb3: {
index 18bc1a17c1b50abe24a283d5b59c88e73a2b3c8e..c59e92dc8292748af51191b68711f285199856ef 100644 (file)
@@ -30,10 +30,10 @@ fn move_out_from_end() -> () {
         StorageLive(_2);                 // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
         _3 = SizeOf(i32);                // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
         _4 = AlignOf(i32);               // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
-        _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+        _5 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
                                          // mir::Constant
                                          // + span: $DIR/uniform_array_move_out.rs:5:14: 5:19
-                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
     }
 
     bb1: {
@@ -49,10 +49,10 @@ fn move_out_from_end() -> () {
         StorageLive(_7);                 // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
         _8 = SizeOf(i32);                // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
         _9 = AlignOf(i32);               // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
-        _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+        _10 = : unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
                                          // mir::Constant
                                          // + span: $DIR/uniform_array_move_out.rs:5:21: 5:26
-                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) }
     }
 
     bb3: {
index 5dc81b787a9fadab5d3242f6b398c50481a0edc0..3aa95cd3f105f0a4caeed297ef4878f12b3ea2f0 100644 (file)
@@ -31,9 +31,9 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () {
 
     bb6: {
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        _3 = <Vec<i32> as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _3 = : for<'r> fn(&'r mut Vec::<i32>) {<Vec<i32> as Drop>::drop}(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                         // + literal: Const { ty: for<'r> fn(&'r mut Vec<i32>) {<Vec<i32> as Drop>::drop}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: for<'r> fn(&'r mut Vec<i32>) {<Vec<i32> as Drop>::drop}, val: Value(ValTree::Branch(..)) }
     }
 }
index 2f1858d39b3c6743218b3cd606bdce3751047722..a1c6840a0f1b364e3f80035f1ce6212e94854f7d 100644 (file)
@@ -1,9 +1,9 @@
 // build-fail
-//~^ ERROR cycle detected when normalizing `<() as Tr>::A` [E0391]
 
 // Cyclic assoc. const defaults don't error unless *used*
 trait Tr {
     const A: u8 = Self::B;
+    //~^ cycle detected when const-evaluating + checking `Tr::A`
 
     const B: u8 = Self::A;
 }
index 3fb4ab72fe6d61239e0d890b776b6026eb6858d3..550897790e9ff1fd8396a4b9f297f95490bef4e2 100644 (file)
@@ -1,37 +1,15 @@
-error[E0391]: cycle detected when normalizing `<() as Tr>::A`
-   |
-note: ...which requires simplifying constant for the type system `Tr::A`...
-  --> $DIR/defaults-cyclic-fail.rs:6:5
-   |
-LL |     const A: u8 = Self::B;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `Tr::A`...
-  --> $DIR/defaults-cyclic-fail.rs:6:5
-   |
-LL |     const A: u8 = Self::B;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `Tr::A`...
-  --> $DIR/defaults-cyclic-fail.rs:6:5
+error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
+  --> $DIR/defaults-cyclic-fail.rs:5:5
    |
 LL |     const A: u8 = Self::B;
    |     ^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<() as Tr>::B`...
-note: ...which requires simplifying constant for the type system `Tr::B`...
-  --> $DIR/defaults-cyclic-fail.rs:8:5
    |
-LL |     const B: u8 = Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `Tr::B`...
-  --> $DIR/defaults-cyclic-fail.rs:8:5
-   |
-LL |     const B: u8 = Self::A;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `Tr::B`...
   --> $DIR/defaults-cyclic-fail.rs:8:5
    |
 LL |     const B: u8 = Self::A;
    |     ^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires normalizing `<() as Tr>::A`, completing the cycle
+   = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
 note: cycle used when const-evaluating + checking `main::promoted[1]`
   --> $DIR/defaults-cyclic-fail.rs:14:1
    |
index 3d696bb049cd986b7e2d8388ba7d15b049c1e5d5..8c85fadf6001425401fe4ce03adf4b98f85b2e67 100644 (file)
@@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-249
 LL |     const BAR: u32 = IMPL_REF_BAR;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which requires normalizing `IMPL_REF_BAR`...
-note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
-   |
-LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`...
+note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
    |
 LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
@@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
    |
 LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
-   |
-LL |     const BAR: u32 = IMPL_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
-   |
-LL |     const BAR: u32 = IMPL_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
    |
index 71e26245e16af486c80049684235e3f8e6614af4..251a69aeabaa2d31ed5d167a3eb9a968a8942ad6 100644 (file)
@@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for `FooDefault::BAR`
 LL |     const BAR: u32 = DEFAULT_REF_BAR;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which requires normalizing `DEFAULT_REF_BAR`...
-note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
-   |
-LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `DEFAULT_REF_BAR`...
+note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
    |
 LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
@@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
    |
 LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<GlobalDefaultRef as FooDefault>::BAR`...
-note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
-   |
-LL |     const BAR: u32 = DEFAULT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `FooDefault::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
-   |
-LL |     const BAR: u32 = DEFAULT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `FooDefault::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
    |
index 020d758e153c2fcc8064bb8ece6df5d87d9770da..45e911d002912f57db4edbb2e1938115580ee758 100644 (file)
@@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-249
 LL |     const BAR: u32 = TRAIT_REF_BAR;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: ...which requires normalizing `TRAIT_REF_BAR`...
-note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
-   |
-LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`...
+note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
    |
 LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
@@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
    |
 LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `<GlobalTraitRef as Foo>::BAR`...
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
-   |
-LL |     const BAR: u32 = TRAIT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
-  --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
-   |
-LL |     const BAR: u32 = TRAIT_REF_BAR;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
    |
index 356517745ffcdad739dc9bec27746e192812472e..9b60612037dd6e76d9792b3e58fe201d8cb592f6 100644 (file)
@@ -2,6 +2,8 @@
 // The `panic!()` below is important to trigger the fixed ICE.
 
 const _CONST: &[u8] = &f(&[], |_| {});
+//~^ ERROR any use of this value
+//~| WARNING this was previously
 
 const fn f<F>(_: &[u8], _: F) -> &[u8]
 where
index 59bf00d0012cdce674321ea2456470cb5dd16cdc..92ebd5a220d904d0f88db711d9d60745ab9e44e4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-81899.rs:10:5
+  --> $DIR/issue-81899.rs:12:5
    |
 LL | const _CONST: &[u8] = &f(&[], |_| {});
    |                        -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
@@ -7,11 +7,23 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:10:5
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:12:5
    |     inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error: any use of this value will cause an error
+  --> $DIR/issue-81899.rs:4:23
+   |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   | ----------------------^^^^^^^^^^^^^^^-
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 632f8dc3ad6f5dfe7c6dfe9a5a84b8e503a3c593..7618d001e86eecf3e4813714c05fd86d7f333cc8 100644 (file)
@@ -1,6 +1,8 @@
 // Regression test related to issue 88434
 
 const _CONST: &() = &f(&|_| {});
+//~^ ERROR any use of this value
+//~| WARNING this was previously
 
 const fn f<F>(_: &F)
 where
index d9635e1ee464ce514a16bd858292bcae3311dcc9..d46cd862e34aad2278e54e773e014f12917d28f8 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-88434-minimal-example.rs:9:5
+  --> $DIR/issue-88434-minimal-example.rs:11:5
    |
 LL | const _CONST: &() = &f(&|_| {});
    |                      ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
@@ -7,11 +7,23 @@ LL | const _CONST: &() = &f(&|_| {});
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:9:5
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:11:5
    |     inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:31]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error: any use of this value will cause an error
+  --> $DIR/issue-88434-minimal-example.rs:3:21
+   |
+LL | const _CONST: &() = &f(&|_| {});
+   | --------------------^^^^^^^^^^^-
+   |                     |
+   |                     referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index f0a6dcd4eb3b885a0b4eee555690ae1514590204..b1fc1615ece7728e0c8eb4c76e18e9206a5b2cf3 100644 (file)
@@ -1,6 +1,8 @@
 // Regression test for issue 88434
 
 const _CONST: &[u8] = &f(&[], |_| {});
+//~^ ERROR any use of this value will cause an error
+//~| WARNING this was previously
 
 const fn f<F>(_: &[u8], _: F) -> &[u8]
 where
index 44e244ae9cc3f9463736309c86628794d8eecbfb..e6b07aba74d426cdd7bc3c7705db522ae2fbc609 100644 (file)
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-88434-removal-index-should-be-less.rs:9:5
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:11:5
    |
 LL | const _CONST: &[u8] = &f(&[], |_| {});
    |                        -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
@@ -7,11 +7,23 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
 LL |     panic!()
    |     ^^^^^^^^
    |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:9:5
+   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:11:5
    |     inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:37]>` at $SRC_DIR/std/src/panic.rs:LL:COL
    |
    = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to previous error
+error: any use of this value will cause an error
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23
+   |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   | ----------------------^^^^^^^^^^^^^^^-
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index c0709a996ce370fab1deaeb85740a952d9e17c69..f0b9035357d82fcfb9d49eb0883ff4f583e6e16b 100644 (file)
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/different_generic_args_array.rs:9:9
    |
 LL |     x = Const::<{ [4] }> {};
-   |         ^^^^^^^^^^^^^^^^^^^ expected `3_usize`, found `4_usize`
+   |         ^^^^^^^^^^^^^^^^^^^ expected `[3_usize]`, found `[4_usize]`
    |
    = note: expected struct `Const<[3_usize]>`
               found struct `Const<[4_usize]>`
index 8705a39fa4bcd3397061a59f03e9bfcec0821941..98931a3936f52eb3fe2f4bab4715000d561d5ce8 100644 (file)
@@ -10,7 +10,11 @@ note: ...which requires checking if `TensorDimension` fulfills its obligations..
 LL | trait TensorDimension {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
-   = note: cycle used when normalizing `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`
+note: cycle used when checking if `TensorDimension` fulfills its obligations
+  --> $DIR/issue-83765.rs:4:1
+   |
+LL | trait TensorDimension {
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 678714d0e055a7254bf3bef4dca34a8e928049f6..52b173c4d04a8107dc522f71a8424386deb859db 100644 (file)
@@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
-   |         memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
   ::: $DIR/out_of_bounds_read.rs:12:33
@@ -18,7 +18,7 @@ error[E0080]: evaluation of constant value failed
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
-   |         memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -37,7 +37,7 @@ error[E0080]: evaluation of constant value failed
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |         |
-   |         memory access failed: alloc7 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
   ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
index e73e54ff5f1b37d667fe486e3deb60312f4721e9..c9460498951fda8a90aeacad17250685f733c2ef 100644 (file)
@@ -1,5 +1,4 @@
 // compile-flags: -Ztreat-err-as-bug=2
-//~^ ERROR 1:1: 1:1: ty::ConstKind::Error constructed but no error reported
 // build-fail
 // failure-status: 101
 // rustc-env:RUST_BACKTRACE=1
@@ -23,5 +22,7 @@
 fn main() {
     let x: &'static i32 = &X;
     //~^ ERROR evaluation of constant value failed
+    //~| ERROR erroneous constant used
+    //~| WARNING this was previously accepted by the compiler
     println!("x={}", x);
 }
index 8bd5c08dc4649703ea896da727669de20f27ad76..b74d5a2722bd8b2e75051d335e4941f0451cdddf 100644 (file)
@@ -1,5 +1,5 @@
 warning: any use of this value will cause an error
-  --> $DIR/const-eval-query-stack.rs:20:16
+  --> $DIR/const-eval-query-stack.rs:19:16
    |
 LL | const X: i32 = 1 / 0;
    | ---------------^^^^^-
@@ -7,7 +7,7 @@ LL | const X: i32 = 1 / 0;
    |                attempt to divide `1_i32` by zero
    |
 note: the lint level is defined here
-  --> $DIR/const-eval-query-stack.rs:19:8
+  --> $DIR/const-eval-query-stack.rs:18:8
    |
 LL | #[warn(const_err)]
    |        ^^^^^^^^^
@@ -15,13 +15,23 @@ LL | #[warn(const_err)]
    = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-eval-query-stack.rs:24:28
+  --> $DIR/const-eval-query-stack.rs:23:28
    |
 LL |     let x: &'static i32 = &X;
    |                            ^ referenced constant has errors
+
+error: erroneous constant used
+  --> $DIR/const-eval-query-stack.rs:23:27
+   |
+LL |     let x: &'static i32 = &X;
+   |                           ^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 query stack during panic:
-#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
-#1 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
-#2 [optimized_mir] optimizing MIR for `main`
-#3 [collect_and_partition_mono_items] collect_and_partition_mono_items
+#0 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
+#1 [optimized_mir] optimizing MIR for `main`
+#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
 end of query stack
index 122f5b97eee06ed6df5797ac96be77bb27884d02..b156ded4a6c2afc44a48ab82e1cccaff1ca17385 100644 (file)
@@ -28,14 +28,22 @@ fn f32() {
     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
 
     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
 
     // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
     // In practice, this seems to only cause a problem on x86, since the most widely used calling
     // convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
     if !cfg!(target_arch = "x86") {
         const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
         const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
     }
 }
 
@@ -47,12 +55,20 @@ fn f64() {
     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
 
     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+    //~^ ERROR any use of this value will cause an error
+    //~| WARNING this was previously accepted
 
     // See comment above.
     if !cfg!(target_arch = "x86") {
         const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
         const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+        //~^ ERROR any use of this value will cause an error
+        //~| WARNING this was previously accepted
     }
 }
 
index b39e881970176d54e9b9b2cc8ab18c12849a756d..f3fd098e848a20476875e5491fb41ed7f0eeb7c5 100644 (file)
@@ -56,6 +56,55 @@ LL |     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:30:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = note: `#[deny(const_err)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:33:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:41:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:44:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
@@ -78,10 +127,10 @@ LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 LL |     called_in_const.call_once(arg)
    |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:46:30
+  ::: $DIR/const-float-bits-reject-conv.rs:54:30
    |
 LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
-   |                              ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:46:30
+   |                              ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:54:30
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
@@ -107,13 +156,61 @@ LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 LL |     called_in_const.call_once(arg)
    |     ------------------------------ inside `const_eval_select::<(f64,), fn(f64) -> u64 {core::f64::<impl f64>::to_bits::ct_f64_to_u64}, [closure@core::f64::<impl f64>::to_bits::{closure#0}], u64>` at $SRC_DIR/core/src/intrinsics.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:47:30
+  ::: $DIR/const-float-bits-reject-conv.rs:55:30
    |
 LL |     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
-   |                              ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:47:30
+   |                              ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:55:30
    |
    = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 4 previous errors
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:57:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:60:34
+   |
+LL |             const _: () = assert!($a);
+   |             --------------------------
+...
+LL |     const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
+   |                                  ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:66:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: any use of this value will cause an error
+  --> $DIR/const-float-bits-reject-conv.rs:69:38
+   |
+LL |             const _: () = assert!($a == $b);
+   |             --------------------------------
+...
+LL |         const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
+   |                                      ^^^^^^^^^^^ referenced constant has errors
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+error: aborting due to 12 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index 35915a7a606a4ddee8e5b93493b1227d97e03d0c..6924956bdf706f174ccc7a68c4ed529d30f2ad8c 100644 (file)
@@ -6,6 +6,7 @@
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR: [i32; X] = [99; 34];
+//~^ ERROR evaluation of constant value failed
 
 const X1: usize = 42 || 39;
 //~^ ERROR mismatched types
@@ -15,6 +16,7 @@
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR1: [i32; X1] = [99; 47];
+//~^ ERROR evaluation of constant value failed
 
 const X2: usize = -42 || -39;
 //~^ ERROR mismatched types
@@ -24,6 +26,7 @@
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR2: [i32; X2] = [99; 18446744073709551607];
+//~^ ERROR evaluation of constant value failed
 
 const X3: usize = -42 && -39;
 //~^ ERROR mismatched types
 //~| ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARR3: [i32; X3] = [99; 6];
+//~^ ERROR evaluation of constant value failed
 
 const Y: usize = 42.0 == 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR: [i32; Y] = [99; 1];
+//~^ ERROR evaluation of constant value failed
 
 const Y1: usize = 42.0 >= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR1: [i32; Y1] = [99; 1];
+//~^ ERROR evaluation of constant value failed
 
 const Y2: usize = 42.0 <= 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR2: [i32; Y2] = [99; 1];
+//~^ ERROR evaluation of constant value failed
 
 const Y3: usize = 42.0 > 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR3: [i32; Y3] = [99; 0];
+//~^ ERROR evaluation of constant value failed
 
 const Y4: usize = 42.0 < 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR4: [i32; Y4] = [99; 0];
+//~^ ERROR evaluation of constant value failed
 
 const Y5: usize = 42.0 != 42.0;
 //~^ ERROR mismatched types
 //~| expected `usize`, found `bool`
 const ARRR5: [i32; Y5] = [99; 0];
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
     let _ = ARR;
index 4e503e5a5c0a4df39a204d7e5e31c4679f620d8a..9001fefd1029f314bc95f9bae48efc75a5baf0cd 100644 (file)
@@ -16,96 +16,157 @@ error[E0308]: mismatched types
 LL | const X: usize = 42 && 39;
    |                  ^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:8:18
+   |
+LL | const ARR: [i32; X] = [99; 34];
+   |                  ^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:10:19
+  --> $DIR/const-integer-bool-ops.rs:11:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:10:25
+  --> $DIR/const-integer-bool-ops.rs:11:25
    |
 LL | const X1: usize = 42 || 39;
    |                         ^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:10:19
+  --> $DIR/const-integer-bool-ops.rs:11:19
    |
 LL | const X1: usize = 42 || 39;
    |                   ^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:18:19
+   |
+LL | const ARR1: [i32; X1] = [99; 47];
+   |                   ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:19:19
+  --> $DIR/const-integer-bool-ops.rs:21:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:19:26
+  --> $DIR/const-integer-bool-ops.rs:21:26
    |
 LL | const X2: usize = -42 || -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:19:19
+  --> $DIR/const-integer-bool-ops.rs:21:19
    |
 LL | const X2: usize = -42 || -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
-error[E0308]: mismatched types
+error[E0080]: evaluation of constant value failed
   --> $DIR/const-integer-bool-ops.rs:28:19
    |
+LL | const ARR2: [i32; X2] = [99; 18446744073709551607];
+   |                   ^^ referenced constant has errors
+
+error[E0308]: mismatched types
+  --> $DIR/const-integer-bool-ops.rs:31:19
+   |
 LL | const X3: usize = -42 && -39;
    |                   ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:28:26
+  --> $DIR/const-integer-bool-ops.rs:31:26
    |
 LL | const X3: usize = -42 && -39;
    |                          ^^^ expected `bool`, found integer
 
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:28:19
+  --> $DIR/const-integer-bool-ops.rs:31:19
    |
 LL | const X3: usize = -42 && -39;
    |                   ^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:38:19
+   |
+LL | const ARR3: [i32; X3] = [99; 6];
+   |                   ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:37:18
+  --> $DIR/const-integer-bool-ops.rs:41:18
    |
 LL | const Y: usize = 42.0 == 42.0;
    |                  ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:44:19
+   |
+LL | const ARRR: [i32; Y] = [99; 1];
+   |                   ^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:42:19
+  --> $DIR/const-integer-bool-ops.rs:47:19
    |
 LL | const Y1: usize = 42.0 >= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:50:20
+   |
+LL | const ARRR1: [i32; Y1] = [99; 1];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:47:19
+  --> $DIR/const-integer-bool-ops.rs:53:19
    |
 LL | const Y2: usize = 42.0 <= 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:56:20
+   |
+LL | const ARRR2: [i32; Y2] = [99; 1];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:52:19
+  --> $DIR/const-integer-bool-ops.rs:59:19
    |
 LL | const Y3: usize = 42.0 > 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:62:20
+   |
+LL | const ARRR3: [i32; Y3] = [99; 0];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:57:19
+  --> $DIR/const-integer-bool-ops.rs:65:19
    |
 LL | const Y4: usize = 42.0 < 42.0;
    |                   ^^^^^^^^^^^ expected `usize`, found `bool`
 
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:68:20
+   |
+LL | const ARRR4: [i32; Y4] = [99; 0];
+   |                    ^^ referenced constant has errors
+
 error[E0308]: mismatched types
-  --> $DIR/const-integer-bool-ops.rs:62:19
+  --> $DIR/const-integer-bool-ops.rs:71:19
    |
 LL | const Y5: usize = 42.0 != 42.0;
    |                   ^^^^^^^^^^^^ expected `usize`, found `bool`
 
-error: aborting due to 18 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-integer-bool-ops.rs:74:20
+   |
+LL | const ARRR5: [i32; Y5] = [99; 0];
+   |                    ^^ referenced constant has errors
+
+error: aborting due to 28 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
index 61b00be345feee4bb0cf3a42aaa397097a8de029..0f420ae1b6b7cc6689dce73199da330bc194873f 100644 (file)
@@ -19,7 +19,13 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
 LL | const S: &'static mut str = &mut " hello ";
    |                             ^^^^^^^^^^^^^^ cannot borrow as mutable
 
-error: aborting due to 3 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-76510.rs:11:70
+   |
+LL |         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+   |                                                                      ^ referenced constant has errors
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0596, E0658, E0764.
-For more information about an error, try `rustc --explain E0596`.
+Some errors have detailed explanations: E0080, E0596, E0658, E0764.
+For more information about an error, try `rustc --explain E0080`.
index 143d2fb6b9a3a1a599f36edcc222f4f1d7d34e83..08cf64ee330db74af03b8bc009206907bd4462bf 100644 (file)
@@ -9,6 +9,7 @@
 
 const fn trigger() -> [(); unsafe {
         let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+        //~^ ERROR evaluation of constant value failed
         0
     }] {
     [(); 0]
index 1067eb003f7c765ad92b045730a3f2254fba575f..0772b1712c5e272dcd570f365725ea98ce32fe1f 100644 (file)
@@ -1,10 +1,10 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{constant#0}`
+error[E0391]: cycle detected when evaluate type-level constant
   --> $DIR/const-size_of-cycle.rs:4:17
    |
 LL |     bytes: [u8; std::mem::size_of::<Foo>()]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`...
+note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
   --> $DIR/const-size_of-cycle.rs:4:17
    |
 LL |     bytes: [u8; std::mem::size_of::<Foo>()]
@@ -17,7 +17,7 @@ LL |     bytes: [u8; std::mem::size_of::<Foo>()]
    = note: ...which requires computing layout of `Foo`...
    = note: ...which requires computing layout of `[u8; _]`...
    = note: ...which requires normalizing `[u8; _]`...
-   = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
+   = note: ...which again requires evaluate type-level constant, completing the cycle
 note: cycle used when checking that `Foo` is well-formed
   --> $DIR/const-size_of-cycle.rs:3:1
    |
index 8057d64369a23e553ba21dcb181203e10c97d4db..763263c6aeb4f9a86c81c99459d07590c6b06733 100644 (file)
@@ -4,6 +4,7 @@
 //~^ ERROR mismatched types
 //~| expected tuple, found `usize`
 const ARR: [i32; TUP.0] = [];
+//~^ ERROR evaluation of constant value failed
 
 fn main() {
 }
index d301f8c4054c23bb901cac12cc877926b3a90607..b178e05e27a095b3c10102f6b0f63a3c7fb2b2a6 100644 (file)
@@ -11,6 +11,13 @@ help: use a trailing comma to create a tuple with one element
 LL | const TUP: (usize,) = (5usize << 64,);
    |                       +            ++
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-tup-index-span.rs:6:18
+   |
+LL | const ARR: [i32; TUP.0] = [];
+   |                  ^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0080, E0308.
+For more information about an error, try `rustc --explain E0080`.
index 9df1a89694ebafed564f8ea9c3796486cd056dbf..6bfa97a2fded7875aeed1c92e698265662037f8e 100644 (file)
@@ -6,7 +6,7 @@ LL | fn main() {
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 8, align: 8) {
-               â•¾â”€â”€â”€â”€â”€â”€â”€alloc8────────╼                         â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼
+               â•¾â”€â”€â”€â”€â”€â”€â”€alloc7────────╼                         â”‚ â•¾â”€â”€â”€â”€â”€â”€â•¼
            }
 
 error: erroneous constant used
index 113f86cf0f99fa84c275401b2aea9b7b4ca03735..9ac6c984cb0cdd8fedb3f9883455c20c40e68d65 100644 (file)
@@ -1,48 +1,20 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Foo::B::{constant#0}`
+error[E0391]: cycle detected when const-evaluating + checking `Foo::B::{constant#0}`
   --> $DIR/issue-36163.rs:4:9
    |
 LL |     B = A,
    |         ^
    |
-note: ...which requires simplifying constant for the type system `Foo::B::{constant#0}`...
-  --> $DIR/issue-36163.rs:4:9
-   |
-LL |     B = A,
-   |         ^
-note: ...which requires const-evaluating + checking `Foo::B::{constant#0}`...
-  --> $DIR/issue-36163.rs:4:9
-   |
-LL |     B = A,
-   |         ^
-   = note: ...which requires normalizing `A`...
-note: ...which requires simplifying constant for the type system `A`...
-  --> $DIR/issue-36163.rs:1:1
-   |
-LL | const A: isize = Foo::B as isize;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `A`...
-  --> $DIR/issue-36163.rs:1:1
-   |
-LL | const A: isize = Foo::B as isize;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `A`...
   --> $DIR/issue-36163.rs:1:1
    |
 LL | const A: isize = Foo::B as isize;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `A`...
-   = note: ...which again requires simplifying constant for the type system `Foo::B::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-36163.rs:1:1
+   = note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle
+note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}`
+  --> $DIR/issue-36163.rs:4:9
    |
-LL | / const A: isize = Foo::B as isize;
-LL | |
-LL | | enum Foo {
-LL | |     B = A,
-LL | | }
-LL | |
-LL | | fn main() {}
-   | |____________^
+LL |     B = A,
+   |         ^
 
 error: aborting due to previous error
 
index 71e764620d1404d5d1db460791a62010a5457c67..79f415e6a2c10f27cc13dd1955793953f4ce4312 100644 (file)
@@ -4,7 +4,7 @@
 
 struct Foo {
     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
-    //~^ ERROR cycle detected when simplifying constant for the type system
+    //~^ ERROR cycle detected when evaluate type-level constant
     x: usize,
 }
 
index 9e3db5ce9a402ce3cdce028910d1d27821be98c5..6641300fc9a87c571ddc583e6fb209089ccf8942 100644 (file)
@@ -1,10 +1,10 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Foo::bytes::{constant#0}`
+error[E0391]: cycle detected when evaluate type-level constant
   --> $DIR/issue-44415.rs:6:17
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
    |                 ^^^^^^
    |
-note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`...
+note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`...
   --> $DIR/issue-44415.rs:6:17
    |
 LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
@@ -17,7 +17,7 @@ LL |     bytes: [u8; unsafe { intrinsics::size_of::<Foo>() }],
    = note: ...which requires computing layout of `Foo`...
    = note: ...which requires computing layout of `[u8; _]`...
    = note: ...which requires normalizing `[u8; _]`...
-   = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle
+   = note: ...which again requires evaluate type-level constant, completing the cycle
 note: cycle used when checking that `Foo` is well-formed
   --> $DIR/issue-44415.rs:5:1
    |
index 0566b802e75b68a010971e5099ce75403508b1ce..7a00fe964ab08da4d7d7c51f24cdf0dc3bc6272b 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass
+// check-pass
 
 fn main() {
     let _ = &[(); usize::MAX];
index 1148577016ab47952dca433672458f80437f0ee8..4856418ed600229d153ce311781e0b01196b158c 100644 (file)
@@ -1,21 +1,10 @@
-error[E0391]: cycle detected when normalizing `FOO`
-   |
-note: ...which requires simplifying constant for the type system `FOO`...
-  --> $DIR/issue-17252.rs:1:1
-   |
-LL | const FOO: usize = FOO;
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `FOO`...
+error[E0391]: cycle detected when const-evaluating + checking `FOO`
   --> $DIR/issue-17252.rs:1:1
    |
 LL | const FOO: usize = FOO;
    | ^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `FOO`...
-  --> $DIR/issue-17252.rs:1:1
    |
-LL | const FOO: usize = FOO;
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires normalizing `FOO`, completing the cycle
+   = note: ...which immediately requires const-evaluating + checking `FOO` again
 note: cycle used when const-evaluating + checking `main::{constant#0}`
   --> $DIR/issue-17252.rs:4:18
    |
index d3a1993536a00aaa60f8fe1e8408f55536b0959d..9366050d7ecdf86f1714a4592ea579f06f331112 100644 (file)
@@ -1,26 +1,15 @@
-error[E0391]: cycle detected when simplifying constant for the type system `X::A::{constant#0}`
+error[E0391]: cycle detected when const-evaluating + checking `X::A::{constant#0}`
   --> $DIR/issue-23302-1.rs:4:9
    |
 LL |     A = X::A as isize,
    |         ^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `X::A::{constant#0}`...
+   = note: ...which immediately requires const-evaluating + checking `X::A::{constant#0}` again
+note: cycle used when simplifying constant for the type system `X::A::{constant#0}`
   --> $DIR/issue-23302-1.rs:4:9
    |
 LL |     A = X::A as isize,
    |         ^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `X::A::{constant#0}`...
-  --> $DIR/issue-23302-1.rs:4:9
-   |
-LL |     A = X::A as isize,
-   |         ^^^^^^^^^^^^^
-   = note: ...which requires normalizing `X::A as isize`...
-   = note: ...which again requires simplifying constant for the type system `X::A::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-23302-1.rs:3:1
-   |
-LL | enum X {
-   | ^^^^^^
 
 error: aborting due to previous error
 
index d3b78ea1af5f5c39e70914777182197dea0faeb8..b97ae287a47a976dba3119de24dbf178abd080fd 100644 (file)
@@ -1,26 +1,15 @@
-error[E0391]: cycle detected when simplifying constant for the type system `Y::A::{constant#0}`
+error[E0391]: cycle detected when const-evaluating + checking `Y::A::{constant#0}`
   --> $DIR/issue-23302-2.rs:4:9
    |
 LL |     A = Y::B as isize,
    |         ^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `Y::A::{constant#0}`...
+   = note: ...which immediately requires const-evaluating + checking `Y::A::{constant#0}` again
+note: cycle used when simplifying constant for the type system `Y::A::{constant#0}`
   --> $DIR/issue-23302-2.rs:4:9
    |
 LL |     A = Y::B as isize,
    |         ^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `Y::A::{constant#0}`...
-  --> $DIR/issue-23302-2.rs:4:9
-   |
-LL |     A = Y::B as isize,
-   |         ^^^^^^^^^^^^^
-   = note: ...which requires normalizing `Y::B as isize`...
-   = note: ...which again requires simplifying constant for the type system `Y::A::{constant#0}`, completing the cycle
-note: cycle used when collecting item types in top-level module
-  --> $DIR/issue-23302-2.rs:3:1
-   |
-LL | enum Y {
-   | ^^^^^^
 
 error: aborting due to previous error
 
index 5233b832ecc796f1bf351011b9e376e400d521f0..1a07d4a95bcfacca5b69d2f7d3467b211118b8ff 100644 (file)
@@ -1,38 +1,20 @@
-error[E0391]: cycle detected when simplifying constant for the type system `A`
+error[E0391]: cycle detected when const-evaluating + checking `A`
   --> $DIR/issue-23302-3.rs:1:1
    |
 LL | const A: i32 = B;
    | ^^^^^^^^^^^^^^^^^
    |
-note: ...which requires simplifying constant for the type system `A`...
-  --> $DIR/issue-23302-3.rs:1:1
-   |
-LL | const A: i32 = B;
-   | ^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `A`...
-  --> $DIR/issue-23302-3.rs:1:1
-   |
-LL | const A: i32 = B;
-   | ^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `B`...
-note: ...which requires simplifying constant for the type system `B`...
-  --> $DIR/issue-23302-3.rs:3:1
-   |
-LL | const B: i32 = A;
-   | ^^^^^^^^^^^^^^^^^
-note: ...which requires simplifying constant for the type system `B`...
+note: ...which requires const-evaluating + checking `B`...
   --> $DIR/issue-23302-3.rs:3:1
    |
 LL | const B: i32 = A;
    | ^^^^^^^^^^^^^^^^^
-note: ...which requires const-evaluating + checking `B`...
-  --> $DIR/issue-23302-3.rs:3:1
+   = note: ...which again requires const-evaluating + checking `A`, completing the cycle
+note: cycle used when simplifying constant for the type system `A`
+  --> $DIR/issue-23302-3.rs:1:1
    |
-LL | const B: i32 = A;
+LL | const A: i32 = B;
    | ^^^^^^^^^^^^^^^^^
-   = note: ...which requires normalizing `A`...
-   = note: ...which again requires simplifying constant for the type system `A`, completing the cycle
-   = note: cycle used when running analysis passes on this crate
 
 error: aborting due to previous error
 
index 06a330813406a9fe0f5a61de534e8e403854181c..64873ac35a00213e78fc7479e75ba180f5029a34 100644 (file)
@@ -5,6 +5,7 @@ enum Foo {
 
 enum Bar {
     A = Foo::A as isize
+    //~^ ERROR evaluation of constant value failed
 }
 
 fn main() {}
index fa95ca9c18a1004a049da6e67152c0e40be605a0..47a24547d4533dcf333588d10315f2c42f942f7c 100644 (file)
@@ -6,6 +6,13 @@ LL |     A = "" + 1
    |         |
    |         &str
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-41394.rs:7:9
+   |
+LL |     A = Foo::A as isize
+   |         ^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0369`.
+Some errors have detailed explanations: E0080, E0369.
+For more information about an error, try `rustc --explain E0080`.
index 42a4d5b674b229c239149037f9398ce90f86565c..ddd391415414763bb38d0f06348458cea2ee85e6 100644 (file)
@@ -9,6 +9,8 @@ const fn const_val<T: Sized>() -> usize {
 }
 
 fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+  //~^ ERROR evaluation of constant value failed
+  //~| ERROR evaluation of constant value failed
     z
 }
 
index efe2ef504a2ba16fcea5c3a274b745f881dfd2f9..6e8d3cac9a7e4f365ea3b338c0d6f793157733cb 100644 (file)
@@ -12,7 +12,19 @@ LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
    |
    = note: cannot satisfy `_: Tt`
 
-error: aborting due to 2 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-54954.rs:11:15
+   |
+LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+   |               ^^^^^^^ referenced constant has errors
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-54954.rs:11:34
+   |
+LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
+   |                                  ^^^^^^^ referenced constant has errors
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0283, E0379.
-For more information about an error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0080, E0283, E0379.
+For more information about an error, try `rustc --explain E0080`.
index 3277df69c028521e1dd3d0025db6a653c0993ab9..32f51d513d122086708ee0f37989a23274bb9a51 100644 (file)
@@ -1,4 +1,4 @@
-// build-pass
+// check-pass
 
 fn main() {
     println!("{}", [(); usize::MAX].len());
index 2c5257ce063cb525897cd2c19a1b4380f1d0c37d..6851b67cb3b3aa3cfa3ac81fe21e3c3af4d4f4b5 100644 (file)
@@ -19,4 +19,5 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA`
 
 fn main() {
     let _ = [0; B::VALUE];
+    //~^ ERROR evaluation of constant value failed
 }
index 8ae0f8b804c93e822b6b5f97fa81105cb3215dcc..cb5b397849c06334fd95724b85d41571ea078e79 100644 (file)
@@ -13,7 +13,13 @@ LL |     type MyA: TraitA;
 LL | impl TraitB for B {
    | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation
 
-error: aborting due to 2 previous errors
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17
+   |
+LL |     let _ = [0; B::VALUE];
+   |                 ^^^^^^^^ referenced constant has errors
+
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0046, E0437.
+Some errors have detailed explanations: E0046, E0080, E0437.
 For more information about an error, try `rustc --explain E0046`.
index 00588735b9a5932c78fdfb9b3d3b9057d8492541..78a20cf8ebb05eab5f6d74fbc37b91bbeb28c38c 100644 (file)
@@ -2,4 +2,5 @@ fn main() {
     const N: u32 = 1_000;
     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; //~ ERROR cannot find value
     let mut digits = [0u32; M];
+    //~^ ERROR evaluation of constant value failed
 }
index 4cc035cb11e2034e9e0d178b1ac23d3e721c595b..f0cb784f56c48037804dfbceb84655104f6b5bda 100644 (file)
@@ -16,6 +16,13 @@ LL -     const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize;
 LL +     const M: usize = (f64::from(N) * LOG10_2) as usize;
    | 
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/issue-50599.rs:4:29
+   |
+LL |     let mut digits = [0u32; M];
+   |                             ^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0425`.
+Some errors have detailed explanations: E0080, E0425.
+For more information about an error, try `rustc --explain E0080`.
index 4b6bc6124dbf301e232d640498f539cfde51fbba..f37f093d9ede7b6f07aebfdaa310efb3a58b3493 100644 (file)
@@ -2,4 +2,5 @@ fn main() {
     let v = vec![0];
     const l: usize = v.count(); //~ ERROR attempt to use a non-constant value in a constant
     let s: [u32; l] = v.into_iter().collect();
+    //~^ERROR evaluation of constant value failed
 }
index 64c7687f7a882d600af96e075bc78c7f9aff7afd..02f267c6c8d73419c7cb6da9f6f5c78a8109051c 100644 (file)
@@ -6,6 +6,13 @@ LL |     const l: usize = v.count();
    |     |
    |     help: consider using `let` instead of `const`: `let l`
 
-error: aborting due to previous error
+error[E0080]: evaluation of constant value failed
+  --> $DIR/type-dependent-def-issue-49241.rs:4:18
+   |
+LL |     let s: [u32; l] = v.into_iter().collect();
+   |                  ^ referenced constant has errors
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0435`.
+Some errors have detailed explanations: E0080, E0435.
+For more information about an error, try `rustc --explain E0080`.
index 10be245b36293ee578c6a8adb64bd51beb7c900d..5d687d06f6f46085485fecf44a8610143f2dd9c8 100644 (file)
@@ -48,10 +48,10 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
                     let mut ty = cx.tcx.type_of(def_id.to_def_id());
                     let constant = cx
                         .tcx
-                        .const_eval_poly(def_id.to_def_id())
+                        .const_eval_poly_for_typeck(def_id.to_def_id())
                         .ok()
-                        .map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
-                    if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
+                        .and_then(|val| val.map(|valtree| rustc_middle::ty::Const::from_value(cx.tcx, valtree, ty)));
+                    if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) {
                         if let ty::Adt(adt, _) = ty.kind() {
                             if adt.is_enum() {
                                 ty = adt.repr().discr_type().to_ty(cx.tcx);
index ed47490e230cee6e7b78fbcf3aa35d9274e5b365..e10993ba7ddce0685ce140fc99547b72f2b9cd92 100644 (file)
@@ -3,7 +3,6 @@
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -53,8 +52,8 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
             if let ItemKind::Const(hir_ty, _) = &item.kind;
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             if let ty::Array(element_type, cst) = ty.kind();
-            if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.kind();
-            if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
+            if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
+            if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
             if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
             if self.maximum_allowed_size < element_count * element_size;
 
index 4ca69465fad4123ee5bba823e2f1f8e645758801..0acbd81aec3438ab99989d2fda6c8960257045b6 100644 (file)
@@ -3,7 +3,6 @@
 use if_chain::if_chain;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, ConstKind};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -43,8 +42,8 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
             if let ExprKind::Repeat(_, _) = expr.kind;
             if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind();
-            if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.kind();
-            if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
+            if let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind();
+            if let Ok(element_count) = element_count.try_to_machine_usize(cx.tcx);
             if let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
             if self.maximum_allowed_size < element_count * element_size;
             then {
index c0b3e95b18523fcbd40bb7523be6d0b96d6b6731..afca7530556b2dcad330fa60391512fa8362158b 100644 (file)
@@ -34,11 +34,11 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs_const = match lhs {
                         Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
-                        None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
+                        None => miri_to_const(cx.tcx, ty.numeric_min_val(cx.tcx)?)?,
                     };
                     let rhs_const = match rhs {
                         Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
-                        None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
+                        None => miri_to_const(cx.tcx, ty.numeric_max_val(cx.tcx)?)?,
                     };
                     let lhs_val = lhs_const.int_value(cx, ty)?;
                     let rhs_val = rhs_const.int_value(cx, ty)?;
index 8db41ba6ee296f399877221d2c24b77d6c0e6e06..9f6fca27b229591b441cb9ca312abdf0d76de2b2 100644 (file)
@@ -13,7 +13,7 @@
     BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass, Lint};
-use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::adjustment::Adjust;
 use rustc_middle::ty::{self, Const, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -133,7 +133,7 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 
 fn is_value_unfrozen_raw<'tcx>(
     cx: &LateContext<'tcx>,
-    result: Result<ConstValue<'tcx>, ErrorHandled>,
+    result: Result<Option<ty::ValTree<'tcx>>, ErrorHandled>,
     ty: Ty<'tcx>,
 ) -> bool {
     fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
@@ -142,7 +142,7 @@ fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
             // leads us to the point checking `UnsafeCell` directly is the only option.
             ty::Adt(ty_def, ..) if Some(ty_def.did()) == cx.tcx.lang_items().unsafe_cell_type() => true,
             ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
-                let val = cx.tcx.destructure_const(cx.param_env.and(val));
+                let val = cx.tcx.destructure_const(val);
                 val.fields.iter().any(|field| inner(cx, *field))
             },
             _ => false,
@@ -174,19 +174,19 @@ fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool {
             // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none).
             err == ErrorHandled::TooGeneric
         },
-        |val| inner(cx, Const::from_value(cx.tcx, val, ty)),
+        |val| val.map_or(false, |val| inner(cx, Const::from_value(cx.tcx, val, ty))),
     )
 }
 
 fn is_value_unfrozen_poly<'tcx>(cx: &LateContext<'tcx>, body_id: BodyId, ty: Ty<'tcx>) -> bool {
-    let result = cx.tcx.const_eval_poly(body_id.hir_id.owner.to_def_id());
+    let result = cx.tcx.const_eval_poly_for_typeck(body_id.hir_id.owner.to_def_id());
     is_value_unfrozen_raw(cx, result, ty)
 }
 
 fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: DefId, ty: Ty<'tcx>) -> bool {
     let substs = cx.typeck_results().node_substs(hir_id);
 
-    let result = cx.tcx.const_eval_resolve(
+    let result = cx.tcx.const_eval_resolve_for_typeck(
         cx.param_env,
         ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
         None,
index 159c5d53d029261fdd159db073356d365021d4c3..c31c560f427f25ef3ec33c05078ffa7b1158e182 100644 (file)
@@ -7,7 +7,6 @@
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
 use rustc_lint::LateContext;
-use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
@@ -423,14 +422,14 @@ fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option<C
                 let result = self
                     .lcx
                     .tcx
-                    .const_eval_resolve(
+                    .const_eval_resolve_for_typeck(
                         self.param_env,
                         ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
                         None,
                     )
                     .ok()
-                    .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
-                let result = miri_to_const(result);
+                    .and_then(|val| val.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty)))?;
+                let result = miri_to_const(self.lcx.tcx, result);
                 if result.is_some() {
                     self.needed_resolution = true;
                 }
@@ -580,80 +579,69 @@ fn binop(&mut self, op: BinOp, left: &Expr<'_>, right: &Expr<'_>) -> Option<Cons
     }
 }
 
-pub fn miri_to_const(result: ty::Const<'_>) -> Option<Constant> {
-    use rustc_middle::mir::interpret::ConstValue;
+pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: ty::Const<'tcx>) -> Option<Constant> {
     match result.kind() {
-        ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => {
-            match result.ty().kind() {
-                ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
-                ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
-                ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
+        ty::ConstKind::Value(valtree) => {
+            match (valtree, result.ty().kind()) {
+                (ty::ValTree::Leaf(int), ty::Bool) => Some(Constant::Bool(int == ScalarInt::TRUE)),
+                (ty::ValTree::Leaf(int), ty::Uint(_) | ty::Int(_)) => Some(Constant::Int(int.assert_bits(int.size()))),
+                (ty::ValTree::Leaf(int), ty::Float(FloatTy::F32)) => Some(Constant::F32(f32::from_bits(
                     int.try_into().expect("invalid f32 bit representation"),
                 ))),
-                ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
+                (ty::ValTree::Leaf(int), ty::Float(FloatTy::F64)) => Some(Constant::F64(f64::from_bits(
                     int.try_into().expect("invalid f64 bit representation"),
                 ))),
-                ty::RawPtr(type_and_mut) => {
+                (ty::ValTree::Leaf(int), ty::RawPtr(type_and_mut)) => {
                     if let ty::Uint(_) = type_and_mut.ty.kind() {
                         return Some(Constant::RawPtr(int.assert_bits(int.size())));
                     }
                     None
                 },
-                // FIXME: implement other conversions.
-                _ => None,
-            }
-        },
-        ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty().kind() {
-            ty::Ref(_, tam, _) => match tam.kind() {
-                ty::Str => String::from_utf8(
-                    data.inner()
-                        .inspect_with_uninit_and_ptr_outside_interpreter(start..end)
-                        .to_owned(),
-                )
-                .ok()
-                .map(Constant::Str),
-                _ => None,
-            },
-            _ => None,
-        },
-        ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty().kind() {
-            ty::Array(sub_type, len) => match sub_type.kind() {
-                ty::Float(FloatTy::F32) => match miri_to_const(*len) {
-                    Some(Constant::Int(len)) => alloc
-                        .inner()
-                        .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
-                        .to_owned()
-                        .chunks(4)
-                        .map(|chunk| {
-                            Some(Constant::F32(f32::from_le_bytes(
-                                chunk.try_into().expect("this shouldn't happen"),
-                            )))
-                        })
-                        .collect::<Option<Vec<Constant>>>()
-                        .map(Constant::Vec),
-                    _ => None,
-                },
-                ty::Float(FloatTy::F64) => match miri_to_const(*len) {
-                    Some(Constant::Int(len)) => alloc
-                        .inner()
-                        .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
-                        .to_owned()
-                        .chunks(8)
-                        .map(|chunk| {
-                            Some(Constant::F64(f64::from_le_bytes(
-                                chunk.try_into().expect("this shouldn't happen"),
-                            )))
-                        })
-                        .collect::<Option<Vec<Constant>>>()
-                        .map(Constant::Vec),
+                (ty::ValTree::Branch(_), ty::Ref(_, inner_ty, _)) if *inner_ty == tcx.types.str_ => valtree
+                    .try_to_raw_bytes(tcx, result.ty())
+                    .and_then(|bytes| String::from_utf8(bytes.to_owned()).ok().map(Constant::Str)),
+                (ty::ValTree::Branch(_), ty::Array(arr_ty, len)) => match arr_ty.kind() {
+                    ty::Float(float_ty) => {
+                        let chunk_size = match float_ty {
+                            FloatTy::F32 => 4,
+                            FloatTy::F64 => 8,
+                        };
+
+                        match miri_to_const(tcx, *len) {
+                            Some(Constant::Int(_)) => valtree.try_to_raw_bytes(tcx, result.ty()).and_then(|bytes| {
+                                bytes
+                                    .to_owned()
+                                    .chunks(chunk_size)
+                                    .map(|chunk| match float_ty {
+                                        FloatTy::F32 => {
+                                            let float = f32::from_le_bytes(
+                                                chunk
+                                                    .try_into()
+                                                    .expect(&format!("expected to construct f32 from {:?}", chunk)),
+                                            );
+                                            Some(Constant::F32(float))
+                                        },
+                                        FloatTy::F64 => {
+                                            let float = f64::from_le_bytes(
+                                                chunk
+                                                    .try_into()
+                                                    .expect(&format!("expected to construct f64 from {:?}", chunk)),
+                                            );
+                                            Some(Constant::F64(float))
+                                        },
+                                    })
+                                    .collect::<Option<Vec<Constant>>>()
+                                    .map(Constant::Vec)
+                            }),
+                            _ => None,
+                        }
+                    },
                     _ => None,
                 },
-                // FIXME: implement other array type conversions.
+                // FIXME: implement other conversions.
                 _ => None,
-            },
-            _ => None,
+            }
         },
-        // FIXME: implement other conversions.
         _ => None,
     }
 }