From 705d818bd52a6324d5e7693cc4306457395eebc8 Mon Sep 17 00:00:00 2001 From: b-naber Date: Wed, 16 Feb 2022 10:56:01 +0100 Subject: [PATCH 01/11] implement valtrees as the type-system representation for constant values --- .../rustc_codegen_cranelift/src/constant.rs | 9 +- .../rustc_codegen_ssa/src/mir/constant.rs | 8 +- .../src/const_eval/eval_queries.rs | 4 +- .../rustc_const_eval/src/const_eval/mod.rs | 194 ++++++------- .../src/const_eval/valtrees.rs | 51 +--- .../rustc_const_eval/src/interpret/operand.rs | 6 +- compiler/rustc_const_eval/src/lib.rs | 13 +- .../src/transform/promote_consts.rs | 33 ++- compiler/rustc_infer/src/infer/mod.rs | 28 +- .../rustc_middle/src/mir/interpret/queries.rs | 80 +++++- .../rustc_middle/src/mir/interpret/value.rs | 1 + compiler/rustc_middle/src/mir/mod.rs | 269 +++++++++++++++--- compiler/rustc_middle/src/mir/pretty.rs | 20 +- compiler/rustc_middle/src/mir/query.rs | 4 +- compiler/rustc_middle/src/mir/terminator.rs | 3 +- compiler/rustc_middle/src/query/mod.rs | 12 +- compiler/rustc_middle/src/traits/chalk.rs | 3 +- compiler/rustc_middle/src/ty/consts.rs | 35 ++- compiler/rustc_middle/src/ty/consts/kind.rs | 83 +++++- .../rustc_middle/src/ty/consts/valtree.rs | 59 ++++ compiler/rustc_middle/src/ty/context.rs | 68 +++-- compiler/rustc_middle/src/ty/instance.rs | 1 - compiler/rustc_middle/src/ty/mod.rs | 32 ++- compiler/rustc_middle/src/ty/print/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 123 ++++---- compiler/rustc_middle/src/ty/relate.rs | 65 +---- .../src/build/expr/as_constant.rs | 59 +++- compiler/rustc_mir_build/src/build/mod.rs | 118 ++++---- compiler/rustc_mir_build/src/thir/constant.rs | 75 ++--- .../src/thir/pattern/const_to_pat.rs | 3 +- .../rustc_mir_build/src/thir/pattern/mod.rs | 7 +- .../rustc_mir_dataflow/src/elaborate_drops.rs | 2 +- .../src/const_debuginfo.rs | 2 +- .../rustc_mir_transform/src/const_prop.rs | 17 +- .../src/elaborate_drops.rs | 2 +- compiler/rustc_mir_transform/src/generator.rs | 2 +- .../rustc_mir_transform/src/instcombine.rs | 8 +- compiler/rustc_mir_transform/src/lib.rs | 2 + .../src/lower_intrinsics.rs | 2 +- .../src/remove_noop_landing_pads.rs | 4 +- compiler/rustc_mir_transform/src/shim.rs | 4 +- compiler/rustc_monomorphize/src/collector.rs | 24 +- compiler/rustc_symbol_mangling/src/legacy.rs | 7 +- compiler/rustc_symbol_mangling/src/v0.rs | 88 +++--- .../src/traits/auto_trait.rs | 12 +- .../src/traits/const_evaluatable.rs | 9 +- .../src/traits/fulfill.rs | 28 +- .../src/traits/project.rs | 3 + .../src/traits/query/normalize.rs | 15 +- .../src/traits/select/mod.rs | 22 +- .../src/normalize_erasing_regions.rs | 1 - compiler/rustc_ty_utils/src/instance.rs | 2 - src/librustdoc/clean/utils.rs | 13 +- src/test/incremental/issue-54242.rs | 2 +- .../box_expr.main.ElaborateDrops.before.mir | 4 +- ...allocation2.main.ConstProp.after.64bit.mir | 32 +-- .../const_prop/boxes.main.ConstProp.diff | 6 +- .../derefer_inline_test.main.Derefer.diff | 8 +- ...line_into_box_place.main.Inline.64bit.diff | 12 +- ...issue_62289.test.ElaborateDrops.before.mir | 4 +- ...egion_subtyping_basic.main.nll.0.64bit.mir | 4 +- ...place.Test.SimplifyCfg-make_shim.after.mir | 4 +- ...ove_out.move_out_by_subslice.mir_map.0.mir | 8 +- ...y_move_out.move_out_from_end.mir_map.0.mir | 8 +- ...2_.AddMovesForPackedDrops.before.64bit.mir | 4 +- .../associated-consts/defaults-cyclic-fail.rs | 2 +- .../defaults-cyclic-fail.stderr | 28 +- ...9-assoc-const-static-recursion-impl.stderr | 19 +- ...onst-static-recursion-trait-default.stderr | 19 +- ...-assoc-const-static-recursion-trait.stderr | 19 +- src/test/ui/borrowck/issue-81899.rs | 2 + src/test/ui/borrowck/issue-81899.stderr | 18 +- .../borrowck/issue-88434-minimal-example.rs | 2 + .../issue-88434-minimal-example.stderr | 18 +- ...ssue-88434-removal-index-should-be-less.rs | 2 + ...-88434-removal-index-should-be-less.stderr | 18 +- .../different_generic_args_array.stderr | 2 +- .../const-generics/issues/issue-83765.stderr | 6 +- .../ui/const-ptr/out_of_bounds_read.stderr | 6 +- .../const-eval/const-eval-query-stack.rs | 3 +- .../const-eval/const-eval-query-stack.stderr | 24 +- .../ui/consts/const-float-bits-reject-conv.rs | 16 ++ .../const-float-bits-reject-conv.stderr | 107 ++++++- src/test/ui/consts/const-integer-bool-ops.rs | 10 + .../ui/consts/const-integer-bool-ops.stderr | 95 +++++-- .../const-mut-refs/issue-76510.64bit.stderr | 12 +- .../ui/consts/const-mut-refs/issue-76510.rs | 1 + src/test/ui/consts/const-size_of-cycle.stderr | 6 +- src/test/ui/consts/const-tup-index-span.rs | 1 + .../ui/consts/const-tup-index-span.stderr | 11 +- src/test/ui/consts/invalid-union.64bit.stderr | 2 +- src/test/ui/consts/issue-36163.stderr | 40 +-- src/test/ui/consts/issue-44415.rs | 2 +- src/test/ui/consts/issue-44415.stderr | 6 +- .../ui/consts/issue-77062-large-zst-array.rs | 2 +- src/test/ui/issues/issue-17252.stderr | 15 +- src/test/ui/issues/issue-23302-1.stderr | 17 +- src/test/ui/issues/issue-23302-2.stderr | 17 +- src/test/ui/issues/issue-23302-3.stderr | 30 +- src/test/ui/issues/issue-41394.rs | 1 + src/test/ui/issues/issue-41394.stderr | 11 +- src/test/ui/issues/issue-54954.rs | 2 + src/test/ui/issues/issue-54954.stderr | 18 +- .../ui/issues/issue-68010-large-zst-consts.rs | 2 +- ...issue-69602-type-err-during-codegen-ice.rs | 1 + ...e-69602-type-err-during-codegen-ice.stderr | 10 +- src/test/ui/resolve/issue-50599.rs | 1 + src/test/ui/resolve/issue-50599.stderr | 11 +- .../ui/type/type-dependent-def-issue-49241.rs | 1 + .../type-dependent-def-issue-49241.stderr | 11 +- .../clippy/clippy_lints/src/enum_clike.rs | 6 +- .../clippy_lints/src/large_const_arrays.rs | 5 +- .../clippy_lints/src/large_stack_arrays.rs | 5 +- .../src/matches/overlapping_arms.rs | 4 +- .../clippy/clippy_lints/src/non_copy_const.rs | 12 +- src/tools/clippy/clippy_utils/src/consts.rs | 116 ++++---- 116 files changed, 1601 insertions(+), 1027 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 3d14a0eca52bb..ef72e6efb946b 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -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> { 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 diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 7e0d3f9adaa28..9a995fbf65ca2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 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 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { 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); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 0c20324e45239..b7e5e7aea49ce 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -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>>, diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 6ee77db4017ea..51edf64de802a 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -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, @@ -25,6 +24,12 @@ pub use fn_queries::*; 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, 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, 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::>>()?; - let fields = tcx.arena.alloc_from_iter(fields); - Ok(mir::DestructuredConst { variant, fields }) + const_: ty::Const<'tcx>, +) -> Option> { + 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::>(); + 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::>(); + + (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`"), diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 7346d69bb5de3..080133275a606 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -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, - 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::>>() .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>, diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 597ca4cfcdd06..e9a9c0e171376 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -637,7 +637,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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) + } } } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 04410ca382859..64a74e9d7e206 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -34,6 +34,7 @@ pub mod interpret; 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(); diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 67a356918d1b9..3595a488d0c5b 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -765,7 +765,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { 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 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { 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(); diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 59c708fb7509a..93a067cb51606 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -20,7 +20,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; 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 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { u } + pub fn try_const_eval_resolve( + &self, + param_env: ty::ParamEnv<'tcx>, + unevaluated: ty::Unevaluated<'tcx>, + ty: Ty<'tcx>, + span: Option, + ) -> Result, 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 `::C`, in which case the given @@ -1634,7 +1656,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, unevaluated: ty::Unevaluated<'tcx>, span: Option, - ) -> EvalToConstValueResult<'tcx> { + ) -> EvalToValTreeResult<'tcx> { let substs = self.resolve_vars_if_possible(unevaluated.substs); debug!(?substs); @@ -1658,7 +1680,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // 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: diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 8fc957cf49c88..69353232f0659 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -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 @@ impl<'tcx> TyCtxt<'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 `::C`, in which case the given @@ -59,6 +79,33 @@ impl<'tcx> TyCtxt<'tcx> { } } + #[instrument(level = "debug", skip(self))] + pub fn const_eval_resolve_for_typeck( + self, + param_env: ty::ParamEnv<'tcx>, + ct: ty::Unevaluated<'tcx>, + span: Option, + ) -> 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 @@ impl<'tcx> TyCtxt<'tcx> { 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 @@ impl<'tcx> TyCtxt<'tcx> { } } + /// 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, + ) -> 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 @@ impl<'tcx> TyCtxtAt<'tcx> { 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. diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 146ae45e46898..f566467b7ce09 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -78,6 +78,7 @@ impl<'tcx> ConstValue<'tcx> { Some(self.try_to_scalar()?.assert_int()) } + #[inline(always)] pub fn try_to_bits(&self, size: Size) -> Option { self.try_to_scalar_int()?.to_bits(size).ok() } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 1511b51fa2548..512615ccbab85 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -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 @@ impl<'tcx> BasicBlockData<'tcx> { } 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 @@ impl<'tcx> Operand<'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 @@ impl<'tcx> Constant<'tcx> { } } -impl<'tcx> From> 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> { match self { ConstantKind::Ty(c) => Some(*c), @@ -2976,6 +2973,7 @@ impl<'tcx> ConstantKind<'tcx> { } } + #[inline(always)] pub fn ty(&self) -> Ty<'tcx> { match self { ConstantKind::Ty(c) => c.ty(), @@ -2983,10 +2981,10 @@ impl<'tcx> ConstantKind<'tcx> { } } - pub fn try_val(&self) -> Option> { + pub fn try_val(&self, tcx: TyCtxt<'tcx>) -> Option> { 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 @@ impl<'tcx> ConstantKind<'tcx> { } #[inline] - pub fn try_to_value(self) -> Option> { + pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option> { 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 { - 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 { - Some(self.try_to_value()?.try_to_scalar()?.assert_int()) + Some(self.try_to_scalar()?.assert_int()) } #[inline] @@ -3025,9 +3035,7 @@ impl<'tcx> ConstantKind<'tcx> { 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 @@ impl<'tcx> ConstantKind<'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 @@ impl<'tcx> ConstantKind<'tcx> { 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 @@ impl<'tcx> ConstantKind<'tcx> { 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 @@ impl<'tcx> ConstantKind<'tcx> { } _ => 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 @@ impl<'tcx> ConstantKind<'tcx> { kind: ty::ConstKind::Param(ty::ParamConst::new(index, name)), ty, }); + debug!(?ty_const); return Self::Ty(ty_const); } @@ -3253,8 +3277,12 @@ impl<'tcx> ConstantKind<'tcx> { 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 @@ impl<'tcx> ConstantKind<'tcx> { }), 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>) -> 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::>(); + 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(()) }) } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 739c543dea773..a81a60df2be8a 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -454,7 +454,12 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { 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 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { 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 @@ pub fn write_allocations<'tcx>( ) -> impl DoubleEndedIterator + '_ { alloc.inner().relocations().values().map(|id| *id) } - fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator + '_ { + + fn alloc_ids_from_const_val(val: ConstValue<'_>) -> impl Iterator + '_ { match val { ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _)) => { Either::Left(Either::Left(std::iter::once(ptr.provenance))) @@ -681,17 +687,11 @@ pub fn write_allocations<'tcx>( struct CollectAllocIds(BTreeSet); 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)); } } } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 01945b543b14b..da4793fa039d0 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -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, - pub fields: &'tcx [mir::ConstantKind<'tcx>], + pub fields: &'tcx [ConstantKind<'tcx>], } /// Coverage information summarized from a MIR if instrumented for source code coverage (see diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index c859d93043e3e..c65e79a80fb8e 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -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 @@ impl<'tcx> TerminatorKind<'tcx> { .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() }) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5b48f164016f7..22b1ad4190489 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -968,7 +968,6 @@ rustc_queries! { key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>> ) -> EvalToValTreeResult<'tcx> { desc { "evaluate type-level constant" } - remap_env_constness } /// Converts a type level constant value into `ConstValue` @@ -980,7 +979,7 @@ rustc_queries! { /// 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> { + query try_destructure_const(key: ty::Const<'tcx>) -> Option> { desc { "destructure type level constant"} } @@ -991,15 +990,6 @@ rustc_queries! { 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( diff --git a/compiler/rustc_middle/src/traits/chalk.rs b/compiler/rustc_middle/src/traits/chalk.rs index 015bdb5783f36..70abdb9ab4cd7 100644 --- a/compiler/rustc_middle/src/traits/chalk.rs +++ b/compiler/rustc_middle/src/traits/chalk.rs @@ -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>; type InternedLifetime = Box>; type InternedConst = Box>; - type InternedConcreteConst = ConstValue<'tcx>; + type InternedConcreteConst = ty::ValTree<'tcx>; type InternedGenericArg = Box>; type InternedGoal = Box>; type InternedGoals = Vec>; diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 0e87a05bade09..47abbb723dce1 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -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 @@ impl<'tcx> Const<'tcx> { /// 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 @@ impl<'tcx> Const<'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 @@ impl<'tcx> Const<'tcx> { /// 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 { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 35d286d2c5781..10d03065c795f 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -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 @@ static_assert_size!(ConstKind<'_>, 40); impl<'tcx> ConstKind<'tcx> { #[inline] - pub fn try_to_value(self) -> Option> { + pub fn try_to_value(self) -> Option> { if let ConstKind::Value(val) = self { Some(val) } else { None } } @@ -86,7 +86,7 @@ impl<'tcx> ConstKind<'tcx> { #[inline] pub fn try_to_scalar_int(self) -> Option { - 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, 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, 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, ErrorGuaranteed>> { if let ConstKind::Unevaluated(unevaluated) = self { use crate::mir::interpret::ErrorHandled; @@ -166,14 +208,29 @@ impl<'tcx> ConstKind<'tcx> { 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 diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 418848f69d726..973dc3dd4a10a 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -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 @@ impl<'tcx> ValTree<'tcx> { _ => 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> { + self.try_to_scalar_int().map(Scalar::Int) + } + + pub fn try_to_scalar_int(self) -> Option { + match self { + Self::Leaf(s) => Some(s), + Self::Branch(_) => None, + } + } + + pub fn try_to_machine_usize(self, tcx: TyCtxt<'tcx>) -> Option { + 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::>(); + + 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::>(); + + return Some(tcx.arena.alloc_from_iter(leafs.into_iter())); + } + _ => {} + }, + _ => {} + } + + None + } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5c0cf534b8025..0930f3edf7254 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -8,7 +8,7 @@ use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintLevelSource}; 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 @@ impl<'tcx> CommonConsts<'tcx> { 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 @@ impl<'tcx> TyCtxt<'tcx> { }; 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 { - 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 @@ impl<'tcx> TyCtxt<'tcx> { /// `*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 @@ impl<'tcx> TyCtxt<'tcx> { 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 @@ impl<'tcx> TyCtxt<'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 @@ impl<'tcx> TyCtxt<'tcx> { eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>], ) -> &'tcx List>> { 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 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List> { - 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 { - 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> { - 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 { - 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( diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index b7130e69f3501..e8dd179eac198 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -369,7 +369,6 @@ impl<'tcx> Instance<'tcx> { } // 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>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7f0f3755c4b33..8da447d16fbfd 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2161,22 +2161,28 @@ impl<'tcx> TyCtxt<'tcx> { } /// 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(..) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 5ad93d778208d..7a096bbc4d96f 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -98,7 +98,6 @@ pub trait Printer<'tcx>: Sized { // Defaults (should not be overridden): - #[instrument(skip(self), level = "debug")] fn default_print_def_path( self, def_id: DefId, @@ -302,6 +301,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Region<'_> { 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 { cx.print_type(*self) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 05f332cdd5fd5..3b11f7572a640 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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 @@ pub trait PrettyPrinter<'tcx>: } } } 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 @@ pub trait PrettyPrinter<'tcx>: } 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 @@ pub trait PrettyPrinter<'tcx>: 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 @@ pub trait PrettyPrinter<'tcx>: 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 @@ pub trait PrettyPrinter<'tcx>: 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 { 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 @@ pub trait PrettyPrinter<'tcx>: 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 @@ pub trait PrettyPrinter<'tcx>: } _ => 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 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { Ok(inner) } - #[instrument(skip(self), level = "debug")] fn prepare_late_bound_region_info(&mut self, value: &ty::Binder<'tcx, T>) where T: TypeFoldable<'tcx>, @@ -2309,9 +2293,8 @@ impl<'tcx> FmtPrinter<'_, '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 { - 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 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { // 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 { let not_previously_inserted = self.type_collector.insert(ty); if not_previously_inserted { @@ -2353,6 +2335,7 @@ where { type Output = P; type Error = P::Error; + fn print(&self, cx: P) -> Result { cx.in_binder(self) } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 31103b8d77ea3..51980acd38f74 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -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>> { fn relate>( relation: &mut R, diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index a87134d1f52e3..3d6e50f0c0622 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } } + +#[instrument(skip(tcx, lit_input))] +pub(crate) fn lit_to_mir_constant<'tcx>( + tcx: TyCtxt<'tcx>, + lit_input: LitToConstInput<'tcx>, +) -> Result, 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)) +} diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 793066e43c3c7..51f7aa642c84f 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -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; @@ -14,14 +14,16 @@ use rustc_index::vec::{Idx, IndexVec}; 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) -> Body<'_ }) } -#[instrument(skip(tcx, lit_input))] -pub(crate) fn lit_to_mir_constant<'tcx>( - tcx: TyCtxt<'tcx>, - lit_input: LitToConstInput<'tcx>, -) -> Result, 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 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } +fn parse_float_into_constval<'tcx>( + num: Symbol, + float_ty: ty::FloatTy, + neg: bool, +) -> Option> { + 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, 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 diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index d82e6688633d0..cfb09ecedd635 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -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> { +) -> Option { 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::() else { return None }; let mut f = num.parse::().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::() else { return None }; let mut f = num.parse::().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> { + parse_float_into_scalar(num, float_ty, neg).map(|s| ty::ValTree::Leaf(s.try_to_int().unwrap())) } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index f694e009ab957..b423c64544747 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -371,6 +371,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { } 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 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // 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 { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 83175439b70fb..e28cb67217c89 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -185,11 +185,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } (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() } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 027af5b9c1f2d..8d16c5f22c3f4 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -1032,7 +1032,7 @@ where 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()), })) } diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs index 3577b3d2d80c6..8944ebed9a704 100644 --- a/compiler/rustc_mir_transform/src/const_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs @@ -19,7 +19,7 @@ impl<'tcx> MirPass<'tcx> for ConstDebugInfo { 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) { diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 2529a7c4232b2..412a5b4fc9104 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -67,6 +67,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { 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 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { 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 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { 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, }))); } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 8a9f21073165b..e0e27c53f1822 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -470,7 +470,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, '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), }))) } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 89895fddd0cfa..f3c67319596d1 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -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, diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs index 4fbb764337863..ea10ec5f25c15 100644 --- a/compiler/rustc_mir_transform/src/instcombine.rs +++ b/compiler/rustc_mir_transform/src/instcombine.rs @@ -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 @@ impl<'tcx> InstCombineContext<'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))); } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0e52da57e60b7..b893225146578 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -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"); diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 65801069560b3..989b94b68c101 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -34,7 +34,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { 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), }))), ))), }); diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index f925d13b2fb91..89808d3d4cdbd 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -15,7 +15,7 @@ impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { 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 @@ impl RemoveNoopLandingPads { } 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); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 78a4ece2ecbb3..3be1783ae3389 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -430,7 +430,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { 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::>(), ) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index dfaf464587be2..2af22e129a5f7 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -323,6 +323,7 @@ impl<'tcx> InliningMap<'tcx> { } } +#[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> { 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( tcx: TyCtxt<'tcx>, starting_point: Spanned>, @@ -752,13 +755,15 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { /// 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 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { 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 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { 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 @@ impl<'v> RootCollector<'_, 'v> { /// 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>, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 2f7e413b087ae..f67b87a6a52b8 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -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 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn print_const(self, ct: ty::Const<'tcx>) -> Result { // 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(_)); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index f79f7a4ebdfc8..ff07063679746 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -5,7 +5,6 @@ use rustc_hir as hir; 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 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { 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 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { } // 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 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { }; match *ct.ty().kind() { - ty::Array(..) => { + ty::Array(..) | ty::Slice(_) => { self.push("A"); self = print_field_list(self)?; } @@ -723,7 +736,6 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { _ => unreachable!(), } } - _ => { bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct); } diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c95d43b71cf1b..a63790b594d83 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -6,6 +6,7 @@ use super::*; 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 @@ impl<'tcx> AutoTraitFinder<'tcx> { 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 { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 6cf39be2a9d5c..5d08ea99ac64a 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -13,9 +13,7 @@ use rustc_hir::def::DefKind; 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 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> { 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); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 50735ef048bf6..7c4b5decee4f4 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -407,7 +407,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { 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 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { 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) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 565f3f509db39..a72f90746edfa 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -618,11 +618,14 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, '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) } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index b00f8fe73a1de..b80a27eb07d06 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -100,7 +100,7 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { } } -/// 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 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ) -> Result, 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), } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 07e7bad6cb787..a002006f0e676 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -636,13 +636,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { 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 @@ impl<'o, 'tcx> TraitObligationStackList<'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 + } } } diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index a8a324dec97ba..5d394ed2263ff 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -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>, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 7c89ce125e01d..552db5406df8d 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -112,7 +112,6 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { } } -#[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, SubstsRef<'tcx>)>, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index e7da6eff51959..7125a7578bd81 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -15,7 +15,6 @@ use rustc_data_structures::thin_vec::ThinVec; 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 { - 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); diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs index 9e449de0cf5ac..d32df9544997e 100644 --- a/src/test/incremental/issue-54242.rs +++ b/src/test/incremental/issue-54242.rs @@ -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() {} diff --git a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir index 5b1ffc76fe5b3..d23203742f07b 100644 --- a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir @@ -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()) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) } } bb1: { diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index ef651f01c9b98..e2acd610b8053 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -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 } diff --git a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff index 342c987343eac..6a490e48b8ed3 100644 --- a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff @@ -22,13 +22,13 @@ 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()) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) } } bb1: { diff --git a/src/test/mir-opt/derefer_inline_test.main.Derefer.diff b/src/test/mir-opt/derefer_inline_test.main.Derefer.diff index e131adae2b683..832a773777707 100644 --- a/src/test/mir-opt/derefer_inline_test.main.Derefer.diff +++ b/src/test/mir-opt/derefer_inline_test.main.Derefer.diff @@ -16,10 +16,10 @@ StorageLive(_1); // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 _2 = SizeOf(std::boxed::Box); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12 _3 = AlignOf(std::boxed::Box); // 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()) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) } } bb1: { @@ -56,10 +56,10 @@ } bb7 (cleanup): { - _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb6; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 + _6 = : unsafe fn(Unique::>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}(move (_5.0: std::ptr::Unique>), 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>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(ValTree::Branch(..)) } } bb8 (cleanup): { diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index c19cbe3e5b0df..806e7b269e249 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -23,10 +23,10 @@ StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 _2 = SizeOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 _3 = AlignOf(std::vec::Vec); // 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()) } + // + 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:: { ptr: Unique:: { pointer: NonNull:: { pointer: {0x4 as *const u32} }, _marker: PhantomData:: }, 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::::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, val: Value(ByRef(..)) } ++ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) } + Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ((*_7).0: alloc::raw_vec::RawVec) = 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 @@ -71,10 +71,10 @@ - } - - bb5 (cleanup): { -- _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- _6 = : unsafe fn(Unique::>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}(move (_5.0: std::ptr::Unique>), 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>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } +- // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(ValTree::Branch(..)) } } } diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index 4d06b91e6dc61..0a18710b2cc6f 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -31,10 +31,10 @@ fn test() -> Option> { 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()) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) } } bb1: { diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 382c89a1fb9b5..c555e0441f423 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -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: { diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir index 09cf06cacd920..8ae79b6604462 100644 --- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir @@ -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 = ::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + _3 = : for<'r> fn(&'r mut Test) {::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) {::drop}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r mut Test) {::drop}, val: Value(ValTree::Branch(..)) } } bb1: { diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir index d7d2cdf9b0c75..3b241264aacfa 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir @@ -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()) } + // + 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()) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) } } bb3: { diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir index 18bc1a17c1b50..c59e92dc82927 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir @@ -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()) } + // + 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()) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(ValTree::Branch(..)) } } bb3: { diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir index 5dc81b787a9fa..3aa95cd3f105f 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir @@ -31,9 +31,9 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { bb6: { _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - _3 = 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::) { 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) { as Drop>::drop}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r mut Vec) { as Drop>::drop}, val: Value(ValTree::Branch(..)) } } } diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.rs b/src/test/ui/associated-consts/defaults-cyclic-fail.rs index 2f1858d39b3c6..a1c6840a0f1b3 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.rs @@ -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; } diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr index 3fb4ab72fe6d6..550897790e9ff 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -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 | diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index 3d696bb049cd9..8c85fadf60014 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for ` $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 `::BAR`... -note: ...which requires simplifying constant for the type system `::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 `::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 `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index 71e26245e16af..251a69aeabaa2 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -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 = ::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 = ::BAR; @@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... | LL | const DEFAULT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `::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 | diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 020d758e153c2..45e911d002912 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -4,13 +4,7 @@ error[E0391]: cycle detected when elaborating drops for ` $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 - | -LL | const TRAIT_REF_BAR: u32 = ::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 = ::BAR; @@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... | LL | const TRAIT_REF_BAR: u32 = ::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `::BAR`... -note: ...which requires simplifying constant for the type system `::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 `::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 `::BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | diff --git a/src/test/ui/borrowck/issue-81899.rs b/src/test/ui/borrowck/issue-81899.rs index 356517745ffcd..9b60612037dd6 100644 --- a/src/test/ui/borrowck/issue-81899.rs +++ b/src/test/ui/borrowck/issue-81899.rs @@ -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(_: &[u8], _: F) -> &[u8] where diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr index 59bf00d0012cd..92ebd5a220d90 100644 --- a/src/test/ui/borrowck/issue-81899.stderr +++ b/src/test/ui/borrowck/issue-81899.stderr @@ -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 + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.rs b/src/test/ui/borrowck/issue-88434-minimal-example.rs index 632f8dc3ad6f5..7618d001e86ee 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.rs +++ b/src/test/ui/borrowck/issue-88434-minimal-example.rs @@ -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) where diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr index d9635e1ee464c..d46cd862e34aa 100644 --- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr +++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr @@ -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 + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs index f0a6dcd4eb3b8..b1fc1615ece77 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs @@ -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(_: &[u8], _: F) -> &[u8] where diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index 44e244ae9cc3f..e6b07aba74d42 100644 --- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -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 + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/different_generic_args_array.stderr b/src/test/ui/const-generics/different_generic_args_array.stderr index c0709a996ce37..f0b9035357d82 100644 --- a/src/test/ui/const-generics/different_generic_args_array.stderr +++ b/src/test/ui/const-generics/different_generic_args_array.stderr @@ -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]>` diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr index 8705a39fa4bcd..98931a3936f52 100644 --- a/src/test/ui/const-generics/issues/issue-83765.stderr +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -10,7 +10,11 @@ note: ...which requires checking if `TensorDimension` fulfills its obligations.. LL | trait TensorDimension { | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires resolving instance ` as TensorDimension>::DIM`, completing the cycle - = note: cycle used when normalizing ` 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 diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr index 678714d0e055a..52b173c4d04a8 100644 --- a/src/test/ui/const-ptr/out_of_bounds_read.stderr +++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr @@ -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::` 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::` 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::` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL | ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs index e73e54ff5f1b3..c9460498951fd 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs @@ -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 @@ const X: i32 = 1 / 0; //~WARN any use of this value will cause an error 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); } diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr index 8bd5c08dc4649..b74d5a2722bd8 100644 --- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr +++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr @@ -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 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 + 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 diff --git a/src/test/ui/consts/const-float-bits-reject-conv.rs b/src/test/ui/consts/const-float-bits-reject-conv.rs index 122f5b97eee06..b156ded4a6c2a 100644 --- a/src/test/ui/consts/const-float-bits-reject-conv.rs +++ b/src/test/ui/consts/const-float-bits-reject-conv.rs @@ -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 } } diff --git a/src/test/ui/consts/const-float-bits-reject-conv.stderr b/src/test/ui/consts/const-float-bits-reject-conv.stderr index b39e881970176..f3fd098e848a2 100644 --- a/src/test/ui/consts/const-float-bits-reject-conv.stderr +++ b/src/test/ui/consts/const-float-bits-reject-conv.stderr @@ -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 + +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 + +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 + +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 + 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::::to_bits::ct_f64_to_u64}, [closure@core::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::::to_bits::ct_f64_to_u64}, [closure@core::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 + +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 + +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 + +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 + +error: aborting due to 12 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-integer-bool-ops.rs b/src/test/ui/consts/const-integer-bool-ops.rs index 35915a7a606a4..6924956bdf706 100644 --- a/src/test/ui/consts/const-integer-bool-ops.rs +++ b/src/test/ui/consts/const-integer-bool-ops.rs @@ -6,6 +6,7 @@ const X: usize = 42 && 39; //~| 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 @@ const X1: usize = 42 || 39; //~| 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 @@ const X2: usize = -42 || -39; //~| 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 @@ -33,36 +36,43 @@ const X3: usize = -42 && -39; //~| 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; diff --git a/src/test/ui/consts/const-integer-bool-ops.stderr b/src/test/ui/consts/const-integer-bool-ops.stderr index 4e503e5a5c0a4..9001fefd1029f 100644 --- a/src/test/ui/consts/const-integer-bool-ops.stderr +++ b/src/test/ui/consts/const-integer-bool-ops.stderr @@ -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`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr index 61b00be345fee..0f420ae1b6b7c 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr +++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr @@ -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>((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`. diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs index 143d2fb6b9a3a..08cf64ee330db 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.rs +++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs @@ -9,6 +9,7 @@ const S: &'static mut str = &mut " hello "; const fn trigger() -> [(); unsafe { let s = transmute::<(*const u8, usize), &ManuallyDrop>((S.as_ptr(), 3)); + //~^ ERROR evaluation of constant value failed 0 }] { [(); 0] diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 1067eb003f7c7..0772b1712c5e2 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -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::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -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::()] @@ -17,7 +17,7 @@ LL | bytes: [u8; std::mem::size_of::()] = 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 | diff --git a/src/test/ui/consts/const-tup-index-span.rs b/src/test/ui/consts/const-tup-index-span.rs index 8057d64369a23..763263c6aeb4f 100644 --- a/src/test/ui/consts/const-tup-index-span.rs +++ b/src/test/ui/consts/const-tup-index-span.rs @@ -4,6 +4,7 @@ const TUP: (usize,) = 5usize << 64; //~^ ERROR mismatched types //~| expected tuple, found `usize` const ARR: [i32; TUP.0] = []; +//~^ ERROR evaluation of constant value failed fn main() { } diff --git a/src/test/ui/consts/const-tup-index-span.stderr b/src/test/ui/consts/const-tup-index-span.stderr index d301f8c4054c2..b178e05e27a09 100644 --- a/src/test/ui/consts/const-tup-index-span.stderr +++ b/src/test/ui/consts/const-tup-index-span.stderr @@ -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`. diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr index 9df1a89694eba..6bfa97a2fded7 100644 --- a/src/test/ui/consts/invalid-union.64bit.stderr +++ b/src/test/ui/consts/invalid-union.64bit.stderr @@ -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 diff --git a/src/test/ui/consts/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr index 113f86cf0f99f..9ac6c984cb0cd 100644 --- a/src/test/ui/consts/issue-36163.stderr +++ b/src/test/ui/consts/issue-36163.stderr @@ -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 diff --git a/src/test/ui/consts/issue-44415.rs b/src/test/ui/consts/issue-44415.rs index 71e764620d140..79f415e6a2c10 100644 --- a/src/test/ui/consts/issue-44415.rs +++ b/src/test/ui/consts/issue-44415.rs @@ -4,7 +4,7 @@ use std::intrinsics; struct Foo { bytes: [u8; unsafe { intrinsics::size_of::() }], - //~^ ERROR cycle detected when simplifying constant for the type system + //~^ ERROR cycle detected when evaluate type-level constant x: usize, } diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr index 9e3db5ce9a402..6641300fc9a87 100644 --- a/src/test/ui/consts/issue-44415.stderr +++ b/src/test/ui/consts/issue-44415.stderr @@ -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::() }], | ^^^^^^ | -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::() }], @@ -17,7 +17,7 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::() }], = 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 | diff --git a/src/test/ui/consts/issue-77062-large-zst-array.rs b/src/test/ui/consts/issue-77062-large-zst-array.rs index 0566b802e75b6..7a00fe964ab08 100644 --- a/src/test/ui/consts/issue-77062-large-zst-array.rs +++ b/src/test/ui/consts/issue-77062-large-zst-array.rs @@ -1,4 +1,4 @@ -// build-pass +// check-pass fn main() { let _ = &[(); usize::MAX]; diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr index 1148577016ab4..4856418ed6002 100644 --- a/src/test/ui/issues/issue-17252.stderr +++ b/src/test/ui/issues/issue-17252.stderr @@ -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 | diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr index d3a1993536a00..9366050d7ecdf 100644 --- a/src/test/ui/issues/issue-23302-1.stderr +++ b/src/test/ui/issues/issue-23302-1.stderr @@ -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 diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr index d3b78ea1af5f5..b97ae287a47a9 100644 --- a/src/test/ui/issues/issue-23302-2.stderr +++ b/src/test/ui/issues/issue-23302-2.stderr @@ -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 diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr index 5233b832ecc79..1a07d4a95bcfa 100644 --- a/src/test/ui/issues/issue-23302-3.stderr +++ b/src/test/ui/issues/issue-23302-3.stderr @@ -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 diff --git a/src/test/ui/issues/issue-41394.rs b/src/test/ui/issues/issue-41394.rs index 06a330813406a..64873ac35a002 100644 --- a/src/test/ui/issues/issue-41394.rs +++ b/src/test/ui/issues/issue-41394.rs @@ -5,6 +5,7 @@ enum Foo { enum Bar { A = Foo::A as isize + //~^ ERROR evaluation of constant value failed } fn main() {} diff --git a/src/test/ui/issues/issue-41394.stderr b/src/test/ui/issues/issue-41394.stderr index fa95ca9c18a10..47a24547d4533 100644 --- a/src/test/ui/issues/issue-41394.stderr +++ b/src/test/ui/issues/issue-41394.stderr @@ -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`. diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs index 42a4d5b674b22..ddd3914154147 100644 --- a/src/test/ui/issues/issue-54954.rs +++ b/src/test/ui/issues/issue-54954.rs @@ -9,6 +9,8 @@ trait Tt { } fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed z } diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index efe2ef504a2ba..6e8d3cac9a7e4 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -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`. diff --git a/src/test/ui/issues/issue-68010-large-zst-consts.rs b/src/test/ui/issues/issue-68010-large-zst-consts.rs index 3277df69c0285..32f51d513d122 100644 --- a/src/test/ui/issues/issue-68010-large-zst-consts.rs +++ b/src/test/ui/issues/issue-68010-large-zst-consts.rs @@ -1,4 +1,4 @@ -// build-pass +// check-pass fn main() { println!("{}", [(); usize::MAX].len()); diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs index 2c5257ce063cb..6851b67cb3b3a 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -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 } diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr index 8ae0f8b804c93..cb5b397849c06 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -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`. diff --git a/src/test/ui/resolve/issue-50599.rs b/src/test/ui/resolve/issue-50599.rs index 00588735b9a59..78a20cf8ebb05 100644 --- a/src/test/ui/resolve/issue-50599.rs +++ b/src/test/ui/resolve/issue-50599.rs @@ -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 } diff --git a/src/test/ui/resolve/issue-50599.stderr b/src/test/ui/resolve/issue-50599.stderr index 4cc035cb11e20..f0cb784f56c48 100644 --- a/src/test/ui/resolve/issue-50599.stderr +++ b/src/test/ui/resolve/issue-50599.stderr @@ -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`. diff --git a/src/test/ui/type/type-dependent-def-issue-49241.rs b/src/test/ui/type/type-dependent-def-issue-49241.rs index 4b6bc6124dbf3..f37f093d9ede7 100644 --- a/src/test/ui/type/type-dependent-def-issue-49241.rs +++ b/src/test/ui/type/type-dependent-def-issue-49241.rs @@ -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 } diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr index 64c7687f7a882..02f267c6c8d73 100644 --- a/src/test/ui/type/type-dependent-def-issue-49241.stderr +++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr @@ -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`. diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 10be245b36293..5d687d06f6f46 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -48,10 +48,10 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { 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); diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index ed47490e230ce..e10993ba7ddce 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -3,7 +3,6 @@ use if_chain::if_chain; 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 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { 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; diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 4ca69465fad41..0acbd81aec343 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -3,7 +3,6 @@ use clippy_utils::source::snippet; 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 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { 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 { diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index c0b3e95b18523..afca7530556b2 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -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)?; diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 8db41ba6ee296..9f6fca27b2295 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -13,7 +13,7 @@ use rustc_hir::{ 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, ErrorHandled>, + result: Result>, ErrorHandled>, ty: Ty<'tcx>, ) -> bool { fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool { @@ -142,7 +142,7 @@ fn is_value_unfrozen_raw<'tcx>( // 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 is_value_unfrozen_raw<'tcx>( // 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, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 159c5d53d0292..c31c560f427f2 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -7,7 +7,6 @@ use rustc_data_structures::sync::Lrc; 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 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { 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 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -pub fn miri_to_const(result: ty::Const<'_>) -> Option { - use rustc_middle::mir::interpret::ConstValue; +pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: ty::Const<'tcx>) -> Option { 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::>>() - .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::>>() - .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::>>() + .map(Constant::Vec) + }), + _ => None, + } + }, _ => None, }, - // FIXME: implement other array type conversions. + // FIXME: implement other conversions. _ => None, - }, - _ => None, + } }, - // FIXME: implement other conversions. _ => None, } } From 5c95a3db2ac54c94b037e0b1b84d29b12ccf8e7a Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 2 Jun 2022 15:15:01 +0200 Subject: [PATCH 02/11] fix clippy test failures --- compiler/rustc_middle/src/ty/consts.rs | 8 ++ .../rustc_mir_build/src/thir/pattern/mod.rs | 2 +- .../clippy/clippy_lints/src/enum_clike.rs | 4 +- .../src/matches/overlapping_arms.rs | 19 ++- .../clippy/clippy_lints/src/non_copy_const.rs | 18 +-- src/tools/clippy/clippy_utils/src/consts.rs | 125 +++++++++++------- 6 files changed, 111 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 47abbb723dce1..fe5c5be15f5a3 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -199,6 +199,14 @@ impl<'tcx> Const<'tcx> { tcx.mk_const(ConstS { kind: ConstKind::Value(val), ty }) } + /// Panics if self.kind != ty::ConstKind::Value + pub fn to_valtree(self) -> ty::ValTree<'tcx> { + match self.val() { + ty::ConstKind::Value(valtree) => valtree, + _ => bug!("expected ConstKind::Value"), + } + } + 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) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index e28cb67217c89..f5d957e30ff09 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -798,7 +798,7 @@ 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(tcx), b.try_val(tcx)) + ) = (a.try_to_value(tcx), b.try_to_value(tcx)) { let a_bytes = get_slice_bytes(&tcx, a_val); let b_bytes = get_slice_bytes(&tcx, b_val); diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 5d687d06f6f46..b326d864d4bff 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -48,9 +48,9 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { let mut ty = cx.tcx.type_of(def_id.to_def_id()); let constant = cx .tcx - .const_eval_poly_for_typeck(def_id.to_def_id()) + .const_eval_poly(def_id.to_def_id()) .ok() - .and_then(|val| val.map(|valtree| rustc_middle::ty::Const::from_value(cx.tcx, valtree, ty))); + .and_then(|val| Some(rustc_middle::mir::ConstantKind::from_value(val, 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() { diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index afca7530556b2..ae69ca8a3393d 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_note; use core::cmp::Ordering; use rustc_hir::{Arm, Expr, PatKind, RangeEnd}; use rustc_lint::LateContext; +use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -34,11 +35,25 @@ 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(cx.tcx, ty.numeric_min_val(cx.tcx)?)?, + None => { + let min_val_const = ty.numeric_min_val(cx.tcx)?; + let min_constant = mir::ConstantKind::from_value( + cx.tcx.valtree_to_const_val((ty, min_val_const.to_valtree())), + ty, + ); + miri_to_const(cx.tcx, min_constant)? + }, }; let rhs_const = match rhs { Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0, - None => miri_to_const(cx.tcx, ty.numeric_max_val(cx.tcx)?)?, + None => { + let max_val_const = ty.numeric_max_val(cx.tcx)?; + let max_constant = mir::ConstantKind::from_value( + cx.tcx.valtree_to_const_val((ty, max_val_const.to_valtree())), + ty, + ); + miri_to_const(cx.tcx, max_constant)? + }, }; let lhs_val = lhs_const.int_value(cx, ty)?; let rhs_val = rhs_const.int_value(cx, ty)?; diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 9f6fca27b2295..7163cfe5e3a2c 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -13,9 +13,10 @@ use rustc_hir::{ BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass, Lint}; -use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::mir; +use rustc_middle::mir::interpret::{ConstValue, ErrorHandled}; use rustc_middle::ty::adjustment::Adjust; -use rustc_middle::ty::{self, Const, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use rustc_typeck::hir_ty_to_ty; @@ -133,22 +134,21 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { fn is_value_unfrozen_raw<'tcx>( cx: &LateContext<'tcx>, - result: Result>, ErrorHandled>, + result: Result, ErrorHandled>, ty: Ty<'tcx>, ) -> bool { - fn inner<'tcx>(cx: &LateContext<'tcx>, val: Const<'tcx>) -> bool { + fn inner<'tcx>(cx: &LateContext<'tcx>, val: mir::ConstantKind<'tcx>) -> bool { match val.ty().kind() { // the fact that we have to dig into every structs to search enums // 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(val); + let val = cx.tcx.destructure_mir_constant(cx.param_env, val); val.fields.iter().any(|field| inner(cx, *field)) }, _ => false, } } - result.map_or_else( |err| { // Consider `TooGeneric` cases as being unfrozen. @@ -174,19 +174,19 @@ fn is_value_unfrozen_raw<'tcx>( // I chose this way because unfrozen enums as assoc consts are rare (or, hopefully, none). err == ErrorHandled::TooGeneric }, - |val| val.map_or(false, |val| inner(cx, Const::from_value(cx.tcx, val, ty))), + |val| inner(cx, mir::ConstantKind::from_value(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_for_typeck(body_id.hir_id.owner.to_def_id()); + let result = cx.tcx.const_eval_poly(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_for_typeck( + let result = cx.tcx.const_eval_resolve( cx.param_env, ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), None, diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index c31c560f427f2..ec323806fbf93 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -7,6 +7,8 @@ use rustc_data_structures::sync::Lrc; 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; +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}; @@ -422,13 +424,13 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { let result = self .lcx .tcx - .const_eval_resolve_for_typeck( + .const_eval_resolve( self.param_env, ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), None, ) .ok() - .and_then(|val| val.map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty)))?; + .and_then(|val| Some(rustc_middle::mir::ConstantKind::from_value(val, ty)))?; let result = miri_to_const(self.lcx.tcx, result); if result.is_some() { self.needed_resolution = true; @@ -579,69 +581,90 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: ty::Const<'tcx>) -> Option { - match result.kind() { +fn try_const_to_constant<'tcx>(tcx: TyCtxt<'tcx>, c: ty::Const<'tcx>) -> Option { + match c.kind() { 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( + let const_val = tcx.valtree_to_const_val((c.ty(), valtree)); + miri_to_const(tcx, mir::ConstantKind::from_value(const_val, c.ty())) + }, + _ => None, + } +} + +pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option { + use rustc_middle::mir::interpret::ConstValue; + match result { + mir::ConstantKind::Val(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( int.try_into().expect("invalid f32 bit representation"), ))), - (ty::ValTree::Leaf(int), ty::Float(FloatTy::F64)) => Some(Constant::F64(f64::from_bits( + ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( int.try_into().expect("invalid f64 bit representation"), ))), - (ty::ValTree::Leaf(int), ty::RawPtr(type_and_mut)) => { + ty::RawPtr(type_and_mut) => { if let ty::Uint(_) = type_and_mut.ty.kind() { return Some(Constant::RawPtr(int.assert_bits(int.size()))); } None }, - (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::>>() - .map(Constant::Vec) - }), - _ => None, - } - }, - _ => None, - }, // FIXME: implement other conversions. _ => None, } }, + mir::ConstantKind::Val(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, + }, + mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { + ty::Array(sub_type, len) => match sub_type.kind() { + ty::Float(FloatTy::F32) => match try_const_to_constant(tcx, *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::>>() + .map(Constant::Vec), + _ => None, + }, + ty::Float(FloatTy::F64) => match try_const_to_constant(tcx, *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::>>() + .map(Constant::Vec), + _ => None, + }, + // FIXME: implement other array type conversions. + _ => None, + }, + _ => None, + }, + // FIXME: implement other conversions. _ => None, } } From dbef6e450799c0da7ec3c749fd7574fe8c6755da Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 2 Jun 2022 19:42:29 +0200 Subject: [PATCH 03/11] address review --- Cargo.lock | 1 - .../rustc_const_eval/src/const_eval/error.rs | 2 + .../rustc_const_eval/src/const_eval/mod.rs | 41 +++++++++---- .../src/const_eval/valtrees.rs | 28 ++++++--- .../rustc_middle/src/mir/interpret/queries.rs | 2 +- .../rustc_middle/src/mir/interpret/value.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 12 ++-- compiler/rustc_middle/src/ty/mod.rs | 9 ++- compiler/rustc_middle/src/ty/print/mod.rs | 1 + compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_mir_build/src/build/mod.rs | 58 +------------------ .../src/thir/pattern/const_to_pat.rs | 2 +- src/test/incremental/issue-54242.rs | 2 +- src/test/ui/consts/const-size_of-cycle.stderr | 4 +- src/test/ui/consts/issue-44415.rs | 2 +- src/test/ui/consts/issue-44415.stderr | 4 +- 16 files changed, 80 insertions(+), 93 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5716ee2fc1499..eafddf8008042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,7 +358,6 @@ dependencies = [ "libgit2-sys", "log", "memchr", - "num_cpus", "opener", "openssl", "os_info", diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 3bd092263c13a..3eeb0138b37f7 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -140,6 +140,7 @@ impl<'tcx> ConstEvalErr<'tcx> { /// /// If `lint_root.is_some()` report it as a lint, else report it as a hard error. /// (Except that for some errors, we ignore all that -- see `must_error` below.) + #[instrument(skip(self, tcx, decorate, lint_root), level = "debug")] fn struct_generic( &self, tcx: TyCtxtAt<'tcx>, @@ -190,6 +191,7 @@ impl<'tcx> ConstEvalErr<'tcx> { decorate(err); }; + debug!("self.error: {:?}", self.error); // Special handling for certain errors match &self.error { // Don't emit a new diagnostic for these errors diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 51edf64de802a..793f02a8adefd 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -24,12 +24,6 @@ pub use fn_queries::*; 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, ValTreeCreationError>; - pub(crate) fn const_caller_location( tcx: TyCtxt<'_>, (file, line, col): (Symbol, u32, u32), @@ -44,6 +38,16 @@ 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 = 100000; + +pub(crate) enum ValTreeCreationError { + NodesOverflow, + NonSupportedType, + Other, +} +pub(crate) type ValTreeCreationResult<'tcx> = Result, ValTreeCreationError>; + /// Evaluates a constant and turns it into a type-level constant value. pub(crate) fn eval_to_valtree<'tcx>( tcx: TyCtxt<'tcx>, @@ -62,11 +66,28 @@ pub(crate) fn eval_to_valtree<'tcx>( let place = ecx.raw_const_to_mplace(const_alloc).unwrap(); debug!(?place); - let valtree_result = const_to_valtree_inner(&ecx, &place); + let mut num_nodes = 0; + let valtree_result = const_to_valtree_inner(&ecx, &place, &mut num_nodes); match valtree_result { Ok(valtree) => Ok(Some(valtree)), - Err(_) => Ok(None), + 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), + } + } } } @@ -75,7 +96,7 @@ pub(crate) fn eval_to_valtree<'tcx>( pub(crate) fn try_destructure_const<'tcx>( tcx: TyCtxt<'tcx>, const_: ty::Const<'tcx>, -) -> Option> { +) -> Option> { if let ty::ConstKind::Value(valtree) = const_.val() { let branches = match valtree { ty::ValTree::Branch(b) => b, @@ -141,7 +162,7 @@ pub(crate) fn try_destructure_const<'tcx>( let fields = tcx.arena.alloc_from_iter(fields.into_iter()); - Some(mir::DestructuredConst { variant, fields }) + Some(ty::DestructuredConst { variant, fields }) } else { None } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 080133275a606..4137e351344bc 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,6 +1,6 @@ use super::eval_queries::{mk_eval_cx, op_to_const}; use super::machine::CompileTimeEvalContext; -use super::{ValTreeCreationError, ValTreeCreationResult}; +use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES}; use crate::interpret::{ intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta, MemoryKind, PlaceTy, Scalar, ScalarMaybeUninit, @@ -16,6 +16,7 @@ fn branches<'tcx>( place: &MPlaceTy<'tcx>, n: usize, variant: Option, + num_nodes: &mut usize, ) -> ValTreeCreationResult<'tcx> { let place = match variant { Some(variant) => ecx.mplace_downcast(&place, variant).unwrap(), @@ -27,7 +28,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)?; + let valtree = const_to_valtree_inner(ecx, &field, num_nodes)?; fields.push(Some(valtree)); } @@ -39,6 +40,11 @@ fn branches<'tcx>( .collect::>>() .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))) } @@ -46,6 +52,7 @@ 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) @@ -54,7 +61,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)?; + let valtree = const_to_valtree_inner(ecx, &place_elem, num_nodes)?; elems.push(valtree); } @@ -65,12 +72,18 @@ 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> { let ty = place.layout.ty; debug!("ty kind: {:?}", ty.kind()); + if *num_nodes >= VALTREE_MAX_NODES { + return Err(ValTreeCreationError::NodesOverflow); + } + match ty.kind() { ty::FnDef(..) => { + *num_nodes += 1; Ok(ty::ValTree::zst()) } ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { @@ -78,6 +91,7 @@ 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())) } @@ -94,11 +108,11 @@ pub(crate) fn const_to_valtree_inner<'tcx>( }; debug!(?derefd_place); - const_to_valtree_inner(ecx, &derefd_place) + const_to_valtree_inner(ecx, &derefd_place, num_nodes) } ty::Str | ty::Slice(_) | ty::Array(_, _) => { - slice_branches(ecx, place) + slice_branches(ecx, place, num_nodes) } // 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 @@ -107,7 +121,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) + branches(ecx, place, elem_tys.len(), None, num_nodes) } ty::Adt(def, _) => { @@ -120,7 +134,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)) + branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes) } ty::Never diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 69353232f0659..9284d240037f0 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -194,7 +194,7 @@ impl<'tcx> TyCtxtAt<'tcx> { 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, const_: ty::Const<'tcx>) -> mir::DestructuredConst<'tcx> { + pub fn destructure_const(self, const_: ty::Const<'tcx>) -> ty::DestructuredConst<'tcx> { self.try_destructure_const(const_).unwrap() } diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index f566467b7ce09..146ae45e46898 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -78,7 +78,6 @@ impl<'tcx> ConstValue<'tcx> { Some(self.try_to_scalar()?.assert_int()) } - #[inline(always)] pub fn try_to_bits(&self, size: Size) -> Option { self.try_to_scalar_int()?.to_bits(size).ok() } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 22b1ad4190489..caa1d4cd34eee 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -967,26 +967,26 @@ rustc_queries! { query eval_to_valtree( key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>> ) -> EvalToValTreeResult<'tcx> { - desc { "evaluate type-level constant" } + desc { "evaluating type-level constant" } } /// Converts a type level constant value into `ConstValue` query valtree_to_const_val(key: (Ty<'tcx>, ty::ValTree<'tcx>)) -> ConstValue<'tcx> { - desc { "convert type-level constant value to mir constant value"} + desc { "converting type-level constant value to mir constant value"} } /// Destructure a constant ADT or array into its variant index and its /// 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::Const<'tcx>) -> Option> { - desc { "destructure type level constant"} + query try_destructure_const(key: ty::Const<'tcx>) -> Option> { + desc { "destructuring type level constant"} } /// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index /// and its field values. query try_destructure_mir_constant(key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>) -> Option> { - desc { "destructure mir constant"} + desc { "destructuring mir constant"} remap_env_constness } @@ -995,7 +995,7 @@ rustc_queries! { query deref_mir_constant( key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>> ) -> mir::ConstantKind<'tcx> { - desc { "deref constant" } + desc { "dereferencing mir constant" } remap_env_constness } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8da447d16fbfd..a53583d8673f7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -42,8 +42,8 @@ use rustc_query_system::ich::StableHashingContext; use rustc_session::cstore::CrateStoreDyn; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; -use rustc_target::abi::Align; pub use subst::*; +use rustc_target::abi::{Align, VariantIdx}; pub use vtable::*; use std::fmt::Debug; @@ -2453,3 +2453,10 @@ pub struct FoundRelationships { /// _>::AssocType = ?T` pub output: bool, } + +/// The constituent parts of a type level constant of kind ADT or array. +#[derive(Copy, Clone, Debug, HashStable)] +pub struct DestructuredConst<'tcx> { + pub variant: Option, + pub fields: &'tcx [ty::Const<'tcx>], +} diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 7a096bbc4d96f..7ae23d371e59f 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -98,6 +98,7 @@ pub trait Printer<'tcx>: Sized { // Defaults (should not be overridden): + #[instrument(skip(self), level = "debug")] fn default_print_def_path( self, def_id: DefId, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3b11f7572a640..3028a57e11c7c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1460,9 +1460,7 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } // Aggregates, printed as array/tuple/struct/variant construction syntax. - (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) - if !ty.has_param_types_or_consts() => - { + (ty::ValTree::Branch(_), ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) => { let Some(contents) = self.tcx().try_destructure_const( ty::Const::from_value(self.tcx(), valtree, ty) ) else { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 51f7aa642c84f..0376b53ecc5fc 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,9 +1,9 @@ use crate::build; +pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant; use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; 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_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -14,9 +14,7 @@ use rustc_index::vec::{Idx, IndexVec}; 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, ConstValue, LitToConstError, LitToConstInput, Scalar, -}; +use rustc_middle::mir::interpret::ConstValue; use rustc_middle::mir::*; use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir}; use rustc_middle::ty::subst::Subst; @@ -24,7 +22,6 @@ 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; use super::lints; @@ -1096,57 +1093,6 @@ fn parse_float_into_constval<'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, 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 diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index b423c64544747..845be2ab264a6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -503,7 +503,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // deref pattern. _ => { if !pointee_ty.is_sized(tcx.at(span), param_env) { - // `tcx.deref_mirconstant()` below will ICE with an unsized type + // `tcx.deref_mir_constant()` 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 { diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs index d32df9544997e..806c84152598f 100644 --- a/src/test/incremental/issue-54242.rs +++ b/src/test/incremental/issue-54242.rs @@ -14,7 +14,7 @@ impl Tr for str { type Arr = [u8; 8]; #[cfg(cfail)] type Arr = [u8; Self::C]; - //[cfail]~^ ERROR cycle detected when evaluate type-level constant + //[cfail]~^ ERROR cycle detected when evaluating type-level constant } fn main() {} diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 0772b1712c5e2..46f02ce8a4533 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when evaluate type-level constant +error[E0391]: cycle detected when evaluating type-level constant --> $DIR/const-size_of-cycle.rs:4:17 | LL | bytes: [u8; std::mem::size_of::()] @@ -17,7 +17,7 @@ LL | bytes: [u8; std::mem::size_of::()] = note: ...which requires computing layout of `Foo`... = note: ...which requires computing layout of `[u8; _]`... = note: ...which requires normalizing `[u8; _]`... - = note: ...which again requires evaluate type-level constant, completing the cycle + = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/const-size_of-cycle.rs:3:1 | diff --git a/src/test/ui/consts/issue-44415.rs b/src/test/ui/consts/issue-44415.rs index 79f415e6a2c10..d93b451be453a 100644 --- a/src/test/ui/consts/issue-44415.rs +++ b/src/test/ui/consts/issue-44415.rs @@ -4,7 +4,7 @@ use std::intrinsics; struct Foo { bytes: [u8; unsafe { intrinsics::size_of::() }], - //~^ ERROR cycle detected when evaluate type-level constant + //~^ ERROR cycle detected when evaluating type-level constant x: usize, } diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr index 6641300fc9a87..c085beb0ea525 100644 --- a/src/test/ui/consts/issue-44415.stderr +++ b/src/test/ui/consts/issue-44415.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when evaluate type-level constant +error[E0391]: cycle detected when evaluating type-level constant --> $DIR/issue-44415.rs:6:17 | LL | bytes: [u8; unsafe { intrinsics::size_of::() }], @@ -17,7 +17,7 @@ LL | bytes: [u8; unsafe { intrinsics::size_of::() }], = note: ...which requires computing layout of `Foo`... = note: ...which requires computing layout of `[u8; _]`... = note: ...which requires normalizing `[u8; _]`... - = note: ...which again requires evaluate type-level constant, completing the cycle + = note: ...which again requires evaluating type-level constant, completing the cycle note: cycle used when checking that `Foo` is well-formed --> $DIR/issue-44415.rs:5:1 | From 17323e05ce3dbb38a9c7e50ee76d89b885423dfb Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 3 Jun 2022 12:47:16 +0200 Subject: [PATCH 04/11] manually bless 32-bit mir-opt tests --- ...allocation2.main.ConstProp.after.32bit.mir | 30 +++++++++---------- ...line_into_box_place.main.Inline.32bit.diff | 12 ++++---- ...egion_subtyping_basic.main.nll.0.32bit.mir | 4 +-- ...2_.AddMovesForPackedDrops.before.32bit.mir | 4 +-- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index 8b5ad40c9f92c..432aac9ccdfbb 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -21,41 +21,41 @@ fn main() -> () { } alloc1 (static: FOO, size: 8, align: 4) { - ╾─alloc28─╼ 03 00 00 00 │ ╾──╼.... + ╾─alloc22─╼ 03 00 00 00 │ ╾──╼.... } -alloc28 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc18─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc26─╼ 03 00 00 00 │ ....*...╾──╼.... +alloc22 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc14─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc20─╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc13 (size: 0, align: 4) {} +alloc9 (size: 0, align: 4) {} -alloc18 (size: 8, align: 4) { - ╾─alloc16─╼ ╾─alloc17─╼ │ ╾──╼╾──╼ +alloc14 (size: 8, align: 4) { + ╾─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: 12, align: 4) { - ╾─a22+0x3─╼ ╾─alloc23─╼ ╾─a25+0x2─╼ │ ╾──╼╾──╼╾──╼ +alloc20 (size: 12, align: 4) { + ╾─a17+0x3─╼ ╾─alloc18─╼ ╾─a19+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 } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index c19cbe3e5b0df..806e7b269e249 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -23,10 +23,10 @@ StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 _2 = SizeOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 _3 = AlignOf(std::vec::Vec); // 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()) } + // + 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:: { ptr: Unique:: { pointer: NonNull:: { pointer: {0x4 as *const u32} }, _marker: PhantomData:: }, 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::::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, val: Value(ByRef(..)) } ++ // + literal: Const { ty: alloc::raw_vec::RawVec, val: Unevaluated(alloc::raw_vec::RawVec::::NEW, [u32], None) } + Deinit((*_7)); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ((*_7).0: alloc::raw_vec::RawVec) = 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 @@ -71,10 +71,10 @@ - } - - bb5 (cleanup): { -- _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- _6 = : unsafe fn(Unique::>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}(move (_5.0: std::ptr::Unique>), 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>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } +- // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(ValTree::Branch(..)) } } } diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index c357210978a60..7d9e012bb296e 100644 --- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -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(0x00000003)) }]; // in scope 0 at $DIR/region-subtyping-basic.rs:17:9: 17:14 + let mut _1: [usize; Const { ty: usize, kind: Value(Leaf(0x00000003)) }]; // 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: { diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir index 5dc81b787a9fa..3aa95cd3f105f 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir @@ -31,9 +31,9 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { bb6: { _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - _3 = 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::) { 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) { as Drop>::drop}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r mut Vec) { as Drop>::drop}, val: Value(ValTree::Branch(..)) } } } From 0a6815a924448b6e4b93adb8645d6903cbbc47eb Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 3 Jun 2022 13:41:53 +0200 Subject: [PATCH 05/11] bless 32-bit ui tests --- .../consts/const-mut-refs/issue-76510.32bit.stderr | 12 +++++++++--- src/test/ui/consts/invalid-union.32bit.stderr | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr index 61b00be345fee..0f420ae1b6b7c 100644 --- a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr +++ b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr @@ -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>((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`. diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr index 884ae71197bcc..38c38d1ae6732 100644 --- a/src/test/ui/consts/invalid-union.32bit.stderr +++ b/src/test/ui/consts/invalid-union.32bit.stderr @@ -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: 4, align: 4) { - ╾─alloc8──╼ │ ╾──╼ + ╾─alloc7──╼ │ ╾──╼ } error: erroneous constant used From 773d8b2e15024b2687b2d29972921a3b17816a13 Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 3 Jun 2022 20:42:35 +0200 Subject: [PATCH 06/11] address review --- Cargo.lock | 1 + .../rustc_middle/src/mir/interpret/queries.rs | 20 ------ .../rustc_middle/src/mir/interpret/value.rs | 4 ++ compiler/rustc_middle/src/mir/mod.rs | 13 +--- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_mir_build/src/build/mod.rs | 59 ++++++++++++++- compiler/rustc_mir_build/src/thir/constant.rs | 72 +------------------ compiler/rustc_symbol_mangling/src/v0.rs | 5 +- src/librustdoc/clean/utils.rs | 19 ++--- .../box_expr.main.ElaborateDrops.before.mir | 4 +- .../const_prop/boxes.main.ConstProp.diff | 6 +- .../derefer_inline_test.main.Derefer.diff | 8 +-- ...line_into_box_place.main.Inline.64bit.diff | 8 +-- ...issue_62289.test.ElaborateDrops.before.mir | 4 +- ...place.Test.SimplifyCfg-make_shim.after.mir | 4 +- ...ove_out.move_out_by_subslice.mir_map.0.mir | 8 +-- ...y_move_out.move_out_from_end.mir_map.0.mir | 8 +-- ...2_.AddMovesForPackedDrops.before.64bit.mir | 4 +- .../ui/consts/issue-77062-large-zst-array.rs | 2 +- .../ui/issues/issue-68010-large-zst-consts.rs | 2 +- .../clippy/clippy_lints/src/enum_clike.rs | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 20 ++---- 22 files changed, 116 insertions(+), 161 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eafddf8008042..5716ee2fc1499 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,6 +358,7 @@ dependencies = [ "libgit2-sys", "log", "memchr", + "num_cpus", "opener", "openssl", "os_info", diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 9284d240037f0..5f32f0d5e89fe 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -11,9 +11,6 @@ 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 @@ -26,23 +23,6 @@ impl<'tcx> TyCtxt<'tcx> { let param_env = self.param_env(def_id).with_reveal_all_normalized(self); 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 `::C`, in which case the given diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 146ae45e46898..e80918d5e5d03 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -111,6 +111,10 @@ impl<'tcx> ConstValue<'tcx> { pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self { ConstValue::Scalar(Scalar::from_machine_usize(i, cx)) } + + pub fn zst() -> Self { + Self::Scalar(Scalar::ZST) + } } /// A `Scalar` represents an immediate, primitive value existing outside of a diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 512615ccbab85..b3cf8cdde0ea6 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2405,7 +2405,7 @@ impl<'tcx> Operand<'tcx> { Operand::Constant(Box::new(Constant { span, user_ty: None, - literal: ConstantKind::Ty(ty::Const::zero_sized(tcx, ty)), + literal: ConstantKind::Val(ConstValue::zst(), ty), })) } @@ -2981,16 +2981,6 @@ impl<'tcx> ConstantKind<'tcx> { } } - pub fn try_val(&self, tcx: TyCtxt<'tcx>) -> Option> { - match self { - ConstantKind::Ty(c) => match c.kind() { - ty::ConstKind::Value(v) => Some(tcx.valtree_to_const_val((c.ty(), v))), - _ => None, - }, - ConstantKind::Val(v, _) => Some(*v), - } - } - #[inline] pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option> { match self { @@ -3548,6 +3538,7 @@ fn comma_sep<'tcx>(fmt: &mut Formatter<'_>, elems: Vec>) -> f Ok(()) } +// FIXME: Move that into `mir/pretty.rs`. fn pretty_print_const_value<'tcx>( ct: ConstValue<'tcx>, ty: Ty<'tcx>, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3028a57e11c7c..129d2051c19e7 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1530,7 +1530,9 @@ pub trait PrettyPrinter<'tcx>: } // fallback - if valtree != ty::ValTree::zst() { + if valtree == ty::ValTree::zst() { + p!(write("")); + } else { p!(write("{:?}", valtree)); } if print_ty { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 0376b53ecc5fc..8d14a37676d2c 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -2,9 +2,9 @@ use crate::build; pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant; use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; -use crate::thir::constant::parse_float_into_scalar; use crate::thir::pattern::pat_from_hir; use rustc_data_structures::fx::FxHashMap; +use rustc_apfloat::ieee::{Double, Single}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -15,6 +15,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::middle::region; use rustc_middle::mir::interpret::ConstValue; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::*; use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir}; use rustc_middle::ty::subst::Subst; @@ -1093,6 +1094,62 @@ fn parse_float_into_constval<'tcx>( parse_float_into_scalar(num, float_ty, neg).map(ConstValue::Scalar) } +pub(crate) fn parse_float_into_scalar( + num: Symbol, + float_ty: ty::FloatTy, + neg: bool, +) -> Option { + let num = num.as_str(); + match float_ty { + ty::FloatTy::F32 => { + let Ok(rust_f) = num.parse::() else { return None }; + let mut f = num.parse::().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 `{}`: \ + {}({:#x}) vs Rust's {}({:#x})", + rust_f, + f, + f.to_bits(), + Single::from_bits(rust_f.to_bits().into()), + rust_f.to_bits() + ); + + if neg { + f = -f; + } + + Some(Scalar::from_f32(f)) + } + ty::FloatTy::F64 => { + let Ok(rust_f) = num.parse::() else { return None }; + let mut f = num.parse::().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 `{}`: \ + {}({:#x}) vs Rust's {}({:#x})", + rust_f, + f, + f.to_bits(), + Double::from_bits(rust_f.to_bits().into()), + rust_f.to_bits() + ); + + if neg { + f = -f; + } + + Some(Scalar::from_f64(f)) + } + } +} + /////////////////////////////////////////////////////////////////////////// // Builder methods are broken up into modules, depending on what kind // of thing is being lowered. Note that they use the `unpack` macro diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index cfb09ecedd635..a7e4403a242e1 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -1,9 +1,6 @@ -use rustc_apfloat::ieee::{Double, Single}; -use rustc_apfloat::Float; use rustc_ast as ast; -use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput, Scalar}; +use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt}; -use rustc_span::symbol::Symbol; pub(crate) fn lit_to_const<'tcx>( tcx: TyCtxt<'tcx>, @@ -45,9 +42,6 @@ pub(crate) fn lit_to_const<'tcx>( 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_into_valtree(*n, *fty, neg).ok_or(LitToConstError::Reported)? - } (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), @@ -56,67 +50,3 @@ pub(crate) fn lit_to_const<'tcx>( Ok(ty::Const::from_value(tcx, valtree, ty)) } - -pub(crate) fn parse_float_into_scalar( - num: Symbol, - float_ty: ty::FloatTy, - neg: bool, -) -> Option { - let num = num.as_str(); - match float_ty { - ty::FloatTy::F32 => { - let Ok(rust_f) = num.parse::() else { return None }; - let mut f = num.parse::().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 `{}`: \ - {}({:#x}) vs Rust's {}({:#x})", - rust_f, - f, - f.to_bits(), - Single::from_bits(rust_f.to_bits().into()), - rust_f.to_bits() - ); - - if neg { - f = -f; - } - - Some(Scalar::from_f32(f)) - } - ty::FloatTy::F64 => { - let Ok(rust_f) = num.parse::() else { return None }; - let mut f = num.parse::().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 `{}`: \ - {}({:#x}) vs Rust's {}({:#x})", - rust_f, - f, - f.to_bits(), - Double::from_bits(rust_f.to_bits().into()), - rust_f.to_bits() - ); - - if neg { - f = -f; - } - - Some(Scalar::from_f64(f)) - } - } -} - -fn parse_float_into_valtree<'tcx>( - num: Symbol, - float_ty: ty::FloatTy, - neg: bool, -) -> Option> { - parse_float_into_scalar(num, float_ty, neg).map(|s| ty::ValTree::Leaf(s.try_to_int().unwrap())) -} diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index ff07063679746..3cd521833302f 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -626,9 +626,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { let _ = write!(self.out, "{:x}_", bits); } - // HACK(eddyb) because `ty::Const` only supports sized values (for now), - // we can't use dereference the const + supporting `str`, we have to specially - // handle `&str` and include both `&` ("R") and `str` ("e") prefixes. + // FIXME(valtrees): Remove the special case for `str` + // here and fully support unsized constants. ty::Ref(_, inner_ty, mutbl) => { self.push(match mutbl { hir::Mutability::Not => "R", diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 7125a7578bd81..41ab0e9377df6 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -15,6 +15,8 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::mir; +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}; @@ -263,13 +265,13 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { } pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - tcx.const_eval_poly_for_typeck(def_id).ok().and_then(|val| { + tcx.const_eval_poly(def_id).ok().and_then(|val| { let ty = tcx.type_of(def_id); match (val, ty.kind()) { (_, &ty::Ref(..)) => None, - (Some(ty::ValTree::Branch(_)), &ty::Adt(_, _)) => None, - (Some(ty::ValTree::Leaf(_)), _) => { - let const_ = ty::Const::from_value(tcx, val.unwrap(), ty); + (ConstValue::Scalar(_), &ty::Adt(_, _)) => None, + (ConstValue::Scalar(_), _) => { + let const_ = mir::ConstantKind::from_value(val, ty); Some(print_const_with_custom_print_scalar(tcx, const_)) } _ => None, @@ -303,19 +305,18 @@ fn format_integer_with_underscore_sep(num: &str) -> String { .collect() } -fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: ty::Const<'_>) -> String { +fn print_const_with_custom_print_scalar(tcx: TyCtxt<'_>, ct: mir::ConstantKind<'_>) -> String { // 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(ty::ValTree::Leaf(int)), ty::Uint(ui)) => { + match (ct, ct.ty().kind()) { + (mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Uint(ui)) => { format!("{}{}", format_integer_with_underscore_sep(&int.to_string()), ui.name_str()) } - (ty::ConstKind::Value(ty::ValTree::Leaf(int)), ty::Int(i)) => { + (mir::ConstantKind::Val(ConstValue::Scalar(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); let sign_extended_data = size.sign_extend(data) as i128; - format!( "{}{}", format_integer_with_underscore_sep(&sign_extended_data.to_string()), diff --git a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir index d23203742f07b..5b1ffc76fe5b3 100644 --- a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir @@ -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 = : 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 + _4 = 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff index 6a490e48b8ed3..342c987343eac 100644 --- a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff @@ -22,13 +22,13 @@ 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 = : 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 +- _6 = 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 = : 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 ++ _6 = 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/derefer_inline_test.main.Derefer.diff b/src/test/mir-opt/derefer_inline_test.main.Derefer.diff index 832a773777707..e131adae2b683 100644 --- a/src/test/mir-opt/derefer_inline_test.main.Derefer.diff +++ b/src/test/mir-opt/derefer_inline_test.main.Derefer.diff @@ -16,10 +16,10 @@ StorageLive(_1); // scope 0 at $DIR/derefer_inline_test.rs:10:5: 10:12 _2 = SizeOf(std::boxed::Box); // scope 1 at $DIR/derefer_inline_test.rs:10:5: 10:12 _3 = AlignOf(std::boxed::Box); // 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 + _4 = 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { @@ -56,10 +56,10 @@ } bb7 (cleanup): { - _6 = : unsafe fn(Unique::>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb6; // scope 0 at $DIR/derefer_inline_test.rs:10:11: 10:12 + _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), 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>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } } bb8 (cleanup): { diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 806e7b269e249..5b2b9f7e3a9ff 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -23,10 +23,10 @@ StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 _2 = SizeOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 _3 = AlignOf(std::vec::Vec); // 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 + _4 = 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { @@ -71,10 +71,10 @@ - } - - bb5 (cleanup): { -- _6 = : unsafe fn(Unique::>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), 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>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(ValTree::Branch(..)) } +- // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } } } diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index 0a18710b2cc6f..4d06b91e6dc61 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -31,10 +31,10 @@ fn test() -> Option> { 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 = : 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 + _4 = 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir index 8ae79b6604462..09cf06cacd920 100644 --- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir @@ -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 = : for<'r> fn(&'r mut Test) {::drop}(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + _3 = ::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) {::drop}, val: Value(ValTree::Branch(..)) } + // + literal: Const { ty: for<'r> fn(&'r mut Test) {::drop}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir index 3b241264aacfa..d7d2cdf9b0c75 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_by_subslice.mir_map.0.mir @@ -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 = : 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 + _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 // 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } 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 = : 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 + _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 // 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb3: { diff --git a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir index c59e92dc82927..18bc1a17c1b50 100644 --- a/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir +++ b/src/test/mir-opt/uniform_array_move_out.move_out_from_end.mir_map.0.mir @@ -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 = : 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 + _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 // 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } 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 = : 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 + _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 // 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb3: { diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir index 3aa95cd3f105f..5dc81b787a9fa 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir @@ -31,9 +31,9 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { bb6: { _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - _3 = : for<'r> fn(&'r mut Vec::) { as Drop>::drop}(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + _3 = 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) { as Drop>::drop}, val: Value(ValTree::Branch(..)) } + // + literal: Const { ty: for<'r> fn(&'r mut Vec) { as Drop>::drop}, val: Value(Scalar()) } } } diff --git a/src/test/ui/consts/issue-77062-large-zst-array.rs b/src/test/ui/consts/issue-77062-large-zst-array.rs index 7a00fe964ab08..0566b802e75b6 100644 --- a/src/test/ui/consts/issue-77062-large-zst-array.rs +++ b/src/test/ui/consts/issue-77062-large-zst-array.rs @@ -1,4 +1,4 @@ -// check-pass +// build-pass fn main() { let _ = &[(); usize::MAX]; diff --git a/src/test/ui/issues/issue-68010-large-zst-consts.rs b/src/test/ui/issues/issue-68010-large-zst-consts.rs index 32f51d513d122..3277df69c0285 100644 --- a/src/test/ui/issues/issue-68010-large-zst-consts.rs +++ b/src/test/ui/issues/issue-68010-large-zst-consts.rs @@ -1,4 +1,4 @@ -// check-pass +// build-pass fn main() { println!("{}", [(); usize::MAX].len()); diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index b326d864d4bff..da67888827d19 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { .tcx .const_eval_poly(def_id.to_def_id()) .ok() - .and_then(|val| Some(rustc_middle::mir::ConstantKind::from_value(val, ty))); + .map(|val| rustc_middle::mir::ConstantKind::from_value(val, 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() { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index ec323806fbf93..6709ac13a432f 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { None, ) .ok() - .and_then(|val| Some(rustc_middle::mir::ConstantKind::from_value(val, ty)))?; + .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?; let result = miri_to_const(self.lcx.tcx, result); if result.is_some() { self.needed_resolution = true; @@ -581,16 +581,6 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -fn try_const_to_constant<'tcx>(tcx: TyCtxt<'tcx>, c: ty::Const<'tcx>) -> Option { - match c.kind() { - ty::ConstKind::Value(valtree) => { - let const_val = tcx.valtree_to_const_val((c.ty(), valtree)); - miri_to_const(tcx, mir::ConstantKind::from_value(const_val, c.ty())) - }, - _ => None, - } -} - pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option { use rustc_middle::mir::interpret::ConstValue; match result { @@ -629,8 +619,8 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - }, mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { ty::Array(sub_type, len) => match sub_type.kind() { - ty::Float(FloatTy::F32) => match try_const_to_constant(tcx, *len) { - Some(Constant::Int(len)) => alloc + ty::Float(FloatTy::F32) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) { + Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize)) .to_owned() @@ -644,8 +634,8 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match try_const_to_constant(tcx, *len) { - Some(Constant::Int(len)) => alloc + ty::Float(FloatTy::F64) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) { + Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize)) .to_owned() From 90c4b947aafb087091c5b30f40f133abbd5aa31a Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 3 Jun 2022 21:41:01 +0200 Subject: [PATCH 07/11] fix wrong evaluation in clippy --- .../inline/inline_into_box_place.main.Inline.32bit.diff | 8 ++++---- ...place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir | 4 ++-- src/tools/clippy/clippy_utils/src/consts.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index 806e7b269e249..5b2b9f7e3a9ff 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -23,10 +23,10 @@ StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11 _2 = SizeOf(std::vec::Vec); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43 _3 = AlignOf(std::vec::Vec); // 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 + _4 = 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(ValTree::Branch(..)) } + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar()) } } bb1: { @@ -71,10 +71,10 @@ - } - - bb5 (cleanup): { -- _6 = : unsafe fn(Unique::>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 +- _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), 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>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(ValTree::Branch(..)) } +- // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } } } diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir index 3aa95cd3f105f..5dc81b787a9fa 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir @@ -31,9 +31,9 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { bb6: { _2 = &mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL - _3 = : for<'r> fn(&'r mut Vec::) { as Drop>::drop}(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + _3 = 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) { as Drop>::drop}, val: Value(ValTree::Branch(..)) } + // + literal: Const { ty: for<'r> fn(&'r mut Vec) { as Drop>::drop}, val: Value(Scalar()) } } } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 6709ac13a432f..5d0ce6cc620ac 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -619,7 +619,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - }, mir::ConstantKind::Val(ConstValue::ByRef { alloc, offset: _ }, _) => match result.ty().kind() { ty::Array(sub_type, len) => match sub_type.kind() { - ty::Float(FloatTy::F32) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) { + ty::Float(FloatTy::F32) => match len.to_valtree().try_to_machine_usize(tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize)) @@ -634,7 +634,7 @@ pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) - .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) { + ty::Float(FloatTy::F64) => match len.to_valtree().try_to_machine_usize(tcx) { Some(len) => alloc .inner() .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize)) From 8093db6e2b51bd9036ea2f76ad4342da0ca03bea Mon Sep 17 00:00:00 2001 From: b-naber Date: Sat, 4 Jun 2022 11:24:29 +0200 Subject: [PATCH 08/11] correctly create Scalar for meta info --- compiler/rustc_const_eval/src/const_eval/valtrees.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 4137e351344bc..4849a07e3b4f4 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -240,7 +240,7 @@ fn create_pointee_place<'tcx>( let place = MPlaceTy::from_aligned_ptr_with_meta( ptr.into(), layout, - MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)), + MemPlaceMeta::Meta(Scalar::from_machine_usize(num_elems as u64, &tcx)), ); debug!(?place); @@ -370,7 +370,8 @@ fn valtree_into_mplace<'tcx>( let imm = match inner_ty.kind() { ty::Slice(_) | ty::Str => { let len = valtree.unwrap_branch().len(); - let len_scalar = ScalarMaybeUninit::Scalar(Scalar::from_u64(len as u64)); + let len_scalar = + ScalarMaybeUninit::Scalar(Scalar::from_machine_usize(len as u64, &tcx)); Immediate::ScalarPair( ScalarMaybeUninit::from_maybe_pointer((*pointee_place).ptr, &tcx), @@ -441,7 +442,10 @@ fn valtree_into_mplace<'tcx>( place .offset( offset, - MemPlaceMeta::Meta(Scalar::from_u64(num_elems as u64)), + MemPlaceMeta::Meta(Scalar::from_machine_usize( + num_elems as u64, + &tcx, + )), inner_layout, &tcx, ) From 060acc97db878964b6229dc89a657201f4232b14 Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 7 Jun 2022 19:29:13 +0200 Subject: [PATCH 09/11] rebase --- .../src/debuginfo/type_names.rs | 3 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 3 +- .../defaults-cyclic-fail.stderr | 6 +- ...9-assoc-const-static-recursion-impl.stderr | 4 +- ...onst-static-recursion-trait-default.stderr | 4 +- ...-assoc-const-static-recursion-trait.stderr | 4 +- .../const-eval/ub-wide-ptr.32bit.stderr | 65 ++++++++++++++----- .../const-eval/ub-wide-ptr.64bit.stderr | 65 ++++++++++++++----- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 6 ++ 10 files changed, 118 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index f849770283285..4ac3d2eaa0cd1 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -703,7 +703,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S // but we get a deterministic, virtually unique value for the constant. let hcx = &mut tcx.create_stable_hashing_context(); let mut hasher = StableHasher::new(); - hcx.while_hashing_spans(false, |hcx| ct.kind().hash_stable(hcx, &mut hasher)); + let ct = ct.eval(tcx, ty::ParamEnv::reveal_all()); + hcx.while_hashing_spans(false, |hcx| ct.to_valtree().hash_stable(hcx, &mut hasher)); // Let's only emit 64 bits of the hash value. That should be plenty for // avoiding collisions and will make the emitted type names shorter. let hash: u64 = hasher.finish(); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index a53583d8673f7..b386ed68dd246 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -42,8 +42,8 @@ use rustc_query_system::ich::StableHashingContext; use rustc_session::cstore::CrateStoreDyn; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; -pub use subst::*; use rustc_target::abi::{Align, VariantIdx}; +pub use subst::*; pub use vtable::*; use std::fmt::Debug; diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 8d14a37676d2c..94c71bbf56da6 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -3,8 +3,9 @@ pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant; use crate::build::expr::as_place::PlaceBuilder; use crate::build::scope::DropKind; use crate::thir::pattern::pat_from_hir; -use rustc_data_structures::fx::FxHashMap; use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::Float; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr index 550897790e9ff..c4cd9c2a49fd7 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -11,10 +11,10 @@ LL | const B: u8 = Self::A; | ^^^^^^^^^^^^^^^^^^^^^^ = 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 + --> $DIR/defaults-cyclic-fail.rs:16:16 | -LL | fn main() { - | ^^^^^^^^^ +LL | assert_eq!(<() as Tr>::A, 0); + | ^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index 8c85fadf60014..b4dc730d8631f 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -1,8 +1,8 @@ error[E0391]: cycle detected when elaborating drops for `::BAR` - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:22 | LL | const BAR: u32 = IMPL_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index 251a69aeabaa2..97ede6ad388f2 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -1,8 +1,8 @@ error[E0391]: cycle detected when elaborating drops for `FooDefault::BAR` - --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:22 | LL | const BAR: u32 = DEFAULT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 45e911d002912..bd97c31229ecc 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -1,8 +1,8 @@ error[E0391]: cycle detected when elaborating drops for `::BAR` - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:22 | LL | const BAR: u32 = TRAIT_REF_BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr index a5e3d078bd09d..a78cff11589fd 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr @@ -149,8 +149,19 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; ╾─allocN─╼ │ ╾──╼ } +error: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:87:40 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | 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 + error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:93:1 + --> $DIR/ub-wide-ptr.rs:95:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered 0x03, but expected a boolean @@ -160,8 +171,19 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 ╾allocN─╼ │ ╾──╼ } +error: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:95:42 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | 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 + error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:96:1 + --> $DIR/ub-wide-ptr.rs:100:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..1[0]: encountered 0x03, but expected a boolean @@ -171,8 +193,19 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran ╾allocN─╼ │ ╾──╼ } +error: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:100:42 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | 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 + error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:103:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { LL | | @@ -187,7 +220,7 @@ LL | | }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:111:1 + --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable @@ -198,7 +231,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:114:1 + --> $DIR/ub-wide-ptr.rs:120:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable @@ -209,7 +242,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:123:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer @@ -220,7 +253,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:119:1 + --> $DIR/ub-wide-ptr.rs:125:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer @@ -231,7 +264,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92 } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:121:1 + --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) @@ -242,7 +275,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92 } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:123:1 + --> $DIR/ub-wide-ptr.rs:129:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) @@ -253,7 +286,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:125:1 + --> $DIR/ub-wide-ptr.rs:131:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function) @@ -264,7 +297,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:129:1 + --> $DIR/ub-wide-ptr.rs:135:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..: encountered 0x03, but expected a boolean @@ -275,7 +308,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:133:1 + --> $DIR/ub-wide-ptr.rs:139:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer @@ -286,7 +319,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:135:1 + --> $DIR/ub-wide-ptr.rs:141:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable @@ -297,17 +330,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm } error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:141:5 + --> $DIR/ub-wide-ptr.rs:147:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:145:5 + --> $DIR/ub-wide-ptr.rs:151:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 12 bytes starting at offset N is out-of-bounds -error: aborting due to 29 previous errors +error: aborting due to 32 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr index a3ba62ca87b58..69a61d9caede6 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr @@ -149,8 +149,19 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; ╾───────allocN───────╼ │ ╾──────╼ } +error: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:87:40 + | +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | 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 + error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:93:1 + --> $DIR/ub-wide-ptr.rs:95:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..0: encountered 0x03, but expected a boolean @@ -160,8 +171,19 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 ╾──────allocN───────╼ │ ╾──────╼ } +error: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:95:42 + | +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | 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 + error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:96:1 + --> $DIR/ub-wide-ptr.rs:100:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..1[0]: encountered 0x03, but expected a boolean @@ -171,8 +193,19 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran ╾──────allocN───────╼ │ ╾──────╼ } +error: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:100:42 + | +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | 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 + error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:103:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { LL | | @@ -187,7 +220,7 @@ LL | | }; } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:111:1 + --> $DIR/ub-wide-ptr.rs:117:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable @@ -198,7 +231,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:114:1 + --> $DIR/ub-wide-ptr.rs:120:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable @@ -209,7 +242,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:123:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer @@ -220,7 +253,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:119:1 + --> $DIR/ub-wide-ptr.rs:125:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer @@ -231,7 +264,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92 } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:121:1 + --> $DIR/ub-wide-ptr.rs:127:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) @@ -242,7 +275,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92 } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:123:1 + --> $DIR/ub-wide-ptr.rs:129:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) @@ -253,7 +286,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:125:1 + --> $DIR/ub-wide-ptr.rs:131:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function) @@ -264,7 +297,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:129:1 + --> $DIR/ub-wide-ptr.rs:135:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at ..: encountered 0x03, but expected a boolean @@ -275,7 +308,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:133:1 + --> $DIR/ub-wide-ptr.rs:139:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer @@ -286,7 +319,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute } error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:135:1 + --> $DIR/ub-wide-ptr.rs:141:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable @@ -297,17 +330,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm } error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:141:5 + --> $DIR/ub-wide-ptr.rs:147:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:145:5 + --> $DIR/ub-wide-ptr.rs:151:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 24 bytes starting at offset N is out-of-bounds -error: aborting due to 29 previous errors +error: aborting due to 32 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 763e6ba296788..f2e5738f88c9f 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -86,15 +86,21 @@ const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; // bad data *inside* the slice const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; //~^ ERROR it is undefined behavior to use this value +//~| ERROR any use of this value will cause an error +//~| WARNING this was previously accepted // good MySliceBool const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]); // bad: sized field is not okay const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); //~^ ERROR it is undefined behavior to use this value +//~| ERROR any use of this value will cause an error +//~| WARNING this was previously accepted // bad: unsized part is not okay const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); //~^ ERROR it is undefined behavior to use this value +//~| ERROR any use of this value will cause an error +//~| WARNING this was previously accepted // # raw slice const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok From e14b34c386ad2809e937e0e6e0379c5cc5474954 Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 14 Jun 2022 10:50:20 +0200 Subject: [PATCH 10/11] account for endianness in debuginfo for const args --- compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 9 ++++++--- src/test/debuginfo/function-names.rs | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 4ac3d2eaa0cd1..8755d91818d22 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -707,12 +707,15 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S hcx.while_hashing_spans(false, |hcx| ct.to_valtree().hash_stable(hcx, &mut hasher)); // Let's only emit 64 bits of the hash value. That should be plenty for // avoiding collisions and will make the emitted type names shorter. - let hash: u64 = hasher.finish(); + // Note: Don't use `StableHashResult` impl of `u64` here directly, since that + // would lead to endianness problems. + let hash: u128 = hasher.finish(); + let hash_short = (hash.to_le() as u64).to_le(); if cpp_like_debuginfo(tcx) { - write!(output, "CONST${:x}", hash) + write!(output, "CONST${:x}", hash_short) } else { - write!(output, "{{CONST#{:x}}}", hash) + write!(output, "{{CONST#{:x}}}", hash_short) } } }, diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs index 73e34d4bb3211..60fb06d409c49 100644 --- a/src/test/debuginfo/function-names.rs +++ b/src/test/debuginfo/function-names.rs @@ -37,7 +37,7 @@ // Const generic parameter // gdb-command:info functions -q function_names::const_generic_fn.* // gdb-check:[...]static fn function_names::const_generic_fn_bool(); -// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#3fcd7c34c1555be6}>(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#6348c650c7b26618}>(); // gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>(); // gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>(); @@ -76,7 +76,7 @@ // Const generic parameter // cdb-command:x a!function_names::const_generic_fn* // cdb-check:[...] a!function_names::const_generic_fn_bool (void) -// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) +// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) // cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) // cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) From 15c1c0652298e9dd3dee45813a2718623f6e3702 Mon Sep 17 00:00:00 2001 From: b-naber Date: Tue, 14 Jun 2022 17:34:37 +0200 Subject: [PATCH 11/11] rebase --- .../rustc_const_eval/src/const_eval/mod.rs | 4 +- .../rustc_const_eval/src/interpret/operand.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 18 ++---- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 4 +- compiler/rustc_middle/src/ty/context.rs | 64 ++++++------------- compiler/rustc_middle/src/ty/print/pretty.rs | 14 +--- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../src/traits/fulfill.rs | 2 +- .../src/traits/select/mod.rs | 6 +- 10 files changed, 36 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 793f02a8adefd..a1d2e5cf3ef12 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -97,7 +97,7 @@ pub(crate) fn try_destructure_const<'tcx>( tcx: TyCtxt<'tcx>, const_: ty::Const<'tcx>, ) -> Option> { - if let ty::ConstKind::Value(valtree) = const_.val() { + if let ty::ConstKind::Value(valtree) = const_.kind() { let branches = match valtree { ty::ValTree::Branch(b) => b, _ => return None, @@ -216,7 +216,7 @@ 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_mir_constant cannot be used with mutable allocations as \ that could allow pattern matching to observe mutable statics", diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index e9a9c0e171376..6b05a49575fd9 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -638,7 +638,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c) } ty::ConstKind::Value(valtree) => { - let ty = val.ty(); + let ty = c.ty(); let const_val = self.tcx.valtree_to_const_val((ty, valtree)); self.const_val_to_op(const_val, ty, layout) } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index b3cf8cdde0ea6..c173d453041ba 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1446,11 +1446,7 @@ impl<'tcx> BasicBlockData<'tcx> { } 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 } } } @@ -2471,11 +2467,7 @@ impl<'tcx> Operand<'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 } } } @@ -2995,7 +2987,7 @@ impl<'tcx> ConstantKind<'tcx> { #[inline] pub fn try_to_scalar(self) -> Option { match self { - ConstantKind::Ty(c) => match c.val() { + ConstantKind::Ty(c) => match c.kind() { ty::ConstKind::Value(valtree) => match valtree { ty::ValTree::Leaf(scalar_int) => Some(Scalar::Int(scalar_int)), ty::ValTree::Branch(_) => None, @@ -3291,7 +3283,7 @@ impl<'tcx> ConstantKind<'tcx> { } pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { - match c.val() { + match c.kind() { ty::ConstKind::Value(valtree) => { let const_val = tcx.valtree_to_const_val((c.ty(), valtree)); Self::Val(const_val, c.ty()) @@ -3587,7 +3579,7 @@ fn pretty_print_const_value<'tcx>( } } (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(); + let n = n.kind().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(); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index a81a60df2be8a..462c0ada3cf87 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -484,7 +484,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { // This reflects what `Const` looked liked before `val` was renamed // as `kind`. We print it like this to avoid having to update // expected output in a lot of tests. - self.push(&format!("+ literal: Const {{ ty: {}, val: {} }}", literal.ty(), kind)); + self.push(&format!("+ literal: Const {{ ty: {}, val: {} }}", literal.ty(), val)); } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index fe5c5be15f5a3..bc52259b151d1 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -201,7 +201,7 @@ impl<'tcx> Const<'tcx> { /// Panics if self.kind != ty::ConstKind::Value pub fn to_valtree(self) -> ty::ValTree<'tcx> { - match self.val() { + match self.kind() { ty::ConstKind::Value(valtree) => valtree, _ => bug!("expected ConstKind::Value"), } @@ -286,7 +286,7 @@ impl<'tcx> Const<'tcx> { /// 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) { + if let Some(val) = self.kind().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())), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0930f3edf7254..4cd25a616264f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1186,7 +1186,11 @@ impl<'tcx> TyCtxt<'tcx> { }; 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) @@ -1659,7 +1663,7 @@ macro_rules! nop_lift { impl<'a, 'tcx> Lift<'tcx> for $ty { type Lifted = $lifted; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - 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) }) @@ -2244,11 +2248,7 @@ impl<'tcx> TyCtxt<'tcx> { /// `*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,11 +2268,7 @@ impl<'tcx> TyCtxt<'tcx> { 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> { @@ -2417,11 +2413,7 @@ impl<'tcx> TyCtxt<'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] @@ -2572,9 +2564,11 @@ impl<'tcx> TyCtxt<'tcx> { eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>], ) -> &'tcx List>> { 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) } @@ -2607,49 +2601,29 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List> { - 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 { - 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> { - 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 { - 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( diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 129d2051c19e7..58dab0f96aba5 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -607,11 +607,7 @@ pub trait PrettyPrinter<'tcx>: } } } 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]"), @@ -1335,11 +1331,7 @@ pub trait PrettyPrinter<'tcx>: 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() => { @@ -2294,7 +2286,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { type BreakTy = (); fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - 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 { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 3cd521833302f..87b844ca759a5 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -669,7 +669,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { .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.tcx.mk_const(ty::ConstS { kind: ct.kind(), ty: pointee_ty }); self = dereferenced_const.print(self)?; } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 7c4b5decee4f4..70d8fdae65140 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -407,7 +407,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { 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(..) => { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a002006f0e676..ee2c8da5a005d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2578,11 +2578,7 @@ impl<'o, 'tcx> TraitObligationStackList<'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 } } }