Skip to content

add const_make_global; err for const_allocate ptrs if didn't call #143595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ const_eval_const_context = {$kind ->
*[other] {""}
}

const_eval_const_heap_ptr_in_final = encountered `const_allocate` pointer in final value that was not made global
.note = use `const_make_global` to make allocated pointers immutable before returning

const_eval_const_make_global_ptr_already_made_global = attempting to call `const_make_global` twice on the same allocation {$alloc}

const_eval_const_make_global_ptr_is_non_heap = pointer passed to `const_make_global` does not point to a heap allocation: {$ptr}

const_eval_const_make_global_with_dangling_ptr = pointer passed to `const_make_global` is dangling: {$ptr}

const_eval_const_make_global_with_offset = making {$ptr} global which does not point to the beginning of an object

const_eval_copy_nonoverlapping_overlapping =
`copy_nonoverlapping` called on overlapping ranges

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_const_eval/src/const_eval/dummy_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ impl HasStaticRootDefId for DummyMachine {

impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
interpret::compile_time_machine!(<'tcx>);
type MemoryKind = !;
const PANIC_ON_ALLOC_FAIL: bool = true;

// We want to just eval random consts in the program, so `eval_mir_const` can fail.
Expand Down
36 changes: 32 additions & 4 deletions compiler/rustc_const_eval/src/const_eval/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::mem;

use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg};
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo};
use rustc_middle::mir::interpret::{AllocId, Provenance, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::{ConstInt, TyCtxt};
Expand All @@ -11,8 +11,8 @@ use rustc_span::{Span, Symbol};
use super::CompileTimeMachine;
use crate::errors::{self, FrameNote, ReportErrorExt};
use crate::interpret::{
ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType, err_inval,
err_machine_stop,
CtfeProvenance, ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType,
Pointer, err_inval, err_machine_stop,
};

/// The CTFE machine has some custom error kinds.
Expand All @@ -22,8 +22,22 @@ pub enum ConstEvalErrKind {
ModifiedGlobal,
RecursiveStatic,
AssertFailure(AssertKind<ConstInt>),
Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
Panic {
msg: Symbol,
line: u32,
col: u32,
file: Symbol,
},
WriteThroughImmutablePointer,
/// Called `const_make_global` twice.
ConstMakeGlobalPtrAlreadyMadeGlobal(AllocId),
/// Called `const_make_global` on a non-heap pointer.
ConstMakeGlobalPtrIsNonHeap(Pointer<Option<CtfeProvenance>>),
/// Called `const_make_global` on a dangling pointer.
ConstMakeGlobalWithDanglingPtr(Pointer<Option<CtfeProvenance>>),
/// Called `const_make_global` on a pointer that does not start at the
/// beginning of an object.
ConstMakeGlobalWithOffset(Pointer<Option<CtfeProvenance>>),
}

impl MachineStopType for ConstEvalErrKind {
Expand All @@ -38,6 +52,12 @@ impl MachineStopType for ConstEvalErrKind {
RecursiveStatic => const_eval_recursive_static,
AssertFailure(x) => x.diagnostic_message(),
WriteThroughImmutablePointer => const_eval_write_through_immutable_pointer,
ConstMakeGlobalPtrAlreadyMadeGlobal { .. } => {
const_eval_const_make_global_ptr_already_made_global
}
ConstMakeGlobalPtrIsNonHeap(_) => const_eval_const_make_global_ptr_is_non_heap,
ConstMakeGlobalWithDanglingPtr(_) => const_eval_const_make_global_with_dangling_ptr,
ConstMakeGlobalWithOffset(_) => const_eval_const_make_global_with_offset,
}
}
fn add_args(self: Box<Self>, adder: &mut dyn FnMut(DiagArgName, DiagArgValue)) {
Expand All @@ -51,6 +71,14 @@ impl MachineStopType for ConstEvalErrKind {
Panic { msg, .. } => {
adder("msg".into(), msg.into_diag_arg(&mut None));
}
ConstMakeGlobalPtrIsNonHeap(ptr)
| ConstMakeGlobalWithOffset(ptr)
| ConstMakeGlobalWithDanglingPtr(ptr) => {
adder("ptr".into(), format!("{ptr:?}").into_diag_arg(&mut None));
}
ConstMakeGlobalPtrAlreadyMadeGlobal(alloc) => {
adder("alloc".into(), alloc.into_diag_arg(&mut None));
}
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use tracing::{debug, instrument, trace};
use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine};
use crate::const_eval::CheckAlignment;
use crate::interpret::{
CtfeValidationMode, GlobalId, Immediate, InternKind, InternResult, InterpCx, InterpErrorKind,
CtfeValidationMode, GlobalId, Immediate, InternError, InternKind, InterpCx, InterpErrorKind,
InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, ReturnContinuation, create_static_alloc,
intern_const_alloc_recursive, interp_ok, throw_exhaust,
};
Expand Down Expand Up @@ -93,25 +93,30 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
// 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.
// Only report this after validation, as validation produces much better diagnostics.
// FIXME: ensure validation always reports this and stop making interning care about it.

match intern_result {
Ok(()) => {}
Err(InternResult::FoundDanglingPointer) => {
Err(InternError::DanglingPointer) => {
throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
ecx.tcx
.dcx()
.emit_err(errors::DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
)));
}
Err(InternResult::FoundBadMutablePointer) => {
Err(InternError::BadMutablePointer) => {
throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
ecx.tcx
.dcx()
.emit_err(errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }),
)));
}
Err(InternError::ConstAllocNotGlobal) => {
throw_inval!(AlreadyReported(ReportedErrorInfo::non_const_eval_error(
ecx.tcx.dcx().emit_err(errors::ConstHeapPtrInFinal { span: ecx.tcx.span }),
)));
}
}

