diff options
Diffstat (limited to 'compiler/rustc_const_eval/src')
| -rw-r--r-- | compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/intern.rs | 45 | ||||
| -rw-r--r-- | compiler/rustc_const_eval/src/interpret/mod.rs | 1 |
3 files changed, 52 insertions, 23 deletions
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 4283ebc99d2..a3e0ea5c1e2 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -10,20 +10,21 @@ use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::Span; use rustc_target::abi::{self, Abi}; use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter}; use crate::const_eval::CheckAlignment; -use crate::errors; use crate::errors::ConstEvalError; -use crate::interpret::eval_nullary_intrinsic; +use crate::errors::{self, DanglingPtrInFinal}; use crate::interpret::{ create_static_alloc, intern_const_alloc_recursive, CtfeValidationMode, GlobalId, Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, StackPopCleanup, }; +use crate::interpret::{eval_nullary_intrinsic, InternResult}; use crate::CTRL_C_RECEIVED; // Returns a pointer to where the result lives @@ -89,11 +90,33 @@ fn eval_body_using_ecx<'mir, 'tcx, R: InterpretationResult<'tcx>>( } // Intern the result - intern_const_alloc_recursive(ecx, intern_kind, &ret)?; + let intern_result = intern_const_alloc_recursive(ecx, intern_kind, &ret); // Since evaluation had no errors, validate the resulting constant. const_validate_mplace(&ecx, &ret, cid)?; + // Only report this after validation, as validaiton produces much better diagnostics. + // FIXME: ensure validation always reports this and stop making interning care about it. + + if let Err(InternResult { found_bad_mutable_pointer, found_dangling_pointer }) = intern_result { + if found_dangling_pointer { + return Err(ecx + .tcx + .dcx() + .emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) + .into()); + } else if found_bad_mutable_pointer { + // only report mutable pointers if there were no dangling pointers + let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }; + ecx.tcx.emit_node_span_lint( + lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, + ecx.best_lint_scope(), + err_diag.span, + err_diag, + ) + } + } + Ok(R::make_result(ret, ecx)) } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index d0f0190fea7..3828351db0a 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -16,19 +16,17 @@ use hir::def::DefKind; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir::interpret::{ConstAllocation, CtfeProvenance, InterpResult}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::TyAndLayout; -use rustc_session::lint; use rustc_span::def_id::LocalDefId; use rustc_span::sym; use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy}; use crate::const_eval; -use crate::errors::{DanglingPtrInFinal, MutablePtrInFinal, NestedStaticInThreadLocal}; +use crate::errors::NestedStaticInThreadLocal; pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< 'mir, @@ -134,6 +132,19 @@ pub enum InternKind { Promoted, } +#[derive(Default, Debug)] +pub struct InternResult { + pub found_bad_mutable_pointer: bool, + pub found_dangling_pointer: bool, +} + +impl InternResult { + fn has_errors(&self) -> bool { + let Self { found_bad_mutable_pointer, found_dangling_pointer } = *self; + found_bad_mutable_pointer || found_dangling_pointer + } +} + /// Intern `ret` and everything it references. /// /// This *cannot raise an interpreter error*. Doing so is left to validation, which @@ -149,7 +160,7 @@ pub fn intern_const_alloc_recursive< ecx: &mut InterpCx<'mir, 'tcx, M>, intern_kind: InternKind, ret: &MPlaceTy<'tcx>, -) -> Result<(), ErrorGuaranteed> { +) -> Result<(), InternResult> { // We are interning recursively, and for mutability we are distinguishing the "root" allocation // that we are starting in, and all other allocations that we are encountering recursively. let (base_mutability, inner_mutability, is_static) = match intern_kind { @@ -201,7 +212,7 @@ pub fn intern_const_alloc_recursive< // Whether we encountered a bad mutable pointer. // We want to first report "dangling" and then "mutable", so we need to delay reporting these // errors. - let mut found_bad_mutable_pointer = false; + let mut result = InternResult::default(); // Keep interning as long as there are things to intern. // We show errors if there are dangling pointers, or mutable pointers in immutable contexts @@ -251,7 +262,7 @@ pub fn intern_const_alloc_recursive< // on the promotion analysis not screwing up to ensure that it is sound to intern // promoteds as immutable. trace!("found bad mutable pointer"); - found_bad_mutable_pointer = true; + result.found_bad_mutable_pointer = true; } if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { // Already interned. @@ -269,21 +280,15 @@ pub fn intern_const_alloc_recursive< // pointers before deciding which allocations can be made immutable; but for now we are // okay with losing some potential for immutability here. This can anyway only affect // `static mut`. - todo.extend(intern_shallow(ecx, alloc_id, inner_mutability).map_err(|()| { - ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) - })?); - } - if found_bad_mutable_pointer { - let err_diag = MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }; - ecx.tcx.emit_node_span_lint( - lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, - ecx.best_lint_scope(), - err_diag.span, - err_diag, - ) + match intern_shallow(ecx, alloc_id, inner_mutability) { + Ok(nested) => todo.extend(nested), + Err(()) => { + ecx.tcx.dcx().delayed_bug("found dangling pointer during const interning"); + result.found_dangling_pointer = true + } + } } - - Ok(()) + if result.has_errors() { Err(result) } else { Ok(()) } } /// Intern `ret`. This function assumes that `ret` references no other allocation. diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 474d35b2aa3..7ede90ad13f 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -23,6 +23,7 @@ pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in pub use self::eval_context::{format_interp_error, Frame, FrameInfo, InterpCx, StackPopCleanup}; pub use self::intern::{ intern_const_alloc_for_constprop, intern_const_alloc_recursive, HasStaticRootDefId, InternKind, + InternResult, }; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; |
