diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 9a6c45ae98d5f..8b19cbf74a054 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -64,6 +64,12 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool { err ); } + ErrorHandled::Silent => { + span_bug!( + constant.span, + "codegen encountered silent error", + ); + } } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 1ef863e84af7f..dbb5069d57d54 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -189,7 +189,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // errored or at least linted ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {} ErrorHandled::TooGeneric => { - span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err) + span_bug!(const_.span, "codegen encountered polymorphic constant: {:?}", err) + } + ErrorHandled::Silent => { + span_bug!(const_.span, "silent error during codegen") } } } 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 c5412affafe23..7a201c53b1e98 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -13,7 +13,7 @@ use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::pretty::display_allocation; use rustc_middle::traits::Reveal; -use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::layout::{LayoutError, LayoutOf}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, subst::Subst, TyCtxt}; use rustc_span::source_map::Span; @@ -28,6 +28,7 @@ pub fn note_on_undefined_behavior_error() -> &'static str { } // Returns a pointer to where the result lives +#[instrument(skip(ecx, body), level = "debug")] fn eval_body_using_ecx<'mir, 'tcx>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, cid: GlobalId<'tcx>, @@ -160,6 +161,7 @@ pub(super) fn op_to_const<'tcx>( ConstValue::Scalar(Scalar::ZST) } }; + match immediate { Ok(ref mplace) => to_const_value(mplace), // see comment on `let try_as_immediate` above @@ -212,77 +214,65 @@ fn turn_into_const_value<'tcx>( op_to_const(&ecx, &mplace.into()) } +#[instrument(skip(tcx), level = "debug")] pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { assert!(key.param_env.constness() == hir::Constness::Const); - // see comment in eval_to_allocation_raw_provider for what we're doing here - if key.param_env.reveal() == Reveal::All { - let mut key = key; - key.param_env = key.param_env.with_user_facing(); - match tcx.eval_to_const_value_raw(key) { - // try again with reveal all as requested - Err(ErrorHandled::TooGeneric) => {} - // deduplicate calls - other => return other, - } - } + let (param_env, id) = key.into_parts(); + let reveal = param_env.reveal(); // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { - let ty = key.value.instance.ty(tcx, key.param_env); + let ty = key.value.instance.ty(tcx, param_env); let substs = match ty.kind() { ty::FnDef(_, substs) => substs, _ => bug!("intrinsic with type {:?}", ty), }; - return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs).map_err(|error| { - let span = tcx.def_span(def_id); - let error = ConstEvalErr { error: error.into_kind(), stacktrace: vec![], span }; - error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic") - }); + + match eval_nullary_intrinsic(tcx, param_env, def_id, substs) { + Ok(val) => { + // store result for deduplication + tcx.save_const_value_for_dedup(id, reveal); + + return Ok(val); + } + Err(e) => { + let span = tcx.def_span(def_id); + let error = ConstEvalErr { error: e.into_kind(), stacktrace: vec![], span }; + + return Err( + error.report_as_error(tcx.at(span), "could not evaluate nullary intrinsic") + ); + } + } } - tcx.eval_to_allocation_raw(key).map(|val| turn_into_const_value(tcx, val, key)) + tcx.dedup_eval_alloc_raw(key, None).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>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { assert!(key.param_env.constness() == hir::Constness::Const); - // Because the constant is computed twice (once per value of `Reveal`), we are at risk of - // reporting the same error twice here. To resolve this, we check whether we can evaluate the - // constant in the more restrictive `Reveal::UserFacing`, which most likely already was - // computed. For a large percentage of constants that will already have succeeded. Only - // associated constants of generic functions will fail due to not enough monomorphization - // information being available. - - // In case we fail in the `UserFacing` variant, we just do the real computation. - if key.param_env.reveal() == Reveal::All { - let mut key = key; - key.param_env = key.param_env.with_user_facing(); - match tcx.eval_to_allocation_raw(key) { - // try again with reveal all as requested - Err(ErrorHandled::TooGeneric) => {} - // deduplicate calls - other => return other, - } - } + let (param_env, cid) = key.into_parts(); + let reveal = param_env.reveal(); + let def = cid.instance.def.with_opt_param(); + if cfg!(debug_assertions) { // Make sure we format the instance even if we do not print it. // This serves as a regression test against an ICE on printing. // The next two lines concatenated contain some discussion: // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/ // subject/anon_const_instance_printing/near/135980032 - let instance = with_no_trimmed_paths(|| key.value.instance.to_string()); + let instance = with_no_trimmed_paths(|| cid.instance.to_string()); trace!("const eval: {:?} ({})", key, instance); } - let cid = key.value; - let def = cid.instance.def.with_opt_param(); - if let Some(def) = def.as_local() { if tcx.has_typeck_results(def.did) { if let Some(error_reported) = tcx.typeck_opt_const_arg(def).tainted_by_errors { @@ -316,6 +306,20 @@ pub fn eval_to_allocation_raw_provider<'tcx>( let res = ecx.load_mir(cid.instance.def, cid.promoted); match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { Err(error) => { + debug!("error from eval_body_using_ecx: {:?}", error); + if reveal == Reveal::Selection { + match error.kind() { + err_inval!(Layout(LayoutError::Unknown(_))) + | err_inval!(TooGeneric) + | err_inval!(AlreadyReported(_)) => { + // We do want to report these errors + } + _ => { + return Err(ErrorHandled::Silent); + } + } + } + let err = ConstEvalErr::new(&ecx, error, None); // Some CTFE errors raise just a lint, not a hard error; see // . @@ -328,7 +332,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>( // use of broken constant from other crate: always an error true }; - if is_hard_err { let msg = if is_static { Cow::from("could not evaluate static initializer") @@ -345,7 +348,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>( Cow::from("evaluation of constant value failed") } }; - Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), &msg)) } else { let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did); @@ -377,10 +379,26 @@ pub fn eval_to_allocation_raw_provider<'tcx>( } }; let alloc_id = mplace.ptr.provenance.unwrap(); + if let Err(error) = validation { // Validation failed, report an error. This is always a hard error. let err = ConstEvalErr::new(&ecx, error, None); - Err(err.struct_error( + + // FIXME Do we also want to keep these silent with Reveal::Selection? + if reveal == Reveal::Selection { + match err.error { + err_inval!(Layout(LayoutError::Unknown(_))) + | err_inval!(TooGeneric) + | err_inval!(AlreadyReported(_)) => { + // We do want to report these errors + } + _ => { + return Err(ErrorHandled::Silent); + } + } + } + + let error = Err(err.struct_error( ecx.tcx, "it is undefined behavior to use this value", |mut diag| { @@ -394,10 +412,19 @@ pub fn eval_to_allocation_raw_provider<'tcx>( )); diag.emit(); }, - )) + )); + + debug!(?error); + + error } else { // Convert to raw constant - Ok(ConstAlloc { alloc_id, ty: mplace.layout.ty }) + let const_alloc = ConstAlloc { alloc_id, ty: mplace.layout.ty }; + + // store information that allows deduplication + tcx.save_alloc_for_dedup(cid, reveal); + + Ok(const_alloc) } } } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 246807a112a40..fb7b026c6fb73 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -18,7 +18,8 @@ use rustc_middle::ty::{ use rustc_mir_dataflow::storage::AlwaysLiveLocals; use rustc_query_system::ich::StableHashingContext; use rustc_session::Limit; -use rustc_span::{Pos, Span}; +use rustc_span::Pos; +use rustc_span::Span; use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout}; use super::{ @@ -809,7 +810,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// cause us to continue unwinding. pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx> { info!( - "popping stack frame ({})", + "popping following stack frame ({})", if unwinding { "during unwinding" } else { "returning from function" } ); @@ -926,6 +927,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + #[instrument(skip(self), level = "debug")] pub fn eval_to_allocation( &self, gid: GlobalId<'tcx>, @@ -941,8 +943,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.param_env }; let param_env = param_env.with_const(); - let val = self.tcx.eval_to_allocation_raw(param_env.and(gid))?; - self.raw_const_to_mplace(val) + let val = self.tcx.dedup_eval_alloc_raw(param_env.and(gid), None); + debug!(?val); + + self.raw_const_to_mplace(val?) } #[must_use] diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e9a857d09124f..714e7ba8ca9df 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -18,6 +18,9 @@ pub enum ErrorHandled { Reported(ErrorReported), /// Already emitted a lint for this evaluation. Linted, + /// Encountered an error without emitting anything. Only returned + /// with `Reveal::Selection`. + Silent, /// Don't emit an error, the evaluation failed because the MIR was generic /// and the substs didn't fully monomorphize it. TooGeneric, @@ -88,7 +91,7 @@ fn print_backtrace(backtrace: &Backtrace) { impl From for InterpErrorInfo<'_> { fn from(err: ErrorHandled) -> Self { match err { - ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => { + ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted | ErrorHandled::Silent => { err_inval!(ReferencedConstant) } ErrorHandled::TooGeneric => err_inval!(TooGeneric), diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index b762a10da847a..086224b6ff806 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -95,8 +95,10 @@ mod pointer; mod queries; mod value; +use std::cell::RefCell; use std::convert::TryFrom; use std::fmt; +use std::fmt::Debug; use std::io; use std::io::{Read, Write}; use std::num::{NonZeroU32, NonZeroU64}; @@ -107,9 +109,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{HashMapExt, Lock}; use rustc_data_structures::tiny_list::TinyList; use rustc_hir::def_id::DefId; -use rustc_macros::HashStable; +use rustc_middle::traits::Reveal; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_serialize::{Decodable, Encodable}; +use rustc_span::Span; use rustc_target::abi::Endian; use crate::mir; @@ -446,6 +449,37 @@ impl<'tcx> AllocMap<'tcx> { } } +/// Used to store results of calls to `eval_to_allocation_raw` and +/// `eval_to_const_value_raw`. +#[derive(Debug)] +pub struct ConstDedupMap<'tcx> { + // interning for deduplication of `eval_to_allocation_raw` + pub alloc_map: RefCell, Reveal>>, + + // interning for deduplication of `eval_to_const_value_raw` + pub const_val_map: RefCell, Reveal>>, +} + +impl<'tcx> ConstDedupMap<'tcx> { + pub fn new() -> Self { + ConstDedupMap { alloc_map: Default::default(), const_val_map: Default::default() } + } + + #[instrument(skip(self), level = "debug")] + fn insert_alloc(&self, id: GlobalId<'tcx>, val: Reveal) { + let mut alloc_map = self.alloc_map.borrow_mut(); + alloc_map.insert(id, val); + debug!("alloc_map after update: {:#?}", alloc_map); + } + + #[instrument(skip(self), level = "debug")] + fn insert_const_val(&self, id: GlobalId<'tcx>, val: Reveal) { + let mut const_val_map = self.const_val_map.borrow_mut(); + const_val_map.insert(id, val); + debug!("const_val_map after update: {:#?}", const_val_map); + } +} + impl<'tcx> TyCtxt<'tcx> { /// Obtains a new allocation ID that can be referenced but does not /// yet have an allocation backing it. @@ -554,6 +588,169 @@ impl<'tcx> TyCtxt<'tcx> { fn set_alloc_id_same_memory(self, id: AllocId, mem: &'tcx Allocation) { self.alloc_map.lock().alloc_map.insert_same(id, GlobalAlloc::Memory(mem)); } + + /// Store the result of a call to `eval_to_allocation_raw` in order to + /// allow deduplication. + #[instrument(skip(self), level = "debug")] + pub fn save_alloc_for_dedup(self, id: GlobalId<'tcx>, val: Reveal) { + let dedup_const_map = self.dedup_const_map.lock(); + dedup_const_map.insert_alloc(id, val); + debug!("dedup_const_map after insert: {:#?}", dedup_const_map); + } + + /// Store the result of a call to `eval_to_const_value_raw` in order to deduplicate it. + #[instrument(skip(self), level = "debug")] + pub fn save_const_value_for_dedup(self, id: GlobalId<'tcx>, val: Reveal) { + let dedup_const_map = self.dedup_const_map.lock(); + dedup_const_map.insert_const_val(id, val); + debug!("dedup_const_map after insert: {:#?}", dedup_const_map); + } + + /// Tries to deduplicate a call to `eval_to_allocation_raw`. If deduplication isn't + /// successful `eval_to_allocation_raw` query is executed. + #[instrument(skip(self, opt_span), level = "debug")] + pub fn dedup_eval_alloc_raw( + self, + key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + opt_span: Option, + ) -> EvalToAllocationRawResult<'tcx> { + self.dedup_eval( + key, + opt_span, + EvalCtxt::Alloc, + |key| self.eval_to_allocation_raw(key), + |key, span| self.at(span).eval_to_allocation_raw(key), + ) + } + + /// Tries to deduplicate a call to `eval_to_const_value_raw`. If deduplication isn't + /// successful, `eval_to_const_value_raw` query is executed. + #[instrument(skip(self), level = "debug")] + pub fn dedup_eval_const_value_raw( + self, + key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + opt_span: Option, + ) -> EvalToConstValueResult<'tcx> { + self.dedup_eval( + key, + opt_span, + EvalCtxt::ConstVal, + |key| self.eval_to_const_value_raw(key), + |key, span| self.at(span).eval_to_const_value_raw(key), + ) + } + + /// Deduplicates the result of a query call. + /// + /// Explanation for why we can deduplicate query calls in certain situations: + /// + /// If we have stored a successful query result with `Reveal::Selection` then we can + /// deduplicate that result on calls of the `dedup` version of the query with both + /// `Reveal::Selection` and `Reveal::UserFacing` (since `Selection` and `UserFacing` + /// only differ in that we keep certain errors silent with `Selection`, but successful + /// allocations are always equivalent). This is also the reason why we can deduplicate + /// from saved calls with `UserFacing`on calls with both `Selection` and `UserFacing`. + /// + /// If we try to deduplicate with `Reveal::All` we are able to deduplicate + /// from saved query results with both `Selection` and `UserFacing`, since `All` + /// will always succeed if either `UserFacing` or `Selection` have succeeded. + /// On the other hand if we have a saved result with `Reveal::All`, it's not + /// guaranteed that query calls with `Reveal::Selection` or `Reveal::UserFacing` + /// succeed, so we can't deduplicate from those. + fn dedup_eval( + self, + key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + opt_span: Option, + eval_ctxt: EvalCtxt, + query_call: impl Fn(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> T, + query_call_span: impl Fn(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, Span) -> T, + ) -> T { + let (param_env, id) = key.into_parts(); + let dedup_const_map = self.dedup_const_map.lock(); + let dedup_query_map = match eval_ctxt { + EvalCtxt::Alloc => dedup_const_map.alloc_map.borrow(), + EvalCtxt::ConstVal => dedup_const_map.const_val_map.borrow(), + }; + + let dedup_reveal = dedup_query_map.get(&id); + debug!(?dedup_reveal); + + match param_env.reveal() { + Reveal::Selection => match dedup_reveal { + Some(Reveal::Selection) => { + drop(dedup_query_map); + drop(dedup_const_map); + + // Use cached result of query + return query_call(key); + } + Some(Reveal::UserFacing) => { + drop(dedup_query_map); + drop(dedup_const_map); + + let new_key = param_env.with_user_facing().and(id); + return query_call(new_key); + } + _ => {} + }, + Reveal::UserFacing => match dedup_reveal { + Some(Reveal::UserFacing) => { + drop(dedup_query_map); + drop(dedup_const_map); + + return query_call(key); + } + Some(Reveal::Selection) => { + drop(dedup_query_map); + drop(dedup_const_map); + + let new_key = param_env.with_reveal_selection().and(id); + return query_call(new_key); + } + _ => {} + }, + Reveal::All => match dedup_reveal { + Some(Reveal::Selection) => { + drop(dedup_query_map); + drop(dedup_const_map); + + let new_key = param_env.with_reveal_selection().and(id); + return query_call(new_key); + } + Some(Reveal::UserFacing) => { + drop(dedup_query_map); + drop(dedup_const_map); + + let new_key = param_env.with_user_facing().and(id); + return query_call(new_key); + } + Some(Reveal::All) => { + drop(dedup_query_map); + drop(dedup_const_map); + + return query_call(key); + } + _ => {} + }, + } + + // Important to drop the lock here + drop(dedup_query_map); + drop(dedup_const_map); + + debug!("unable to deduplicate"); + + // We weren't able to deduplicate + match opt_span { + Some(span) => query_call_span(key, span), + None => query_call(key), + } + } +} + +enum EvalCtxt { + Alloc, + ConstVal, } //////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index f983185563315..8edc34164c2c7 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -58,6 +58,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Evaluate a constant. + #[instrument(skip(self), level = "debug")] pub fn const_eval_global_id( self, param_env: ty::ParamEnv<'tcx>, @@ -68,11 +69,11 @@ impl<'tcx> TyCtxt<'tcx> { // 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)); - if let Some(span) = span { - self.at(span).eval_to_const_value_raw(inputs) - } else { - self.eval_to_const_value_raw(inputs) - } + + let raw_const = self.dedup_eval_const_value_raw(inputs, span); + debug!(?raw_const); + + raw_const } /// Evaluate a static's initializer, returning the allocation of the initializer's memory. @@ -88,6 +89,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Evaluate anything constant-like, returning the allocation of the final memory. + #[instrument(skip(self), level = "debug")] fn eval_to_allocation( self, gid: GlobalId<'tcx>, @@ -95,7 +97,9 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Result<&'tcx mir::Allocation, ErrorHandled> { let param_env = param_env.with_const(); trace!("eval_to_allocation: Need to compute {:?}", gid); - let raw_const = self.eval_to_allocation_raw(param_env.and(gid))?; - Ok(self.global_alloc(raw_const.alloc_id).unwrap_memory()) + let raw_const = self.dedup_eval_alloc_raw(param_env.and(gid), None); + debug!(?raw_const); + + Ok(self.global_alloc(raw_const?.alloc_id).unwrap_memory()) } } diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs index f80beadd6e551..978f16e9fcfb7 100644 --- a/compiler/rustc_middle/src/thir/abstract_const.rs +++ b/compiler/rustc_middle/src/thir/abstract_const.rs @@ -34,6 +34,7 @@ pub enum NotConstEvaluatable { Error(ErrorReported), MentionsInfer, MentionsParam, + Silent, } impl From for NotConstEvaluatable { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index de5beffb5c541..c5a883d876818 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -37,6 +37,12 @@ pub use self::chalk::{ChalkEnvironmentAndGoal, RustInterner as ChalkRustInterner /// more or less conservative. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)] pub enum Reveal { + // Similar to `Reveal::UserFacing`, except that we also do not emit errors + // when failing const evaluation. + // + // Used by `feature(const_evaluatable_checked)` to allow for `ConstEvaluatable` + // predicates to not hold without emitting an error. + Selection, /// At type-checking time, we refuse to project any associated /// type that is marked `default`. Non-`default` ("final") types /// are always projected. This is necessary in general for diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 5cde54c9328d1..2151534e233a3 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -426,6 +426,7 @@ impl<'tcx> AdtDef { "enum discriminant evaluation failed" } ErrorHandled::TooGeneric => "enum discriminant depends on generics", + ErrorHandled::Silent => return None, }; tcx.sess.delay_span_bug(tcx.def_span(expr_did), msg); None diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 27e22ccac02a7..278ebdc726c8e 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -257,6 +257,14 @@ impl<'tcx> Const<'tcx> { self.try_eval_usize(tcx, param_env) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } + + #[inline] + pub fn try_get_unevaluated(self) -> Option> { + match self.val { + ConstKind::Unevaluated(uv) => Some(uv), + _ => None, + } + } } pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 7188eed544551..cac85042ad5ef 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -3,6 +3,7 @@ use std::fmt; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; use crate::mir::Promoted; +use crate::traits::Reveal; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; use crate::ty::{self, TyCtxt, TypeFoldable}; @@ -160,10 +161,15 @@ impl<'tcx> ConstKind<'tcx> { // Note that we erase regions *before* calling `with_reveal_all_normalized`, // so that we don't try to invoke this query with // any region variables. - let param_env_and = tcx - .erase_regions(param_env) - .with_reveal_all_normalized(tcx) - .and(tcx.erase_regions(unevaluated)); + let param_env_and = match param_env.reveal() { + Reveal::Selection => { + tcx.erase_regions(param_env).and(tcx.erase_regions(unevaluated)) + } + _ => tcx + .erase_regions(param_env) + .with_reveal_all_normalized(tcx) + .and(tcx.erase_regions(unevaluated)), + }; // HACK(eddyb) when the query key would contain inference variables, // attempt using identity substs and `ParamEnv` instead, that will succeed @@ -191,7 +197,7 @@ impl<'tcx> ConstKind<'tcx> { // (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::TooGeneric | ErrorHandled::Linted | ErrorHandled::Silent) => None, Err(ErrorHandled::Reported(e)) => Some(Err(e)), } } else { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index caa7008f1085e..6086117b8111f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1043,6 +1043,10 @@ pub struct GlobalCtxt<'tcx> { /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock>, + /// Used to deduplicate calls to `eval_to_allocation_raw` and + /// `eval_to_const_value_raw`. + pub dedup_const_map: Lock>, + output_filenames: Arc, } @@ -1187,6 +1191,7 @@ impl<'tcx> TyCtxt<'tcx> { stability_interner: Default::default(), const_stability_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), + dedup_const_map: Lock::new(interpret::ConstDedupMap::new()), output_filenames: Arc::new(output_filenames), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 37d99766da9d2..a6558e2af2a48 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1237,23 +1237,28 @@ struct ParamTag { } unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { - const BITS: usize = 2; + const BITS: usize = 3; #[inline] fn into_usize(self) -> usize { match self { - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, - Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, - Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, + Self { reveal: traits::Reveal::Selection, constness: hir::Constness::NotConst } => 0, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 1, + Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 2, + Self { reveal: traits::Reveal::Selection, constness: hir::Constness::Const } => 3, + Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 4, + Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 5, } } + #[inline] unsafe fn from_usize(ptr: usize) -> Self { match ptr { - 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, - 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, - 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, - 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, + 0 => Self { reveal: traits::Reveal::Selection, constness: hir::Constness::NotConst }, + 1 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, + 2 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, + 3 => Self { reveal: traits::Reveal::Selection, constness: hir::Constness::Const }, + 4 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, + 5 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, _ => std::hint::unreachable_unchecked(), } } @@ -1343,6 +1348,11 @@ impl<'tcx> ParamEnv<'tcx> { ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal, constness }) } } + pub fn with_reveal_selection(mut self) -> Self { + self.packed.set_tag(ParamTag { reveal: Reveal::Selection, ..self.packed.tag() }); + self + } + pub fn with_user_facing(mut self) -> Self { self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); self @@ -1412,7 +1422,7 @@ impl<'tcx> ParamEnv<'tcx> { /// although the surrounding function is never reachable. pub fn and>(self, value: T) -> ParamEnvAnd<'tcx, T> { match self.reveal() { - Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, + Reveal::Selection | Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, Reveal::All => { if value.is_known_global() { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b1fa9041342a6..8dbc153283576 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -731,6 +731,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { "collection encountered polymorphic constant: {:?}", literal ), + Err(ErrorHandled::Silent) => span_bug!( + self.body.source_info(location).span, + "silent error emitted during collection", + ), } } _ => return, @@ -763,6 +767,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { "collection encountered polymorphic constant: {}", substituted_constant ), + Err(ErrorHandled::Silent) => span_bug!( + self.body.source_info(location).span, + "silent error emitted during collection", + ), } } _ => {} diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 0ea3a18ca34fa..6a1b210dbab4f 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -26,12 +26,18 @@ use std::cmp; use std::iter; use std::ops::ControlFlow; +pub enum UseRevealSelection { + Yes, + No, +} + /// Check if a given constant can be evaluated. pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, uv: ty::Unevaluated<'tcx, ()>, param_env: ty::ParamEnv<'tcx>, span: Span, + use_reveal_sel: UseRevealSelection, ) -> Result<(), NotConstEvaluatable> { debug!("is_const_evaluatable({:?})", uv); if infcx.tcx.features().generic_const_exprs { @@ -147,7 +153,12 @@ pub fn is_const_evaluatable<'cx, 'tcx>( // and hopefully soon change this to an error. // // See #74595 for more details about this. - let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span)); + let param_env_resolve = match use_reveal_sel { + UseRevealSelection::Yes => param_env.with_reveal_selection(), + UseRevealSelection::No => param_env, + }; + + let concrete = infcx.const_eval_resolve(param_env_resolve, uv.expand(), Some(span)); if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) { match infcx.tcx.def_kind(uv.def.did) { @@ -173,6 +184,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( Err(NotConstEvaluatable::Error(ErrorReported)) } Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)), + Err(ErrorHandled::Silent) => Err(NotConstEvaluatable::Silent), Ok(_) => Ok(()), } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index b5c5724f56edc..e808ef8c2cbe0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2,10 +2,10 @@ pub mod on_unimplemented; pub mod suggestions; use super::{ - EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, - Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective, - OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation, - SelectionContext, SelectionError, TraitNotObjectSafe, + const_evaluatable, EvaluationResult, FulfillmentError, FulfillmentErrorCode, + MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, + OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, + PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; @@ -86,6 +86,14 @@ pub trait InferCtxtExt<'tcx> { found_args: Vec, is_closure: bool, ) -> DiagnosticBuilder<'tcx>; + + fn report_const_eval_failure( + &self, + uv: ty::Unevaluated<'tcx, ()>, + obligation: PredicateObligation<'tcx>, + root_obligation: &PredicateObligation<'tcx>, + fallback_has_occurred: bool, + ); } impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { @@ -238,6 +246,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { error: &SelectionError<'tcx>, fallback_has_occurred: bool, ) { + debug!("report_selection_error(error: {:?})", error); let tcx = self.tcx; let mut span = obligation.cause.span; @@ -795,12 +804,48 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) } - SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsInfer) => { bug!( "MentionsInfer should have been handled in `traits/fulfill.rs` or `traits/select/mod.rs`" ) } + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Silent) => { + let pred = obligation.predicate.clone(); + + // Try to prove the obligation again without Reveal::Selection for + // better diagnostics + match pred.kind().skip_binder() { + ty::PredicateKind::ConstEvaluatable(uv) => { + self.report_const_eval_failure( + uv, + obligation.clone(), + root_obligation, + fallback_has_occurred, + ); + } + ty::PredicateKind::ConstEquate(c1, c2) => { + if let Some(uv1) = c1.try_get_unevaluated() { + self.report_const_eval_failure( + uv1.shrink(), + obligation.clone(), + root_obligation, + fallback_has_occurred, + ); + } + + if let Some(uv2) = c2.try_get_unevaluated() { + self.report_const_eval_failure( + uv2.shrink(), + obligation.clone(), + root_obligation, + fallback_has_occurred, + ); + } + } + _ => {} + } + tcx.sess.struct_span_err(span, "failed to evaluate the given constant") + } SelectionError::NotConstEvaluatable(NotConstEvaluatable::MentionsParam) => { if !self.tcx.features().generic_const_exprs { let mut err = self.tcx.sess.struct_span_err( @@ -1062,6 +1107,45 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err } + + #[instrument(skip(self, obligation, root_obligation, fallback_has_occurred), level = "debug")] + fn report_const_eval_failure( + &self, + uv: ty::Unevaluated<'tcx, ()>, + obligation: PredicateObligation<'tcx>, + root_obligation: &PredicateObligation<'tcx>, + fallback_has_occurred: bool, + ) { + let res = const_evaluatable::is_const_evaluatable( + self, + uv, + obligation.param_env.with_user_facing(), + obligation.cause.span, + const_evaluatable::UseRevealSelection::No, + ); + debug!(?res); + + match res { + Err(NotConstEvaluatable::Silent) => { + bug!("called with Reveal::UserFacing, but Silent error returned") + } + Err(e @ NotConstEvaluatable::MentionsParam | e @ NotConstEvaluatable::Error(_)) => { + let err = SelectionError::NotConstEvaluatable(e); + + self.report_selection_error( + obligation, + root_obligation, + &err, + fallback_has_occurred, + ); + } + Ok(()) => bug!( + "ConstEvaluatable predicate of {:?} failed with Reveal::Selection but succeeded with Reveal::UserFacing?", + uv + ), + _ => {} + } + } } trait InferCtxtPrivExt<'hir, 'tcx> { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 42e3f0db15e53..e841273479ffa 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -528,12 +528,15 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } ty::PredicateKind::ConstEvaluatable(uv) => { - match const_evaluatable::is_const_evaluatable( + let res = const_evaluatable::is_const_evaluatable( self.selcx.infcx(), uv, - obligation.param_env, + obligation.param_env.with_reveal_selection(), obligation.cause.span, - ) { + const_evaluatable::UseRevealSelection::Yes, + ); + + match res { Ok(()) => ProcessResult::Changed(vec![]), Err(NotConstEvaluatable::MentionsInfer) => { pending_obligation.stalled_on.clear(); @@ -546,7 +549,8 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { } Err( e @ NotConstEvaluatable::MentionsParam - | e @ NotConstEvaluatable::Error(_), + | e @ NotConstEvaluatable::Error(_) + | e @ NotConstEvaluatable::Silent, ) => ProcessResult::Error(CodeSelectionError( SelectionError::NotConstEvaluatable(e), )), @@ -625,6 +629,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { "ConstEquate: const_eval_resolve returned an unexpected error" ) } + (Err(ErrorHandled::Silent), _) | (_, Err(ErrorHandled::Silent)) => { + ProcessResult::Error(CodeSelectionError( + SelectionError::NotConstEvaluatable(NotConstEvaluatable::Silent), + )) + } (Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => { if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() { ProcessResult::Unchanged diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a8f26982d2e42..b7660dddc8ce0 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -273,6 +273,7 @@ fn do_normalize_predicates<'tcx>( // FIXME: this is gonna need to be removed ... /// Normalizes the parameter environment, reporting errors if they occur. +#[instrument(skip(tcx), level = "debug")] pub fn normalize_param_env_or_error<'tcx>( tcx: TyCtxt<'tcx>, region_context: DefId, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 23f615a96185d..dbd6cf1bd06d4 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -26,6 +26,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; + use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; @@ -296,7 +297,7 @@ where pub(crate) fn needs_normalization<'tcx, T: TypeFoldable<'tcx>>(value: &T, reveal: Reveal) -> bool { match reveal { - Reveal::UserFacing => value + Reveal::Selection | Reveal::UserFacing => value .has_type_flags(ty::TypeFlags::HAS_TY_PROJECTION | ty::TypeFlags::HAS_CT_PROJECTION), Reveal::All => value.has_type_flags( ty::TypeFlags::HAS_TY_PROJECTION @@ -394,8 +395,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { - Reveal::UserFacing => ty.super_fold_with(self), - + Reveal::UserFacing | Reveal::Selection => ty.super_fold_with(self), Reveal::All => { let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 26bacf787e2eb..d91a7c00acfe9 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -210,8 +210,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal() { - Reveal::UserFacing => ty.try_super_fold_with(self), - + Reveal::UserFacing | Reveal::Selection => ty.try_super_fold_with(self), Reveal::All => { let substs = substs.try_super_fold_with(self)?; let recursion_limit = self.tcx().recursion_limit(); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index fa88c8ee37015..6d9bcc2754502 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -625,6 +625,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { uv, obligation.param_env, obligation.cause.span, + const_evaluatable::UseRevealSelection::Yes, ) { Ok(()) => Ok(EvaluatedToOk), Err(NotConstEvaluatable::MentionsInfer) => Ok(EvaluatedToAmbig), @@ -654,7 +655,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::ConstKind::Unevaluated(unevaluated) = c.val { self.infcx .const_eval_resolve( - obligation.param_env, + obligation.param_env.with_reveal_selection(), unevaluated, Some(obligation.cause.span), ) @@ -675,8 +676,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Err(_) => Ok(EvaluatedToErr), } } - (Err(ErrorHandled::Reported(ErrorReported)), _) - | (_, Err(ErrorHandled::Reported(ErrorReported))) => Ok(EvaluatedToErr), + (Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Silent), _) + | (_, Err(ErrorHandled::Reported(ErrorReported) | ErrorHandled::Silent)) => { + Ok(EvaluatedToErr) + } (Err(ErrorHandled::Linted), _) | (_, Err(ErrorHandled::Linted)) => { span_bug!( obligation.cause.span(self.tcx()), diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr index 3fb4ab72fe6d6..e5a2777a47bc5 100644 --- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr @@ -5,11 +5,6 @@ note: ...which requires simplifying constant for the type system `Tr::A`... | 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 | @@ -21,11 +16,6 @@ note: ...which requires simplifying constant for the type system `Tr::B`... | 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 | 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 61b16cb9d5811..1ec52e019d4c9 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `IMPL LL | const IMPL_REF_BAR: u32 = GlobalImplRef::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 const-evaluating + checking `IMPL_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 | @@ -20,11 +15,6 @@ 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 494dc0c0ed447..4a6d0c5019ec5 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `DEFA LL | const DEFAULT_REF_BAR: u32 = ::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 const-evaluating + checking `DEFAULT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 | @@ -20,11 +15,6 @@ note: ...which requires simplifying constant for the type system `FooDefault::BA | 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 4ff253bffcb32..727c326e594dc 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `TRAI LL | const TRAIT_REF_BAR: u32 = ::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 const-evaluating + checking `TRAIT_REF_BAR`... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 | @@ -20,11 +15,6 @@ 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/const-generics/defaults/default-param-wf-concrete.rs b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs index 41a52c7eb0d83..2d6d64bbf4de7 100644 --- a/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -1,3 +1,4 @@ struct Foo; //~^ ERROR evaluation of constant value failed +//~| ERROR failed to evaluate fn main() {} diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr index e8ebddade5c16..24ad7a1ad5a67 100644 --- a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr +++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr @@ -4,6 +4,12 @@ error[E0080]: evaluation of constant value failed LL | struct Foo; | ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow -error: aborting due to previous error +error: failed to evaluate the given constant + --> $DIR/default-param-wf-concrete.rs:1:18 + | +LL | struct Foo; + | ^ + +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/defaults/wfness.rs b/src/test/ui/const-generics/defaults/wfness.rs index d366040ba3ea6..e13b07f5ba0cb 100644 --- a/src/test/ui/const-generics/defaults/wfness.rs +++ b/src/test/ui/const-generics/defaults/wfness.rs @@ -1,5 +1,6 @@ struct Ooopsies; //~^ error: evaluation of constant value failed +//~| ERROR failed to evaluate trait Trait {} impl Trait<3> for () {} diff --git a/src/test/ui/const-generics/defaults/wfness.stderr b/src/test/ui/const-generics/defaults/wfness.stderr index facf0ae19f734..a4015479ac488 100644 --- a/src/test/ui/const-generics/defaults/wfness.stderr +++ b/src/test/ui/const-generics/defaults/wfness.stderr @@ -4,8 +4,14 @@ error[E0080]: evaluation of constant value failed LL | struct Ooopsies; | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow +error: failed to evaluate the given constant + --> $DIR/wfness.rs:1:23 + | +LL | struct Ooopsies; + | ^ + error[E0277]: the trait bound `(): Trait<2_u8>` is not satisfied - --> $DIR/wfness.rs:6:47 + --> $DIR/wfness.rs:7:47 | LL | struct WhereClause where (): Trait; | ^^^^^^^^ the trait `Trait<2_u8>` is not implemented for `()` @@ -14,7 +20,7 @@ LL | struct WhereClause where (): Trait; <() as Trait<3_u8>> error[E0277]: the trait bound `(): Trait<1_u8>` is not satisfied - --> $DIR/wfness.rs:14:13 + --> $DIR/wfness.rs:15:13 | LL | fn foo() -> DependentDefaultWfness { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1_u8>` is not implemented for `()` @@ -22,12 +28,12 @@ LL | fn foo() -> DependentDefaultWfness { = help: the following implementations were found: <() as Trait<3_u8>> note: required by a bound in `WhereClause` - --> $DIR/wfness.rs:6:47 + --> $DIR/wfness.rs:7:47 | LL | struct WhereClause where (): Trait; | ^^^^^^^^ required by this bound in `WhereClause` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0080, E0277. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs index 90953145944fe..b0b8574f4a85f 100644 --- a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs +++ b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.rs @@ -8,4 +8,6 @@ fn test() -> [u8; N - 1] { fn main() { test::<0>(); + //~^ ERROR failed to evaluate + //~| ERROR failed to evaluate } diff --git a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr index 31ccf97969472..c7a33b2571829 100644 --- a/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/from-sig-fail.stderr @@ -4,6 +4,30 @@ error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed LL | fn test() -> [u8; N - 1] { | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -error: aborting due to previous error +error: failed to evaluate the given constant + --> $DIR/from-sig-fail.rs:10:5 + | +LL | test::<0>(); + | ^^^^^^^^^ + | +note: required by a bound in `test` + --> $DIR/from-sig-fail.rs:4:35 + | +LL | fn test() -> [u8; N - 1] { + | ^^^^^ required by this bound in `test` + +error: failed to evaluate the given constant + --> $DIR/from-sig-fail.rs:10:5 + | +LL | test::<0>(); + | ^^^^^^^^^^^ + | +note: required by a bound in `test` + --> $DIR/from-sig-fail.rs:4:35 + | +LL | fn test() -> [u8; N - 1] { + | ^^^^^ required by this bound in `test` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs b/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs index 275f69953024c..83e3f6f718372 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs +++ b/src/test/ui/const-generics/generic_const_exprs/issue-80742.rs @@ -29,4 +29,5 @@ where fn main() { let dst = Inline::::new(0); //~ ERROR //~^ ERROR + //~| ERROR failed to evaluate } diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr index 56cb11bacbe6b..ca8126e47ada1 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -1,17 +1,3 @@ -error[E0080]: evaluation of `Inline::::{constant#0}` failed - --> $SRC_DIR/core/src/mem/mod.rs:LL:COL - | -LL | intrinsics::size_of::() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | size_of called on unsized type `dyn Debug` - | inside `std::mem::size_of::` at $SRC_DIR/core/src/mem/mod.rs:LL:COL - | - ::: $DIR/issue-80742.rs:22:10 - | -LL | [u8; size_of::() + 1]: , - | -------------- inside `Inline::::{constant#0}` at $DIR/issue-80742.rs:22:10 - error[E0599]: the function or associated item `new` exists for struct `Inline`, but its trait bounds were not satisfied --> $DIR/issue-80742.rs:30:36 | @@ -35,6 +21,23 @@ LL | pub trait Debug { = note: the following trait bounds were not satisfied: `dyn Debug: Sized` +error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time + --> $DIR/issue-80742.rs:30:15 + | +LL | let dst = Inline::::new(0); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Debug` +note: required by a bound in `Inline` + --> $DIR/issue-80742.rs:12:15 + | +LL | struct Inline + | ^ required by this bound in `Inline` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Inline + | ++++++++ + error[E0080]: evaluation of `Inline::::{constant#0}` failed --> $SRC_DIR/core/src/mem/mod.rs:LL:COL | @@ -49,22 +52,20 @@ LL | intrinsics::size_of::() LL | [u8; size_of::() + 1]: , | -------------- inside `Inline::::{constant#0}` at $DIR/issue-80742.rs:14:10 -error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time +error: failed to evaluate the given constant --> $DIR/issue-80742.rs:30:15 | LL | let dst = Inline::::new(0); - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^^ | - = help: the trait `Sized` is not implemented for `dyn Debug` note: required by a bound in `Inline` - --> $DIR/issue-80742.rs:12:15 + --> $DIR/issue-80742.rs:14:10 | LL | struct Inline - | ^ required by this bound in `Inline` -help: consider relaxing the implicit `Sized` restriction - | -LL | struct Inline - | ++++++++ + | ------ required by a bound in this +LL | where +LL | [u8; size_of::() + 1]: , + | ^^^^^^^^^^^^^^^^^^ required by this bound in `Inline` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs b/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs index c47a350c7fb43..6a78a6b23cf23 100644 --- a/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs +++ b/src/test/ui/const-generics/generic_const_exprs/simple_fail.rs @@ -11,4 +11,6 @@ fn test() -> Arr where [u8; N - 1]: Sized { fn main() { test::<0>(); + //~^ ERROR failed to evaluate + //~| ERROR failed to evaluate } diff --git a/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr b/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr index 99fc92fb4f0ad..e3b493c4c8833 100644 --- a/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/simple_fail.stderr @@ -4,12 +4,30 @@ error[E0080]: evaluation of `test::<0_usize>::{constant#0}` failed LL | fn test() -> Arr where [u8; N - 1]: Sized { | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow +error: failed to evaluate the given constant + --> $DIR/simple_fail.rs:13:5 + | +LL | test::<0>(); + | ^^^^^^^^^ + | +note: required by a bound in `test` + --> $DIR/simple_fail.rs:7:48 + | +LL | fn test() -> Arr where [u8; N - 1]: Sized { + | ^^^^^ required by this bound in `test` + error[E0080]: evaluation of `Arr::<0_usize>::{constant#0}` failed --> $DIR/simple_fail.rs:4:33 | LL | type Arr = [u8; N - 1]; | ^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow -error: aborting due to 2 previous errors +error: failed to evaluate the given constant + --> $DIR/simple_fail.rs:13:5 + | +LL | test::<0>(); + | ^^^^^^^^^^^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/issues/issue-67739.rs b/src/test/ui/const-generics/issues/issue-67739.rs index de0eb7f509ae5..8eae84c8bfb30 100644 --- a/src/test/ui/const-generics/issues/issue-67739.rs +++ b/src/test/ui/const-generics/issues/issue-67739.rs @@ -9,8 +9,8 @@ pub trait Trait { fn associated_size(&self) -> usize { [0u8; mem::size_of::()]; - //[min]~^ ERROR constant expression depends on a generic parameter - //[full]~^^ ERROR unconstrained generic constant + //[full]~^ ERROR unconstrained generic constant + //[min]~^^ ERROR constant expression depends on a generic parameter 0 } } diff --git a/src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr index 415a53a56274a..f61067fb8fdd5 100644 --- a/src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr +++ b/src/test/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr @@ -34,7 +34,24 @@ LL | get_flag::(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:40:14 + --> $DIR/invalid-patterns.rs:38:21 + | +LL | get_flag::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | + = 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) { + __ __ __ __ │ ░░░░ + } + +error: failed to evaluate the given constant + --> $DIR/invalid-patterns.rs:38:21 + | +LL | get_flag::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:42:14 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, but expected a boolean @@ -47,6 +64,45 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); error[E0080]: it is undefined behavior to use this value --> $DIR/invalid-patterns.rs:42:14 | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, but expected a boolean + | + = 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: 1, align: 1) { + 42 │ B + } + +error: failed to evaluate the given constant + --> $DIR/invalid-patterns.rs:42:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:46:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, but expected a boolean + | + = 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: 1, align: 1) { + 42 │ B + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:46:47 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) + | + = 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) { + __ __ __ __ │ ░░░░ + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/invalid-patterns.rs:46:14 + | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x42, but expected a boolean | @@ -55,8 +111,14 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character 42 │ B } +error: failed to evaluate the given constant + --> $DIR/invalid-patterns.rs:46:14 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0080]: it is undefined behavior to use this value - --> $DIR/invalid-patterns.rs:42:47 + --> $DIR/invalid-patterns.rs:46:47 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) @@ -66,7 +128,13 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character __ __ __ __ │ ░░░░ } -error: aborting due to 8 previous errors +error: failed to evaluate the given constant + --> $DIR/invalid-patterns.rs:46:47 + | +LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors Some errors have detailed explanations: E0080, E0308. For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs b/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs index 682e0eced9dff..d4e4abed44f57 100644 --- a/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs +++ b/src/test/ui/const-generics/min_const_generics/invalid-patterns.rs @@ -37,9 +37,17 @@ fn main() { get_flag::(); //~^ ERROR it is undefined behavior + //~| ERROR it is undefined behavior + //~| ERROR failed to evaluate get_flag::<{ unsafe { bool_raw.boolean } }, 'z'>(); //~^ ERROR it is undefined behavior + //~| ERROR it is undefined behavior + //~| ERROR failed to evaluate get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); //~^ ERROR it is undefined behavior //~| ERROR it is undefined behavior + //~| ERROR it is undefined behavior + //~| ERROR it is undefined behavior + //~| ERROR failed to evaluate + //~| ERROR failed to evaluate } diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.rs b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs index bcc966dc9621c..334016f76f8cd 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3.rs +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.rs @@ -17,6 +17,8 @@ const A_I8_I : [u32; (i8::MAX as usize) + 1] = [0; (i8::MAX + 1) as usize]; //~^ ERROR evaluation of constant value failed +//~| ERROR evaluation of constant value failed +//~| ERROR failed to evaluate fn main() { foo(&A_I8_I[..]); diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr index 73f421b5b1465..d1f103a145198 100644 --- a/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr +++ b/src/test/ui/consts/const-eval/const-eval-overflow-3.stderr @@ -4,6 +4,18 @@ error[E0080]: evaluation of constant value failed LL | = [0; (i8::MAX + 1) as usize]; | ^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow -error: aborting due to previous error +error[E0080]: evaluation of constant value failed + --> $DIR/const-eval-overflow-3.rs:18:11 + | +LL | = [0; (i8::MAX + 1) as usize]; + | ^^^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow + +error: failed to evaluate the given constant + --> $DIR/const-eval-overflow-3.rs:18:11 + | +LL | = [0; (i8::MAX + 1) as usize]; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr new file mode 100644 index 0000000000000..72e54f8ec21da --- /dev/null +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -0,0 +1,237 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:25:5 + | +LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes + | + = 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. + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:28:43 + | +LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 }; + | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + | + = note: `#[deny(const_err)]` on by default + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:31:45 + | +LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 }; + | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:34:45 + | +LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 }; + | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:37:5 + | +LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc24, but expected initialized plain (non-pointer) bytes + | + = 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. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:40:5 + | +LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes + | + = 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. + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:43:43 + | +LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 }; + | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:46:45 + | +LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 }; + | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:49:45 + | +LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 }; + | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:52:5 + | +LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc50, but expected initialized plain (non-pointer) bytes + | + = 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. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:55:5 + | +LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes + | + = 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. + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:58:45 + | +LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 }; + | ----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:61:5 + | +LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc64, but expected initialized plain (non-pointer) bytes + | + = 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. + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:64:47 + | +LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey }; + | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:67:47 + | +LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character }; + | ------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:70:39 + | +LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 }; + | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:73:41 + | +LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 }; + | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:76:41 + | +LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 }; + | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:79:5 + | +LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc98, but expected initialized plain (non-pointer) bytes + | + = 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. + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:82:43 + | +LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 }; + | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:85:39 + | +LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 }; + | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:88:41 + | +LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 }; + | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:91:41 + | +LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 }; + | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:94:5 + | +LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc125, but expected initialized plain (non-pointer) bytes + | + = 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. + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:97:43 + | +LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 }; + | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:100:41 + | +LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 }; + | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error[E0080]: it is undefined behavior to use this value + --> $DIR/const-pointer-values-in-various-types.rs:103:5 + | +LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc140, but expected initialized plain (non-pointer) bytes + | + = 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. + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:106:43 + | +LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey }; + | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: any use of this value will cause an error + --> $DIR/const-pointer-values-in-various-types.rs:109:43 + | +LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character }; + | --------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn pointer into raw bytes + +error: aborting due to 29 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/infinite_loop.rs b/src/test/ui/consts/const-eval/infinite_loop.rs index 14a573ccf5ac6..08cf043e867ab 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.rs +++ b/src/test/ui/consts/const-eval/infinite_loop.rs @@ -1,11 +1,12 @@ fn main() { // Tests the Collatz conjecture with an incorrect base case (0 instead of 1). // The value of `n` will loop indefinitely (4 - 2 - 1 - 4). - let _ = [(); { + let _ = [(); { //~ ERROR failed to evaluate the given constant let mut n = 113383; // #20 in https://oeis.org/A006884 while n != 0 { n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed } n }]; diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr index 3b5a0f22f28be..9770435678984 100644 --- a/src/test/ui/consts/const-eval/infinite_loop.stderr +++ b/src/test/ui/consts/const-eval/infinite_loop.stderr @@ -4,6 +4,25 @@ error[E0080]: evaluation of constant value failed LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; | ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) -error: aborting due to previous error +error: failed to evaluate the given constant + --> $DIR/infinite_loop.rs:4:18 + | +LL | let _ = [(); { + | __________________^ +LL | | let mut n = 113383; // #20 in https://oeis.org/A006884 +LL | | while n != 0 { +LL | | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; +... | +LL | | n +LL | | }]; + | |_____^ + +error[E0080]: evaluation of constant value failed + --> $DIR/infinite_loop.rs:7:20 + | +LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 }; + | ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/issue-52475.rs b/src/test/ui/consts/const-eval/issue-52475.rs index ce65407bbab0b..fe5d52e4b1e49 100644 --- a/src/test/ui/consts/const-eval/issue-52475.rs +++ b/src/test/ui/consts/const-eval/issue-52475.rs @@ -1,9 +1,11 @@ fn main() { - let _ = [(); { + let _ = [(); { //~ ERROR failed to evaluate the given constant let mut x = &0; let mut n = 0; while n < 5 { - n = (n + 1) % 5; //~ ERROR evaluation of constant value failed + n = (n + 1) % 5; + //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed x = &0; // Materialize a new AllocId } 0 diff --git a/src/test/ui/consts/const-eval/issue-52475.stderr b/src/test/ui/consts/const-eval/issue-52475.stderr index 8536ff02c6dae..aa09c2925c1f3 100644 --- a/src/test/ui/consts/const-eval/issue-52475.stderr +++ b/src/test/ui/consts/const-eval/issue-52475.stderr @@ -4,6 +4,25 @@ error[E0080]: evaluation of constant value failed LL | n = (n + 1) % 5; | ^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) -error: aborting due to previous error +error: failed to evaluate the given constant + --> $DIR/issue-52475.rs:2:18 + | +LL | let _ = [(); { + | __________________^ +LL | | let mut x = &0; +LL | | let mut n = 0; +LL | | while n < 5 { +... | +LL | | 0 +LL | | }]; + | |_____^ + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-52475.rs:6:17 + | +LL | n = (n + 1) % 5; + | ^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`) + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr index 4f7dd5cdf7c73..0d7d1f691ed0e 100644 --- a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr @@ -13,22 +13,22 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:27:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc9, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc11, but expected initialized plain (non-pointer) bytes | = 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) { - ╾───────alloc9────────╼ │ ╾──────╼ + ╾───────alloc11───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc13, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc15, but expected initialized plain (non-pointer) bytes | = 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) { - ╾───────alloc13───────╼ │ ╾──────╼ + ╾───────alloc15───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -46,22 +46,22 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:44:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc19, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc21, but expected initialized plain (non-pointer) bytes | = 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) { - ╾───────alloc19───────╼ │ ╾──────╼ + ╾───────alloc21───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:47:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc23, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0.: encountered pointer to alloc25, but expected initialized plain (non-pointer) bytes | = 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) { - ╾───────alloc23───────╼ │ ╾──────╼ + ╾───────alloc25───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value @@ -79,11 +79,11 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc29, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .: encountered pointer to alloc31, but expected initialized plain (non-pointer) bytes | = 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) { - ╾───────alloc29───────╼ │ ╾──────╼ + ╾───────alloc31───────╼ │ ╾──────╼ } error[E0080]: it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 1067eb003f7c7..82fed16e06ca6 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Foo: LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`... - --> $DIR/const-size_of-cycle.rs:4:17 - | -LL | bytes: [u8; std::mem::size_of::()] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/const-size_of-cycle.rs:4:17 | diff --git a/src/test/ui/consts/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr index 113f86cf0f99f..915cf4fafd7bd 100644 --- a/src/test/ui/consts/issue-36163.stderr +++ b/src/test/ui/consts/issue-36163.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Foo: 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 | @@ -20,11 +15,6 @@ note: ...which requires simplifying constant for the type system `A`... | 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 | diff --git a/src/test/ui/consts/issue-44415.stderr b/src/test/ui/consts/issue-44415.stderr index 9e3db5ce9a402..4a9df8206ded1 100644 --- a/src/test/ui/consts/issue-44415.stderr +++ b/src/test/ui/consts/issue-44415.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Foo: LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^ | -note: ...which requires simplifying constant for the type system `Foo::bytes::{constant#0}`... - --> $DIR/issue-44415.rs:6:17 - | -LL | bytes: [u8; unsafe { intrinsics::size_of::() }], - | ^^^^^^ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`... --> $DIR/issue-44415.rs:6:17 | diff --git a/src/test/ui/consts/issue-66693-panic-in-array-len.rs b/src/test/ui/consts/issue-66693-panic-in-array-len.rs index fc0dcd7a44daa..b929bd3f351cf 100644 --- a/src/test/ui/consts/issue-66693-panic-in-array-len.rs +++ b/src/test/ui/consts/issue-66693-panic-in-array-len.rs @@ -9,6 +9,8 @@ fn main() { // ensure that conforming panics are handled correctly let _ = [false; panic!()]; //~^ ERROR: evaluation of constant value failed + //~| ERROR: evaluation of constant value failed + //~| ERROR failed to evaluate the given constant // typechecking halts before getting to this one let _ = ['a', panic!("panic in array len")]; diff --git a/src/test/ui/consts/issue-66693-panic-in-array-len.stderr b/src/test/ui/consts/issue-66693-panic-in-array-len.stderr index 4ccbeb73c8a25..1ff69c1faef0f 100644 --- a/src/test/ui/consts/issue-66693-panic-in-array-len.stderr +++ b/src/test/ui/consts/issue-66693-panic-in-array-len.stderr @@ -14,6 +14,22 @@ LL | let _ = [false; panic!()]; | = 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 2 previous errors +error: failed to evaluate the given constant + --> $DIR/issue-66693-panic-in-array-len.rs:10:21 + | +LL | let _ = [false; panic!()]; + | ^^^^^^^^ + | + = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-66693-panic-in-array-len.rs:10:21 + | +LL | let _ = [false; panic!()]; + | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-66693-panic-in-array-len.rs:10:21 + | + = 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 4 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/recursive-zst-static.default.stderr b/src/test/ui/consts/recursive-zst-static.default.stderr index 03f8f5c5a0e5d..8d2cfd284e20f 100644 --- a/src/test/ui/consts/recursive-zst-static.default.stderr +++ b/src/test/ui/consts/recursive-zst-static.default.stderr @@ -4,12 +4,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` LL | static FOO: () = FOO; | ^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `FOO`... - --> $DIR/recursive-zst-static.rs:10:1 - | -LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + = note: ...which immediately requires const-evaluating + checking `FOO` again = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/consts/recursive-zst-static.unleash.stderr b/src/test/ui/consts/recursive-zst-static.unleash.stderr index 03f8f5c5a0e5d..8d2cfd284e20f 100644 --- a/src/test/ui/consts/recursive-zst-static.unleash.stderr +++ b/src/test/ui/consts/recursive-zst-static.unleash.stderr @@ -4,12 +4,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` LL | static FOO: () = FOO; | ^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `FOO`... - --> $DIR/recursive-zst-static.rs:10:1 - | -LL | static FOO: () = FOO; - | ^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + = note: ...which immediately requires const-evaluating + checking `FOO` again = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/consts/write-to-static-mut-in-static.stderr b/src/test/ui/consts/write-to-static-mut-in-static.stderr index 789919bd1668d..8916ea3283565 100644 --- a/src/test/ui/consts/write-to-static-mut-in-static.stderr +++ b/src/test/ui/consts/write-to-static-mut-in-static.stderr @@ -10,12 +10,7 @@ error[E0391]: cycle detected when const-evaluating + checking `C` LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `C`... - --> $DIR/write-to-static-mut-in-static.rs:5:1 - | -LL | pub static mut C: u32 = unsafe { C = 1; 0 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `C`, completing the cycle + = note: ...which immediately requires const-evaluating + checking `C` again = note: cycle used when running analysis passes on this crate error: aborting due to 2 previous errors diff --git a/src/test/ui/enum/issue-67945-1.rs b/src/test/ui/enum/issue-67945-1.rs index f4697344cc7a4..e279dd1e501ca 100644 --- a/src/test/ui/enum/issue-67945-1.rs +++ b/src/test/ui/enum/issue-67945-1.rs @@ -1,6 +1,7 @@ enum Bug { //~ ERROR parameter `S` is never used Var = { - let x: S = 0; //~ ERROR generic parameters may not be used + let x: S = 0; + //~^ ERROR generic parameters may not be used 0 }, } diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr index 1148577016ab4..86e81a0784830 100644 --- a/src/test/ui/issues/issue-17252.stderr +++ b/src/test/ui/issues/issue-17252.stderr @@ -5,11 +5,6 @@ note: ...which requires simplifying constant for the type system `FOO`... | LL | const FOO: usize = 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 const-evaluating + checking `FOO`... --> $DIR/issue-17252.rs:1:1 | diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr index d3a1993536a00..b71d07f10ea9c 100644 --- a/src/test/ui/issues/issue-23302-1.stderr +++ b/src/test/ui/issues/issue-23302-1.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `X::A LL | A = X::A as isize, | ^^^^^^^^^^^^^ | -note: ...which requires 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 | diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr index d3b78ea1af5f5..94c68b6ae5e14 100644 --- a/src/test/ui/issues/issue-23302-2.stderr +++ b/src/test/ui/issues/issue-23302-2.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Y::A LL | A = Y::B as isize, | ^^^^^^^^^^^^^ | -note: ...which requires 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 | diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr index 5233b832ecc79..441fcdcea04c4 100644 --- a/src/test/ui/issues/issue-23302-3.stderr +++ b/src/test/ui/issues/issue-23302-3.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `A` 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 | @@ -20,11 +15,6 @@ note: ...which requires simplifying constant for the type system `B`... | LL | const B: i32 = A; | ^^^^^^^^^^^^^^^^^ -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 const-evaluating + checking `B`... --> $DIR/issue-23302-3.rs:3:1 | diff --git a/src/test/ui/mir/issue-80742.rs b/src/test/ui/mir/issue-80742.rs new file mode 100644 index 0000000000000..bf7d4e9ab3131 --- /dev/null +++ b/src/test/ui/mir/issue-80742.rs @@ -0,0 +1,34 @@ +// check-fail + +// This test used to cause an ICE in rustc_mir::interpret::step::eval_rvalue_into_place + +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +use std::fmt::Debug; +use std::marker::PhantomData; +use std::mem::size_of; + +struct Inline +where + [u8; size_of::() + 1]: , +{ + _phantom: PhantomData, + buf: [u8; size_of::() + 1], +} + +impl Inline +where + [u8; size_of::() + 1]: , +{ + pub fn new(val: T) -> Inline { + todo!() + } +} + +fn main() { + let dst = Inline::::new(0); + //~^ ERROR the function or associated item `new` exists for struct + //~| ERROR the size for values of type + //~| ERROR failed to evaluate +} diff --git a/src/test/ui/mir/issue-80742.stderr b/src/test/ui/mir/issue-80742.stderr new file mode 100644 index 0000000000000..ca8126e47ada1 --- /dev/null +++ b/src/test/ui/mir/issue-80742.stderr @@ -0,0 +1,73 @@ +error[E0599]: the function or associated item `new` exists for struct `Inline`, but its trait bounds were not satisfied + --> $DIR/issue-80742.rs:30:36 + | +LL | / struct Inline +LL | | where +LL | | [u8; size_of::() + 1]: , +LL | | { +LL | | _phantom: PhantomData, +LL | | buf: [u8; size_of::() + 1], +LL | | } + | |_- function or associated item `new` not found for this +... +LL | let dst = Inline::::new(0); + | ^^^ function or associated item cannot be called on `Inline` due to unsatisfied trait bounds + | + ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL + | +LL | pub trait Debug { + | --------------- doesn't satisfy `dyn Debug: Sized` + | + = note: the following trait bounds were not satisfied: + `dyn Debug: Sized` + +error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time + --> $DIR/issue-80742.rs:30:15 + | +LL | let dst = Inline::::new(0); + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Debug` +note: required by a bound in `Inline` + --> $DIR/issue-80742.rs:12:15 + | +LL | struct Inline + | ^ required by this bound in `Inline` +help: consider relaxing the implicit `Sized` restriction + | +LL | struct Inline + | ++++++++ + +error[E0080]: evaluation of `Inline::::{constant#0}` failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | +LL | intrinsics::size_of::() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | size_of called on unsized type `dyn Debug` + | inside `std::mem::size_of::` at $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + ::: $DIR/issue-80742.rs:14:10 + | +LL | [u8; size_of::() + 1]: , + | -------------- inside `Inline::::{constant#0}` at $DIR/issue-80742.rs:14:10 + +error: failed to evaluate the given constant + --> $DIR/issue-80742.rs:30:15 + | +LL | let dst = Inline::::new(0); + | ^^^^^^^^^^^^^^^^^^^ + | +note: required by a bound in `Inline` + --> $DIR/issue-80742.rs:14:10 + | +LL | struct Inline + | ------ required by a bound in this +LL | where +LL | [u8; size_of::() + 1]: , + | ^^^^^^^^^^^^^^^^^^ required by this bound in `Inline` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0080, E0277, E0599. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/recursion/recursive-static-definition.stderr b/src/test/ui/recursion/recursive-static-definition.stderr index ee73b026a0b75..56767f391531b 100644 --- a/src/test/ui/recursion/recursive-static-definition.stderr +++ b/src/test/ui/recursion/recursive-static-definition.stderr @@ -4,12 +4,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO` LL | pub static FOO: u32 = FOO; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating + checking `FOO`... - --> $DIR/recursive-static-definition.rs:1:1 - | -LL | pub static FOO: u32 = FOO; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `FOO`, completing the cycle + = note: ...which immediately requires const-evaluating + checking `FOO` again = note: cycle used when running analysis passes on this crate error: aborting due to previous error diff --git a/src/test/ui/treat-err-as-bug/err.stderr b/src/test/ui/treat-err-as-bug/err.stderr index 8f67571c2990e..40dc0a8685b20 100644 --- a/src/test/ui/treat-err-as-bug/err.stderr +++ b/src/test/ui/treat-err-as-bug/err.stderr @@ -8,5 +8,5 @@ error: internal compiler error: unexpected panic query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `C` -#1 [eval_to_allocation_raw] const-evaluating + checking `C` +#1 [analysis] running analysis passes on this crate end of query stack diff --git a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr index 277f4e8424030..c0f67b2889a99 100644 --- a/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -4,11 +4,6 @@ error[E0391]: cycle detected when simplifying constant for the type system `Alph LL | V3 = Self::V1 {} as u8 + 2, | ^^^^^^^^ | -note: ...which requires simplifying constant for the type system `Alpha::V3::{constant#0}`... - --> $DIR/self-in-enum-definition.rs:5:10 - | -LL | V3 = Self::V1 {} as u8 + 2, - | ^^^^^^^^ note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`... --> $DIR/self-in-enum-definition.rs:5:10 |