interp_ok(R::make_result(ret, ecx))
Expand Down
25 changes: 18 additions & 7 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,19 @@ pub type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>;

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum MemoryKind {
Heap,
Heap {
/// Indicates whether `make_global` was called on this allocation.
/// If this is `true`, the allocation must be immutable.
was_made_global: bool,
},
}

impl fmt::Display for MemoryKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MemoryKind::Heap => write!(f, "heap allocation"),
MemoryKind::Heap { was_made_global } => {
write!(f, "heap allocation{}", if *was_made_global { " (made global)" } else { "" })
}
}
}
}
Expand All @@ -184,7 +190,7 @@ impl interpret::MayLeak for MemoryKind {
#[inline(always)]
fn may_leak(self) -> bool {
match self {
MemoryKind::Heap => false,
MemoryKind::Heap { was_made_global } => was_made_global,
}
}
}
Expand Down Expand Up @@ -314,8 +320,6 @@ impl<'tcx> CompileTimeMachine<'tcx> {
impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
compile_time_machine!(<'tcx>);

type MemoryKind = MemoryKind;

const PANIC_ON_ALLOC_FAIL: bool = false; // will be raised as a proper error

#[inline(always)]
Expand Down Expand Up @@ -420,7 +424,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
let ptr = ecx.allocate_ptr(
Size::from_bytes(size),
align,
interpret::MemoryKind::Machine(MemoryKind::Heap),
interpret::MemoryKind::Machine(MemoryKind::Heap { was_made_global: false }),
AllocInit::Uninit,
)?;
ecx.write_pointer(ptr, dest)?;
Expand Down Expand Up @@ -453,10 +457,17 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.deallocate_ptr(
ptr,
Some((size, align)),
interpret::MemoryKind::Machine(MemoryKind::Heap),
interpret::MemoryKind::Machine(MemoryKind::Heap { was_made_global: false }),
)?;
}
}

sym::const_make_global => {
let ptr = ecx.read_pointer(&args[0])?;
ecx.make_const_heap_ptr_global(ptr)?;
ecx.write_pointer(ptr, dest)?;
}

// The intrinsic represents whether the value is known to the optimizer (LLVM).
// We're not doing any optimizations here, so there is no optimizer that could know the value.
// (We know the value here in the machine of course, but this is the runtime of that code,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ pub(crate) struct MutablePtrInFinal {
pub kind: InternKind,
}

#[derive(Diagnostic)]
#[diag(const_eval_const_heap_ptr_in_final)]
#[note]
pub(crate) struct ConstHeapPtrInFinal {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(const_eval_unstable_in_stable_exposed)]
pub(crate) struct UnstableInStableExposed {
Expand Down
Loading
Loading