give extra context to ABI mismatch errors
This commit is contained in:
parent
897a65804d
commit
f993ddc079
@ -482,6 +482,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||||||
use UndefinedBehaviorInfo::*;
|
use UndefinedBehaviorInfo::*;
|
||||||
match self {
|
match self {
|
||||||
Ub(msg) => msg.clone().into(),
|
Ub(msg) => msg.clone().into(),
|
||||||
|
Custom(x) => (x.msg)(),
|
||||||
|
ValidationError(e) => e.diagnostic_message(),
|
||||||
|
|
||||||
Unreachable => const_eval_unreachable,
|
Unreachable => const_eval_unreachable,
|
||||||
BoundsCheckFailed { .. } => const_eval_bounds_check_failed,
|
BoundsCheckFailed { .. } => const_eval_bounds_check_failed,
|
||||||
DivisionByZero => const_eval_division_by_zero,
|
DivisionByZero => const_eval_division_by_zero,
|
||||||
@ -513,8 +516,8 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||||||
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
|
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
|
||||||
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
|
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
|
||||||
UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
|
UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
|
||||||
ValidationError(e) => e.diagnostic_message(),
|
AbiMismatchArgument { .. } => const_eval_incompatible_types,
|
||||||
Custom(x) => (x.msg)(),
|
AbiMismatchReturn { .. } => const_eval_incompatible_return_types,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,8 +528,15 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||||||
) {
|
) {
|
||||||
use UndefinedBehaviorInfo::*;
|
use UndefinedBehaviorInfo::*;
|
||||||
match self {
|
match self {
|
||||||
Ub(_)
|
Ub(_) => {}
|
||||||
| Unreachable
|
Custom(custom) => {
|
||||||
|
(custom.add_args)(&mut |name, value| {
|
||||||
|
builder.set_arg(name, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ValidationError(e) => e.add_args(handler, builder),
|
||||||
|
|
||||||
|
Unreachable
|
||||||
| DivisionByZero
|
| DivisionByZero
|
||||||
| RemainderByZero
|
| RemainderByZero
|
||||||
| DivisionOverflow
|
| DivisionOverflow
|
||||||
@ -593,11 +603,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||||||
builder.set_arg("target_size", info.target_size);
|
builder.set_arg("target_size", info.target_size);
|
||||||
builder.set_arg("data_size", info.data_size);
|
builder.set_arg("data_size", info.data_size);
|
||||||
}
|
}
|
||||||
ValidationError(e) => e.add_args(handler, builder),
|
AbiMismatchArgument { caller_ty, callee_ty }
|
||||||
Custom(custom) => {
|
| AbiMismatchReturn { caller_ty, callee_ty } => {
|
||||||
(custom.add_args)(&mut |name, value| {
|
builder.set_arg("caller_ty", caller_ty.to_string());
|
||||||
builder.set_arg(name, value);
|
builder.set_arg("callee_ty", callee_ty.to_string());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,13 +439,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
|
|
||||||
// Check compatibility
|
// Check compatibility
|
||||||
if !self.check_argument_compat(caller_abi, callee_abi)? {
|
if !self.check_argument_compat(caller_abi, callee_abi)? {
|
||||||
let callee_ty = format!("{}", callee_ty);
|
throw_ub!(AbiMismatchArgument {
|
||||||
let caller_ty = format!("{}", caller_arg.layout().ty);
|
caller_ty: caller_abi.layout.ty,
|
||||||
throw_ub_custom!(
|
callee_ty: callee_abi.layout.ty
|
||||||
fluent::const_eval_incompatible_types,
|
});
|
||||||
callee_ty = callee_ty,
|
|
||||||
caller_ty = caller_ty,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// We work with a copy of the argument for now; if this is in-place argument passing, we
|
// We work with a copy of the argument for now; if this is in-place argument passing, we
|
||||||
// will later protect the source it comes from. This means the callee cannot observe if we
|
// will later protect the source it comes from. This means the callee cannot observe if we
|
||||||
@ -712,13 +709,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
// Don't forget to check the return type!
|
// Don't forget to check the return type!
|
||||||
if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
|
if !self.check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret)? {
|
||||||
let callee_ty = format!("{}", callee_fn_abi.ret.layout.ty);
|
throw_ub!(AbiMismatchReturn {
|
||||||
let caller_ty = format!("{}", caller_fn_abi.ret.layout.ty);
|
caller_ty: caller_fn_abi.ret.layout.ty,
|
||||||
throw_ub_custom!(
|
callee_ty: callee_fn_abi.ret.layout.ty
|
||||||
fluent::const_eval_incompatible_return_types,
|
});
|
||||||
callee_ty = callee_ty,
|
|
||||||
caller_ty = caller_ty,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
// Ensure the return place is aligned and dereferenceable, and protect it for
|
// Ensure the return place is aligned and dereferenceable, and protect it for
|
||||||
// in-place return value passing.
|
// in-place return value passing.
|
||||||
|
@ -255,9 +255,16 @@ impl_into_diagnostic_arg_through_debug! {
|
|||||||
|
|
||||||
/// Error information for when the program caused Undefined Behavior.
|
/// Error information for when the program caused Undefined Behavior.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum UndefinedBehaviorInfo<'a> {
|
pub enum UndefinedBehaviorInfo<'tcx> {
|
||||||
/// Free-form case. Only for errors that are never caught! Used by miri
|
/// Free-form case. Only for errors that are never caught! Used by miri
|
||||||
Ub(String),
|
Ub(String),
|
||||||
|
// FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
|
||||||
|
// dispatched
|
||||||
|
/// A custom (free-form) fluent-translated error, created by `err_ub_custom!`.
|
||||||
|
Custom(crate::error::CustomSubdiagnostic<'tcx>),
|
||||||
|
/// Validation error.
|
||||||
|
ValidationError(ValidationErrorInfo<'tcx>),
|
||||||
|
|
||||||
/// Unreachable code was executed.
|
/// Unreachable code was executed.
|
||||||
Unreachable,
|
Unreachable,
|
||||||
/// A slice/array index projection went out-of-bounds.
|
/// A slice/array index projection went out-of-bounds.
|
||||||
@ -319,12 +326,10 @@ pub enum UndefinedBehaviorInfo<'a> {
|
|||||||
UninhabitedEnumVariantWritten(VariantIdx),
|
UninhabitedEnumVariantWritten(VariantIdx),
|
||||||
/// An uninhabited enum variant is projected.
|
/// An uninhabited enum variant is projected.
|
||||||
UninhabitedEnumVariantRead(VariantIdx),
|
UninhabitedEnumVariantRead(VariantIdx),
|
||||||
/// Validation error.
|
/// ABI-incompatible argument types.
|
||||||
ValidationError(ValidationErrorInfo<'a>),
|
AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
|
||||||
// FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
|
/// ABI-incompatible return types.
|
||||||
// dispatched
|
AbiMismatchReturn { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
|
||||||
/// A custom (free-form) error, created by `err_ub_custom!`.
|
|
||||||
Custom(crate::error::CustomSubdiagnostic<'a>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
@ -199,6 +199,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
e: InterpErrorInfo<'tcx>,
|
e: InterpErrorInfo<'tcx>,
|
||||||
) -> Option<(i64, bool)> {
|
) -> Option<(i64, bool)> {
|
||||||
use InterpError::*;
|
use InterpError::*;
|
||||||
|
use UndefinedBehaviorInfo::*;
|
||||||
|
|
||||||
let mut msg = vec![];
|
let mut msg = vec![];
|
||||||
|
|
||||||
@ -271,7 +272,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
(title, helps)
|
(title, helps)
|
||||||
} else {
|
} else {
|
||||||
let title = match e.kind() {
|
let title = match e.kind() {
|
||||||
UndefinedBehavior(UndefinedBehaviorInfo::ValidationError(validation_err))
|
UndefinedBehavior(ValidationError(validation_err))
|
||||||
if matches!(
|
if matches!(
|
||||||
validation_err.kind,
|
validation_err.kind,
|
||||||
ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer
|
ValidationErrorKind::PointerAsInt { .. } | ValidationErrorKind::PartialPointer
|
||||||
@ -299,7 +300,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
let helps = match e.kind() {
|
let helps = match e.kind() {
|
||||||
Unsupported(_) =>
|
Unsupported(_) =>
|
||||||
vec![(None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"))],
|
vec![(None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"))],
|
||||||
UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. })
|
UndefinedBehavior(AlignmentCheckFailed { .. })
|
||||||
if ecx.machine.check_alignment == AlignmentCheck::Symbolic
|
if ecx.machine.check_alignment == AlignmentCheck::Symbolic
|
||||||
=>
|
=>
|
||||||
vec![
|
vec![
|
||||||
@ -311,13 +312,20 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
|
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
|
||||||
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
|
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
|
||||||
];
|
];
|
||||||
if let UndefinedBehaviorInfo::PointerUseAfterFree(alloc_id, _) | UndefinedBehaviorInfo::PointerOutOfBounds { alloc_id, .. } = info {
|
match info {
|
||||||
if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
|
PointerUseAfterFree(alloc_id, _) | PointerOutOfBounds { alloc_id, .. } => {
|
||||||
helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
|
if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
|
||||||
|
helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
|
||||||
|
}
|
||||||
|
if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
|
||||||
|
helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
|
AbiMismatchArgument { .. } | AbiMismatchReturn { .. } => {
|
||||||
helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
|
helps.push((None, format!("this means these two types are not *guaranteed* to be ABI-compatible across all targets")));
|
||||||
|
helps.push((None, format!("if you think this code should be accepted anyway, please report an issue")));
|
||||||
}
|
}
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
helps
|
helps
|
||||||
}
|
}
|
||||||
@ -339,7 +347,7 @@ pub fn report_error<'tcx, 'mir>(
|
|||||||
// We want to dump the allocation if this is `InvalidUninitBytes`. Since `format_error` consumes `e`, we compute the outut early.
|
// We want to dump the allocation if this is `InvalidUninitBytes`. Since `format_error` consumes `e`, we compute the outut early.
|
||||||
let mut extra = String::new();
|
let mut extra = String::new();
|
||||||
match e.kind() {
|
match e.kind() {
|
||||||
UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
|
UndefinedBehavior(InvalidUninitBytes(Some((alloc_id, access)))) => {
|
||||||
writeln!(
|
writeln!(
|
||||||
extra,
|
extra,
|
||||||
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
|
"Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
|
||||||
|
@ -6,6 +6,8 @@ LL | g(Default::default())
|
|||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
|
||||||
|
= help: if you think this code should be accepted anyway, please report an issue
|
||||||
= note: BACKTRACE:
|
= note: BACKTRACE:
|
||||||
= note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
|
= note: inside `main` at $DIR/abi_mismatch_array_vs_struct.rs:LL:CC
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ LL | g(42)
|
|||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
|
||||||
|
= help: if you think this code should be accepted anyway, please report an issue
|
||||||
= note: BACKTRACE:
|
= note: BACKTRACE:
|
||||||
= note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC
|
= note: inside `main` at $DIR/abi_mismatch_int_vs_float.rs:LL:CC
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ LL | g(&42 as *const i32)
|
|||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
|
||||||
|
= help: if you think this code should be accepted anyway, please report an issue
|
||||||
= note: BACKTRACE:
|
= note: BACKTRACE:
|
||||||
= note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC
|
= note: inside `main` at $DIR/abi_mismatch_raw_pointer.rs:LL:CC
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ LL | g()
|
|||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
|
||||||
|
= help: if you think this code should be accepted anyway, please report an issue
|
||||||
= note: BACKTRACE:
|
= note: BACKTRACE:
|
||||||
= note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC
|
= note: inside `main` at $DIR/abi_mismatch_return_type.rs:LL:CC
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ LL | g(42)
|
|||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
|
||||||
|
= help: if you think this code should be accepted anyway, please report an issue
|
||||||
= note: BACKTRACE:
|
= note: BACKTRACE:
|
||||||
= note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC
|
= note: inside `main` at $DIR/abi_mismatch_simple.rs:LL:CC
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ LL | g(Default::default())
|
|||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= help: this means these two types are not *guaranteed* to be ABI-compatible across all targets
|
||||||
|
= help: if you think this code should be accepted anyway, please report an issue
|
||||||
= note: BACKTRACE:
|
= note: BACKTRACE:
|
||||||
= note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC
|
= note: inside `main` at $DIR/abi_mismatch_vector.rs:LL:CC
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user