make intern_const_alloc_recursive return error fix #78655
This commit is contained in:
parent
8e8939b804
commit
bd7229daf0
9 changed files with 64 additions and 11 deletions
|
@ -81,6 +81,12 @@ impl From<ErrorHandled> for InterpErrorInfo<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ErrorReported> for InterpErrorInfo<'_> {
|
||||||
|
fn from(err: ErrorReported) -> Self {
|
||||||
|
InterpError::InvalidProgram(InvalidProgramInfo::AlreadyReported(err)).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
||||||
fn from(kind: InterpError<'tcx>) -> Self {
|
fn from(kind: InterpError<'tcx>) -> Self {
|
||||||
let capture_backtrace = tls::with_opt(|tcx| {
|
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
|
/// Cannot compute this constant because it depends on another one
|
||||||
/// which already produced an error.
|
/// which already produced an error.
|
||||||
ReferencedConstant,
|
ReferencedConstant,
|
||||||
/// Abort in case type errors are reached.
|
/// Abort in case errors are already reported.
|
||||||
TypeckError(ErrorReported),
|
AlreadyReported(ErrorReported),
|
||||||
/// An error occurred during layout computation.
|
/// An error occurred during layout computation.
|
||||||
Layout(layout::LayoutError<'tcx>),
|
Layout(layout::LayoutError<'tcx>),
|
||||||
/// An invalid transmute happened.
|
/// An invalid transmute happened.
|
||||||
|
@ -129,7 +135,7 @@ impl fmt::Display for InvalidProgramInfo<'_> {
|
||||||
match self {
|
match self {
|
||||||
TooGeneric => write!(f, "encountered overly generic constant"),
|
TooGeneric => write!(f, "encountered overly generic constant"),
|
||||||
ReferencedConstant => write!(f, "referenced constant has errors"),
|
ReferencedConstant => write!(f, "referenced constant has errors"),
|
||||||
TypeckError(ErrorReported) => {
|
AlreadyReported(ErrorReported) => {
|
||||||
write!(f, "encountered constants with type errors, stopping evaluation")
|
write!(f, "encountered constants with type errors, stopping evaluation")
|
||||||
}
|
}
|
||||||
Layout(ref err) => write!(f, "{}", err),
|
Layout(ref err) => write!(f, "{}", err),
|
||||||
|
|
|
@ -141,7 +141,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
|
||||||
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
|
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
|
||||||
return ErrorHandled::TooGeneric;
|
return ErrorHandled::TooGeneric;
|
||||||
}
|
}
|
||||||
err_inval!(TypeckError(error_reported)) => {
|
err_inval!(AlreadyReported(error_reported)) => {
|
||||||
return ErrorHandled::Reported(error_reported);
|
return ErrorHandled::Reported(error_reported);
|
||||||
}
|
}
|
||||||
// We must *always* hard error on these, even if the caller wants just a lint.
|
// We must *always* hard error on these, even if the caller wants just a lint.
|
||||||
|
|
|
@ -67,7 +67,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
|
||||||
None => InternKind::Constant,
|
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);
|
debug!("eval_body_using_ecx done: {:?}", *ret);
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
|
|
|
@ -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 mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
|
||||||
|
|
||||||
let loc_place = ecx.alloc_caller_location(file, line, col);
|
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)
|
ConstValue::Scalar(loc_place.ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -471,7 +471,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
if let Some(def) = def.as_local() {
|
if let Some(def) = def.as_local() {
|
||||||
if self.tcx.has_typeck_results(def.did) {
|
if self.tcx.has_typeck_results(def.did) {
|
||||||
if let Some(error_reported) = self.tcx.typeck_opt_const_arg(def).tainted_by_errors {
|
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(Some(instance)) => Ok(instance),
|
||||||
Ok(None) => throw_inval!(TooGeneric),
|
Ok(None) => throw_inval!(TooGeneric),
|
||||||
|
|
||||||
// FIXME(eddyb) this could be a bit more specific than `TypeckError`.
|
// FIXME(eddyb) this could be a bit more specific than `AlreadyReported`.
|
||||||
Err(error_reported) => throw_inval!(TypeckError(error_reported)),
|
Err(error_reported) => throw_inval!(AlreadyReported(error_reported)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
use super::validity::RefTracking;
|
use super::validity::RefTracking;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
|
use rustc_errors::ErrorReported;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_middle::mir::interpret::InterpResult;
|
use rustc_middle::mir::interpret::InterpResult;
|
||||||
use rustc_middle::ty::{self, layout::TyAndLayout, Ty};
|
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.
|
/// 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
|
/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
|
||||||
/// are hard errors.
|
/// are hard errors.
|
||||||
|
#[tracing::instrument(skip(ecx))]
|
||||||
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
||||||
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
ecx: &mut InterpCx<'mir, 'tcx, M>,
|
||||||
intern_kind: InternKind,
|
intern_kind: InternKind,
|
||||||
ret: MPlaceTy<'tcx>,
|
ret: MPlaceTy<'tcx>,
|
||||||
) where
|
) -> Result<(), ErrorReported>
|
||||||
|
where
|
||||||
'tcx: 'mir,
|
'tcx: 'mir,
|
||||||
{
|
{
|
||||||
let tcx = ecx.tcx;
|
let tcx = ecx.tcx;
|
||||||
|
@ -405,12 +408,14 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
|
||||||
// Codegen does not like dangling pointers, and generally `tcx` assumes that
|
// Codegen does not like dangling pointers, and generally `tcx` assumes that
|
||||||
// all allocations referenced anywhere actually exist. So, make sure we error here.
|
// 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");
|
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() {
|
} 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
|
// 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.
|
// marked as dangling by local memory. That should be impossible.
|
||||||
span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
|
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> {
|
impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
|
|
|
@ -550,7 +550,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
// Early-return cases.
|
// Early-return cases.
|
||||||
let val_val = match val.val {
|
let val_val = match val.val {
|
||||||
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
|
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) => {
|
ty::ConstKind::Unevaluated(def, substs, promoted) => {
|
||||||
let instance = self.resolve(def, substs)?;
|
let instance = self.resolve(def, substs)?;
|
||||||
return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into());
|
return Ok(self.eval_to_allocation(GlobalId { instance, promoted })?.into());
|
||||||
|
|
10
src/test/ui/consts/issue-78655.rs
Normal file
10
src/test/ui/consts/issue-78655.rs
Normal file
|
@ -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
|
||||||
|
}
|
30
src/test/ui/consts/issue-78655.stderr
Normal file
30
src/test/ui/consts/issue-78655.stderr
Normal file
|
@ -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`.
|
Loading…
Add table
Add a link
Reference in a new issue