From bd7229daf06b954b93d553825e8c7673cb1019c9 Mon Sep 17 00:00:00 2001 From: Vishnunarayan K I Date: Wed, 4 Nov 2020 22:23:43 +0530 Subject: [PATCH 1/2] make intern_const_alloc_recursive return error fix #78655 --- .../rustc_middle/src/mir/interpret/error.rs | 12 ++++++-- compiler/rustc_mir/src/const_eval/error.rs | 2 +- .../rustc_mir/src/const_eval/eval_queries.rs | 2 +- compiler/rustc_mir/src/const_eval/mod.rs | 4 ++- .../rustc_mir/src/interpret/eval_context.rs | 6 ++-- compiler/rustc_mir/src/interpret/intern.rs | 7 ++++- compiler/rustc_mir/src/interpret/operand.rs | 2 +- src/test/ui/consts/issue-78655.rs | 10 +++++++ src/test/ui/consts/issue-78655.stderr | 30 +++++++++++++++++++ 9 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/consts/issue-78655.rs create mode 100644 src/test/ui/consts/issue-78655.stderr diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index d41e5680602..e35ff6b996e 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -81,6 +81,12 @@ impl From for InterpErrorInfo<'_> { } } +impl From for InterpErrorInfo<'_> { + fn from(err: ErrorReported) -> Self { + InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err)).into() + } +} + impl<'tcx> From> for InterpErrorInfo<'tcx> { fn from(kind: InterpError<'tcx>) -> Self { let capture_backtrace = tls::with_opt(|tcx| { @@ -115,8 +121,8 @@ pub enum InvalidProgramInfo<'tcx> { /// Cannot compute this constant because it depends on another one /// which already produced an error. ReferencedConstant, - /// Abort in case type errors are reached. - TypeckError(ErrorReported), + /// Abort in case errors are already reported. + AlreadyReported(ErrorReported), /// An error occurred during layout computation. Layout(layout::LayoutError<'tcx>), /// An invalid transmute happened. @@ -129,7 +135,7 @@ impl fmt::Display for InvalidProgramInfo<'_> { match self { TooGeneric => write!(f, "encountered overly generic constant"), ReferencedConstant => write!(f, "referenced constant has errors"), - TypeckError(ErrorReported) => { + AlreadyReported(ErrorReported) => { write!(f, "encountered constants with type errors, stopping evaluation") } Layout(ref err) => write!(f, "{}", err), diff --git a/compiler/rustc_mir/src/const_eval/error.rs b/compiler/rustc_mir/src/const_eval/error.rs index 044d27a6a9d..39358e03e75 100644 --- a/compiler/rustc_mir/src/const_eval/error.rs +++ b/compiler/rustc_mir/src/const_eval/error.rs @@ -141,7 +141,7 @@ impl<'tcx> ConstEvalErr<'tcx> { err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { return ErrorHandled::TooGeneric; } - err_inval!(TypeckError(error_reported)) => { + err_inval!(AlreadyReported(error_reported)) => { return ErrorHandled::Reported(error_reported); } // We must *always* hard error on these, even if the caller wants just a lint. diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index 7b9a4ec873d..438704d0f4d 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -67,7 +67,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( None => InternKind::Constant, } }; - intern_const_alloc_recursive(ecx, intern_kind, ret); + intern_const_alloc_recursive(ecx, intern_kind, ret)?; debug!("eval_body_using_ecx done: {:?}", *ret); Ok(ret) diff --git a/compiler/rustc_mir/src/const_eval/mod.rs b/compiler/rustc_mir/src/const_eval/mod.rs index 11a211ef7b3..9dd2a8592a7 100644 --- a/compiler/rustc_mir/src/const_eval/mod.rs +++ b/compiler/rustc_mir/src/const_eval/mod.rs @@ -29,7 +29,9 @@ pub(crate) fn const_caller_location( let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); let loc_place = ecx.alloc_caller_location(file, line, col); - intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place); + if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place).is_err() { + bug!("intern_const_alloc_recursive should not error in this case") + } ConstValue::Scalar(loc_place.ptr) } diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index ec1195d3703..1ec2e3b7c5a 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -471,7 +471,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(def) = def.as_local() { if self.tcx.has_typeck_results(def.did) { if let Some(error_reported) = self.tcx.typeck_opt_const_arg(def).tainted_by_errors { - throw_inval!(TypeckError(error_reported)) + throw_inval!(AlreadyReported(error_reported)) } } } @@ -527,8 +527,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(Some(instance)) => Ok(instance), Ok(None) => throw_inval!(TooGeneric), - // FIXME(eddyb) this could be a bit more specific than `TypeckError`. - Err(error_reported) => throw_inval!(TypeckError(error_reported)), + // FIXME(eddyb) this could be a bit more specific than `AlreadyReported`. + Err(error_reported) => throw_inval!(AlreadyReported(error_reported)), } } diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_mir/src/interpret/intern.rs index 5e5c74a3723..413be427339 100644 --- a/compiler/rustc_mir/src/interpret/intern.rs +++ b/compiler/rustc_mir/src/interpret/intern.rs @@ -16,6 +16,7 @@ use super::validity::RefTracking; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::{self, layout::TyAndLayout, Ty}; @@ -285,11 +286,13 @@ pub enum InternKind { /// tracks where in the value we are and thus can show much better error messages. /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures /// are hard errors. +#[tracing::instrument(skip(ecx))] pub fn intern_const_alloc_recursive>( ecx: &mut InterpCx<'mir, 'tcx, M>, intern_kind: InternKind, ret: MPlaceTy<'tcx>, -) where +) -> Result<(), ErrorReported> +where 'tcx: 'mir, { let tcx = ecx.tcx; @@ -405,12 +408,14 @@ pub fn intern_const_alloc_recursive>( // Codegen does not like dangling pointers, and generally `tcx` assumes that // all allocations referenced anywhere actually exist. So, make sure we error here. ecx.tcx.sess.span_err(ecx.tcx.span, "encountered dangling pointer in final constant"); + return Err(ErrorReported); } else if ecx.tcx.get_global_alloc(alloc_id).is_none() { // We have hit an `AllocId` that is neither in local or global memory and isn't // marked as dangling by local memory. That should be impossible. span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id); } } + Ok(()) } impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 3c68b1c8355..ba59ac14f9f 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -550,7 +550,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Early-return cases. let val_val = match val.val { ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric), - ty::ConstKind::Error(_) => throw_inval!(TypeckError(ErrorReported)), + ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)), ty::ConstKind::Unevaluated(def, substs, promoted) => { let instance = self.resolve(def, substs)?; return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into()); diff --git a/src/test/ui/consts/issue-78655.rs b/src/test/ui/consts/issue-78655.rs new file mode 100644 index 00000000000..066764bc46f --- /dev/null +++ b/src/test/ui/consts/issue-78655.rs @@ -0,0 +1,10 @@ +const FOO: *const u32 = { //~ ERROR encountered dangling pointer in final constant + let x; + &x //~ ERROR borrow of possibly-uninitialized variable: `x` +}; + +fn main() { + let FOO = FOO; + //~^ ERROR could not evaluate constant pattern + //~| ERROR could not evaluate constant pattern +} diff --git a/src/test/ui/consts/issue-78655.stderr b/src/test/ui/consts/issue-78655.stderr new file mode 100644 index 00000000000..cf3fe18f802 --- /dev/null +++ b/src/test/ui/consts/issue-78655.stderr @@ -0,0 +1,30 @@ +error[E0381]: borrow of possibly-uninitialized variable: `x` + --> $DIR/issue-78655.rs:3:5 + | +LL | &x + | ^^ use of possibly-uninitialized `x` + +error: encountered dangling pointer in final constant + --> $DIR/issue-78655.rs:1:1 + | +LL | / const FOO: *const u32 = { +LL | | let x; +LL | | &x +LL | | }; + | |__^ + +error: could not evaluate constant pattern + --> $DIR/issue-78655.rs:7:9 + | +LL | let FOO = FOO; + | ^^^ + +error: could not evaluate constant pattern + --> $DIR/issue-78655.rs:7:9 + | +LL | let FOO = FOO; + | ^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0381`. From a15ee4d7c844c317043116969cede8341d932a46 Mon Sep 17 00:00:00 2001 From: Vishnunarayan K I Date: Thu, 5 Nov 2020 13:24:21 +0530 Subject: [PATCH 2/2] update dangling-alloc-id-ice test --- src/test/ui/consts/dangling-alloc-id-ice.rs | 2 +- src/test/ui/consts/dangling-alloc-id-ice.stderr | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs index 3b7f1de5b9b..95acacdb787 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.rs +++ b/src/test/ui/consts/dangling-alloc-id-ice.rs @@ -6,7 +6,7 @@ union Foo<'a> { long_live_the_unit: &'static (), } -const FOO: &() = { //~ ERROR it is undefined behavior to use this value +const FOO: &() = { //~^ ERROR encountered dangling pointer in final constant let y = (); unsafe { Foo { y: &y }.long_live_the_unit } diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr index 14a49810b9d..24f57449872 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.stderr +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -8,18 +8,5 @@ LL | | unsafe { Foo { y: &y }.long_live_the_unit } LL | | }; | |__^ -error[E0080]: it is undefined behavior to use this value - --> $DIR/dangling-alloc-id-ice.rs:9:1 - | -LL | / const FOO: &() = { -LL | | -LL | | let y = (); -LL | | unsafe { Foo { y: &y }.long_live_the_unit } -LL | | }; - | |__^ type validation failed: encountered a dangling reference (use-after-free) - | - = 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: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0080`.