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/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index f849770283285..8755d91818d22 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -703,15 +703,19 @@ 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(); + // 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/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/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/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..a1d2e5cf3ef12 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, @@ -40,7 +39,7 @@ pub(crate) fn const_caller_location( } // We forbid type-level constants that contain more than `VALTREE_MAX_NODES` nodes. -const VALTREE_MAX_NODES: usize = 1000; +const VALTREE_MAX_NODES: usize = 100000; pub(crate) enum ValTreeCreationError { NodesOverflow, @@ -56,6 +55,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 @@ -90,40 +91,81 @@ pub(crate) fn eval_to_valtree<'tcx>( } } -/// 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_.kind() { + 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(ty::DestructuredConst { variant, fields }) + } else { + None + } } #[instrument(skip(tcx), level = "debug")] @@ -143,8 +185,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 +205,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>, @@ -213,14 +218,14 @@ pub(crate) fn deref_mir_constant<'tcx>( assert_eq!( 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..4849a07e3b4f4 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -5,13 +5,11 @@ 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>, @@ -76,13 +74,13 @@ pub(crate) fn const_to_valtree_inner<'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); } - let ty = place.layout.ty; - debug!("ty kind: {:?}", ty.kind()); - match ty.kind() { ty::FnDef(..) => { *num_nodes += 1; @@ -234,19 +232,15 @@ 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( 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); @@ -262,7 +256,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 +266,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 +330,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>, @@ -377,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), @@ -448,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, ) diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 597ca4cfcdd06..6b05a49575fd9 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 = 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_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..5f32f0d5e89fe 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,7 @@ 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. + #[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 @@ -22,7 +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) } - /// Resolves and evaluates a constant. /// /// The constant can be located on a trait like `::C`, in which case the given @@ -59,6 +59,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 +95,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 +114,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 +174,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>) -> ty::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..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 1511b51fa2548..c173d453041ba 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}; @@ -2399,7 +2401,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), })) } @@ -2953,22 +2955,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 +2965,7 @@ impl<'tcx> ConstantKind<'tcx> { } } + #[inline(always)] pub fn ty(&self) -> Ty<'tcx> { match self { ConstantKind::Ty(c) => c.ty(), @@ -2983,32 +2973,34 @@ impl<'tcx> ConstantKind<'tcx> { } } - pub fn try_val(&self) -> Option> { + #[inline] + pub fn try_to_value(self, tcx: TyCtxt<'tcx>) -> Option> { match self { ConstantKind::Ty(c) => match c.kind() { - ty::ConstKind::Value(v) => Some(v), + ty::ConstKind::Value(valtree) => Some(tcx.valtree_to_const_val((c.ty(), valtree))), _ => None, }, - ConstantKind::Val(v, _) => Some(*v), - } - } - - #[inline] - pub fn try_to_value(self) -> Option> { - match self { - ConstantKind::Ty(c) => c.kind().try_to_value(), 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.kind() { + 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 +3017,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 +3071,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 +3092,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 +3109,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 +3202,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 +3229,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 +3259,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 +3275,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.kind() { + 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 +3506,183 @@ 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(()) +} + +// FIXME: Move that into `mir/pretty.rs`. 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.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(); + 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..462c0ada3cf87 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(_) @@ -479,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)); } } @@ -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..caa1d4cd34eee 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -967,36 +967,26 @@ rustc_queries! { query eval_to_valtree( key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>> ) -> EvalToValTreeResult<'tcx> { - desc { "evaluate type-level constant" } - remap_env_constness + 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::ParamEnvAnd<'tcx, 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"} - 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" } + desc { "destructuring mir constant"} remap_env_constness } @@ -1005,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/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..bc52259b151d1 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,21 @@ 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) + /// Panics if self.kind != ty::ConstKind::Value + pub fn to_valtree(self) -> ty::ValTree<'tcx> { + match self.kind() { + 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) } #[inline] @@ -212,13 +219,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 +271,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.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())), + } + } 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..4cd25a616264f 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, }), } 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..b386ed68dd246 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -42,7 +42,7 @@ 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; +use rustc_target::abi::{Align, VariantIdx}; pub use subst::*; pub use vtable::*; @@ -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(..) @@ -2447,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 5ad93d778208d..7ae23d371e59f 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -302,6 +302,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..58dab0f96aba5 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, @@ -1224,7 +1224,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 +1262,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); @@ -1408,85 +1408,62 @@ 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(..)) => { 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 +1490,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 +1511,22 @@ 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("")); + } else { + p!(write("{:?}", valtree)); + } if print_ty { p!(": ", print(ty)); } @@ -2296,7 +2273,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,7 +2285,6 @@ 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); if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { @@ -2326,7 +2301,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 +2327,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..94c71bbf56da6 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,9 +1,10 @@ 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; use crate::thir::pattern::pat_from_hir; -use rustc_ast as ast; +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; @@ -14,15 +15,15 @@ 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::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; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults}; use rustc_span::symbol::sym; use rustc_span::Span; -use rustc_target::abi::Size; +use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use super::lints; @@ -266,57 +267,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 +1087,70 @@ 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) +} + +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 d82e6688633d0..a7e4403a242e1 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -1,13 +1,7 @@ -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_span::symbol::Symbol; -use rustc_target::abi::Size; +use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; +use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt}; -// 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,94 +14,39 @@ 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 })? - } - (ast::LitKind::Float(n, _), ty::Float(fty)) => { - parse_float(*n, *fty, neg).ok_or(LitToConstError::Reported)? + 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::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)) -} - -// FIXME move this to rustc_mir_build::build -pub(crate) fn parse_float<'tcx>( - num: Symbol, - fty: ty::FloatTy, - neg: bool, -) -> Option> { - let num = num.as_str(); - use rustc_apfloat::ieee::{Double, Single}; - let scalar = match fty { - 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; - } - 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; - } - Scalar::from_f64(f) - } - }; - Some(ConstValue::Scalar(scalar)) + Ok(ty::Const::from_value(tcx, valtree, ty)) } 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..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 @@ -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_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/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 83175439b70fb..f5d957e30ff09 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_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); 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..87b844ca759a5 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 { @@ -625,46 +626,57 @@ 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 `deref_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); + // 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", + 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 { kind: ct.kind(), 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 +688,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 +735,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..70d8fdae65140 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -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..ee2c8da5a005d 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) } 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..41ab0e9377df6 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -15,6 +15,7 @@ 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}; @@ -270,7 +271,7 @@ pub(crate) fn print_evaluated_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option None, (ConstValue::Scalar(_), &ty::Adt(_, _)) => None, (ConstValue::Scalar(_), _) => { - let const_ = ty::Const::from_value(tcx, val, ty); + let const_ = mir::ConstantKind::from_value(val, ty); Some(print_const_with_custom_print_scalar(tcx, const_)) } _ => None, @@ -304,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(ConstValue::Scalar(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(ConstValue::Scalar(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/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) diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs index 9e449de0cf5ac..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 simplifying constant + //[cfail]~^ ERROR cycle detected when evaluating type-level constant } fn main() {} 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/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/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..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 @@ -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 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..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 @@ -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 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/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/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..c4cd9c2a49fd7 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -1,42 +1,20 @@ -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 + --> $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 3d696bb049cd9..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,16 +1,10 @@ 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 normalizing `IMPL_REF_BAR`... -note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 + | ^^^^^^^^^^^^ | -LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `IMPL_REF_BAR`... +note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; @@ -20,17 +14,6 @@ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... | LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires normalizing `::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..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,16 +1,10 @@ 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 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..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,16 +1,10 @@ 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 normalizing `TRAIT_REF_BAR`... -note: ...which requires simplifying constant for the type system `TRAIT_REF_BAR`... - --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | ^^^^^^^^^^^^^ | -LL | const TRAIT_REF_BAR: u32 = ::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-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 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.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/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..46f02ce8a4533 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 evaluating 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 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/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.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 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..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 simplifying constant for the type system + //~^ 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 9e3db5ce9a402..c085beb0ea525 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 evaluating 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 evaluating 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/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-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..da67888827d19 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -50,8 +50,8 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { .tcx .const_eval_poly(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) { + .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() { 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..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(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(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 8db41ba6ee296..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; 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; @@ -136,19 +137,18 @@ fn is_value_unfrozen_raw<'tcx>( 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(cx.param_env.and(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,7 +174,7 @@ 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| inner(cx, mir::ConstantKind::from_value(val, ty)), ) } diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 159c5d53d0292..5d0ce6cc620ac 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -7,6 +7,7 @@ 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}; @@ -429,8 +430,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { None, ) .ok() - .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?; - let result = miri_to_const(result); + .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; } @@ -580,10 +581,10 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } -pub fn miri_to_const(result: ty::Const<'_>) -> Option { +pub fn miri_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::ConstantKind<'tcx>) -> Option { use rustc_middle::mir::interpret::ConstValue; - match result.kind() { - ty::ConstKind::Value(ConstValue::Scalar(Scalar::Int(int))) => { + 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()))), @@ -603,7 +604,7 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option { _ => None, } }, - ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty().kind() { + 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() @@ -616,10 +617,10 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option { }, _ => None, }, - ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty().kind() { + 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 miri_to_const(*len) { - Some(Constant::Int(len)) => alloc + 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)) .to_owned() @@ -633,8 +634,8 @@ pub fn miri_to_const(result: ty::Const<'_>) -> Option { .map(Constant::Vec), _ => None, }, - ty::Float(FloatTy::F64) => match miri_to_const(*len) { - Some(Constant::Int(len)) => alloc + 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)) .to_owned()