diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2021-01-29 09:17:38 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-29 09:17:38 +0900 |
| commit | 046a414c19cdbec02cf6809f4d25e53057a3a1c9 (patch) | |
| tree | e34acc2848b27a35487254abc7eeb82ced800f15 /compiler | |
| parent | 94e093ab9775946983cec2ac7547f61db3064a40 (diff) | |
| parent | 48f9dbfd59356f865f81ce674eefdbab2d7c3cbb (diff) | |
| download | rust-046a414c19cdbec02cf6809f4d25e53057a3a1c9.tar.gz rust-046a414c19cdbec02cf6809f4d25e53057a3a1c9.zip | |
Rollup merge of #81333 - RalfJung:const-err-simplify, r=oli-obk
clean up some const error reporting around promoteds These are some error reporting simplifications enabled by https://github.com/rust-lang/rust/pull/80579. Further simplifications are possible but could be blocked on making `const_err` a hard error. r? ``````@oli-obk``````
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_cranelift/src/constant.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/constant.rs | 7 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/const_eval/eval_queries.rs | 102 |
3 files changed, 32 insertions, 85 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index beff84fb2e2..5702832bcb6 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -134,11 +134,9 @@ pub(crate) fn codegen_constant<'tcx>( { Ok(const_val) => const_val, Err(_) => { - if promoted.is_none() { - fx.tcx - .sess - .span_err(constant.span, "erroneous constant encountered"); - } + fx.tcx + .sess + .span_err(constant.span, "erroneous constant encountered"); return crate::trap::trap_unreachable_ret_value( fx, fx.layout_of(const_.ty), diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 3a85c268e0e..b79a221a0e7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -30,12 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .tcx() .const_eval_resolve(ty::ParamEnv::reveal_all(), def, substs, promoted, None) .map_err(|err| { - if promoted.is_none() { - self.cx - .tcx() - .sess - .span_err(constant.span, "erroneous constant encountered"); - } + self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); err }), ty::ConstKind::Value(value) => Ok(value), diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index df163f65628..252f5e7ef2f 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -298,6 +298,8 @@ pub fn eval_to_allocation_raw_provider<'tcx>( tcx.def_span(def.did), key.param_env, CompileTimeInterpreter::new(tcx.sess.const_eval_limit()), + // Statics (and promoteds inside statics) may access other statics, because unlike consts + // they do not have to behave "as if" they were evaluated at runtime. MemoryExtra { can_access_statics: is_static }, ); @@ -305,83 +307,35 @@ pub fn eval_to_allocation_raw_provider<'tcx>( match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) { Err(error) => { let err = ConstEvalErr::new(&ecx, error, None); - // errors in statics are always emitted as fatal errors - if is_static { - // Ensure that if the above error was either `TooGeneric` or `Reported` - // an error must be reported. - let v = err.report_as_error( - ecx.tcx.at(ecx.cur_span()), - "could not evaluate static initializer", - ); - - // If this is `Reveal:All`, then we need to make sure an error is reported but if - // this is `Reveal::UserFacing`, then it's expected that we could get a - // `TooGeneric` error. When we fall back to `Reveal::All`, then it will either - // succeed or we'll report this error then. - if key.param_env.reveal() == Reveal::All { - tcx.sess.delay_span_bug( - err.span, - &format!("static eval failure did not emit an error: {:#?}", v), - ); - } - - Err(v) - } else if let Some(def) = def.as_local() { - // constant defined in this crate, we can figure out a lint level! - match tcx.def_kind(def.did.to_def_id()) { - // constants never produce a hard error at the definition site. Anything else is - // a backwards compatibility hazard (and will break old versions of winapi for - // sure) - // - // note that validation may still cause a hard error on this very same constant, - // because any code that existed before validation could not have failed - // validation thus preventing such a hard error from being a backwards - // compatibility hazard - DefKind::Const | DefKind::AssocConst => { - let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - Err(err.report_as_lint( - tcx.at(tcx.def_span(def.did)), - "any use of this value will cause an error", - hir_id, - Some(err.span), - )) - } - // promoting runtime code is only allowed to error if it references broken - // constants any other kind of error will be reported to the user as a - // deny-by-default lint - _ => { - if let Some(p) = cid.promoted { - let span = tcx.promoted_mir_opt_const_arg(def.to_global())[p].span; - if let err_inval!(ReferencedConstant) = err.error { - Err(err.report_as_error( - tcx.at(span), - "evaluation of constant expression failed", - )) - } else { - Err(err.report_as_lint( - tcx.at(span), - "reaching this expression at runtime will panic or abort", - tcx.hir().local_def_id_to_hir_id(def.did), - Some(err.span), - )) - } - // anything else (array lengths, enum initializers, constant patterns) are - // reported as hard errors - } else { - Err(err.report_as_error( - ecx.tcx.at(ecx.cur_span()), - "evaluation of constant value failed", - )) - } - } - } + // Some CTFE errors raise just a lint, not a hard error; see + // <https://github.com/rust-lang/rust/issues/71800>. + let emit_as_lint = if let Some(def) = def.as_local() { + // (Associated) consts only emit a lint, since they might be unused. + matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst) } else { - // use of broken constant from other crate - Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")) + // use of broken constant from other crate: always an error + false + }; + if emit_as_lint { + let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did); + Err(err.report_as_lint( + tcx.at(tcx.def_span(def.did)), + "any use of this value will cause an error", + hir_id, + Some(err.span), + )) + } else { + let msg = if is_static { + "could not evaluate static initializer" + } else { + "evaluation of constant value failed" + }; + Err(err.report_as_error(ecx.tcx.at(ecx.cur_span()), msg)) } } Ok(mplace) => { - // Since evaluation had no errors, valiate the resulting constant: + // Since evaluation had no errors, validate the resulting constant. + // This is a separate `try` block to provide more targeted error reporting. let validation = try { let mut ref_tracking = RefTracking::new(mplace); let mut inner = false; @@ -399,7 +353,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( } }; if let Err(error) = validation { - // Validation failed, report an error + // Validation failed, report an error. This is always a hard error. let err = ConstEvalErr::new(&ecx, error, None); Err(err.struct_error( ecx.tcx, |
