Rollup merge of #78742 - vn-ki:fix-issue-78655, r=oli-obk
make intern_const_alloc_recursive return error fix #78655 r? ``@oli-obk``
This commit is contained in:
commit
5ffccc4dfa
11 changed files with 66 additions and 26 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -469,7 +469,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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,8 +525,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> {
|
||||||
|
|
|
@ -544,7 +544,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());
|
||||||
|
|
|
@ -6,7 +6,7 @@ union Foo<'a> {
|
||||||
long_live_the_unit: &'static (),
|
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
|
//~^ ERROR encountered dangling pointer in final constant
|
||||||
let y = ();
|
let y = ();
|
||||||
unsafe { Foo { y: &y }.long_live_the_unit }
|
unsafe { Foo { y: &y }.long_live_the_unit }
|
||||||
|
|
|
@ -8,18 +8,5 @@ LL | | unsafe { Foo { y: &y }.long_live_the_unit }
|
||||||
LL | | };
|
LL | | };
|
||||||
| |__^
|
| |__^
|
||||||
|
|
||||||
error[E0080]: it is undefined behavior to use this value
|
error: aborting due to previous error
|
||||||
--> $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 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0080`.
|
|
||||||
|
|
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