Move alignment failure error reporting to machine
This commit is contained in:
parent
d66824dbc4
commit
d9d92ed7da
6 changed files with 78 additions and 44 deletions
|
@ -1,9 +1,10 @@
|
|||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::{LangItem, CRATE_HIR_ID};
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::PointerArithmetic;
|
||||
use rustc_middle::mir::interpret::{PointerArithmetic, UndefinedBehaviorInfo};
|
||||
use rustc_middle::ty::layout::FnAbiOf;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::lint::builtin::INVALID_ALIGNMENT;
|
||||
use std::borrow::Borrow;
|
||||
use std::hash::Hash;
|
||||
use std::ops::ControlFlow;
|
||||
|
@ -338,6 +339,40 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
ecx.tcx.sess.opts.unstable_opts.extra_const_ub_checks
|
||||
}
|
||||
|
||||
fn alignment_check_failed(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
has: Align,
|
||||
required: Align,
|
||||
check: CheckAlignment,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
match check {
|
||||
CheckAlignment::Error => {
|
||||
throw_ub!(AlignmentCheckFailed { has, required })
|
||||
}
|
||||
CheckAlignment::No => span_bug!(
|
||||
ecx.cur_span(),
|
||||
"`alignment_check_failed` called when no alignment check requested"
|
||||
),
|
||||
CheckAlignment::FutureIncompat => ecx.tcx.struct_span_lint_hir(
|
||||
INVALID_ALIGNMENT,
|
||||
ecx.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
|
||||
ecx.cur_span(),
|
||||
UndefinedBehaviorInfo::AlignmentCheckFailed { has, required }.to_string(),
|
||||
|db| {
|
||||
let mut stacktrace = ecx.generate_stacktrace();
|
||||
// Filter out `requires_caller_location` frames.
|
||||
stacktrace
|
||||
.retain(|frame| !frame.instance.def.requires_caller_location(*ecx.tcx));
|
||||
for frame in stacktrace {
|
||||
db.span_label(frame.span, format!("inside `{}`", frame.instance));
|
||||
}
|
||||
db
|
||||
},
|
||||
),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_mir(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
instance: ty::InstanceDef<'tcx>,
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
|||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::Size;
|
||||
use rustc_target::abi::{Align, Size};
|
||||
use rustc_target::spec::abi::Abi as CallAbi;
|
||||
|
||||
use crate::const_eval::CheckAlignment;
|
||||
|
@ -132,6 +132,13 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||
/// If this returns true, Provenance::OFFSET_IS_ADDR must be true.
|
||||
fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
||||
|
||||
fn alignment_check_failed(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
has: Align,
|
||||
required: Align,
|
||||
check: CheckAlignment,
|
||||
) -> InterpResult<'tcx, ()>;
|
||||
|
||||
/// Whether to enforce the validity invariant
|
||||
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool;
|
||||
|
||||
|
|
|
@ -14,11 +14,8 @@ use std::ptr;
|
|||
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_middle::mir::display_allocation;
|
||||
use rustc_middle::mir::interpret::UndefinedBehaviorInfo;
|
||||
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
|
||||
use rustc_session::lint::builtin::INVALID_ALIGNMENT;
|
||||
use rustc_target::abi::{Align, HasDataLayout, Size};
|
||||
|
||||
use crate::const_eval::CheckAlignment;
|
||||
|
@ -448,7 +445,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
} else {
|
||||
// Check allocation alignment and offset alignment.
|
||||
if alloc_align.bytes() < align.bytes() {
|
||||
self.alignment_check_failed(alloc_align, align, check)?;
|
||||
M::alignment_check_failed(self, alloc_align, align, check)?;
|
||||
}
|
||||
self.check_offset_align(offset.bytes(), align, check)?;
|
||||
}
|
||||
|
@ -472,43 +469,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
} else {
|
||||
// The biggest power of two through which `offset` is divisible.
|
||||
let offset_pow2 = 1 << offset.trailing_zeros();
|
||||
self.alignment_check_failed(Align::from_bytes(offset_pow2).unwrap(), align, check)
|
||||
M::alignment_check_failed(self, Align::from_bytes(offset_pow2).unwrap(), align, check)
|
||||
}
|
||||
}
|
||||
|
||||
fn alignment_check_failed(
|
||||
&self,
|
||||
has: Align,
|
||||
required: Align,
|
||||
check: CheckAlignment,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
match check {
|
||||
CheckAlignment::Error => {
|
||||
throw_ub!(AlignmentCheckFailed { has, required })
|
||||
}
|
||||
CheckAlignment::No => span_bug!(
|
||||
self.cur_span(),
|
||||
"`alignment_check_failed` called when no alignment check requested"
|
||||
),
|
||||
CheckAlignment::FutureIncompat => self.tcx.struct_span_lint_hir(
|
||||
INVALID_ALIGNMENT,
|
||||
self.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
|
||||
self.cur_span(),
|
||||
UndefinedBehaviorInfo::AlignmentCheckFailed { has, required }.to_string(),
|
||||
|db| {
|
||||
let mut stacktrace = self.generate_stacktrace();
|
||||
// Filter out `requires_caller_location` frames.
|
||||
stacktrace
|
||||
.retain(|frame| !frame.instance.def.requires_caller_location(*self.tcx));
|
||||
for frame in stacktrace {
|
||||
db.span_label(frame.span, format!("inside `{}`", frame.instance));
|
||||
}
|
||||
db
|
||||
},
|
||||
),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocation accessors
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue