1
Fork 0

Improve CTFE validation error message

This commit is contained in:
Rémy Rakic 2021-06-13 22:40:42 +02:00
parent fb3ea63d9b
commit 87ecf84c36
2 changed files with 22 additions and 12 deletions

View file

@ -256,7 +256,10 @@ pub enum UndefinedBehaviorInfo<'tcx> {
/// The value validity check found a problem. /// The value validity check found a problem.
/// Should only be thrown by `validity.rs` and always point out which part of the value /// Should only be thrown by `validity.rs` and always point out which part of the value
/// is the problem. /// is the problem.
ValidationFailure(String), ValidationFailure {
path: Option<String>,
msg: String,
},
/// Using a non-boolean `u8` as bool. /// Using a non-boolean `u8` as bool.
InvalidBool(u8), InvalidBool(u8),
/// Using a non-character `u32` as character. /// Using a non-character `u32` as character.
@ -331,7 +334,10 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
), ),
WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a), WriteToReadOnly(a) => write!(f, "writing to {} which is read-only", a),
DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a), DerefFunctionPointer(a) => write!(f, "accessing {} which contains a function", a),
ValidationFailure(ref err) => write!(f, "type validation failed: {}", err), ValidationFailure { path: None, msg } => write!(f, "type validation failed: {}", msg),
ValidationFailure { path: Some(path), msg } => {
write!(f, "type validation failed at {}: {}", path, msg)
}
InvalidBool(b) => { InvalidBool(b) => {
write!(f, "interpreting an invalid 8-bit value as a bool: 0x{:02x}", b) write!(f, "interpreting an invalid 8-bit value as a bool: 0x{:02x}", b)
} }
@ -499,13 +505,13 @@ impl fmt::Debug for InterpError<'_> {
} }
impl InterpError<'_> { impl InterpError<'_> {
/// Some errors to string formatting even if the error is never printed. /// Some errors do string formatting even if the error is never printed.
/// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors, /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
/// so this method lets us detect them and `bug!` on unexpected errors. /// so this method lets us detect them and `bug!` on unexpected errors.
pub fn formatted_string(&self) -> bool { pub fn formatted_string(&self) -> bool {
match self { match self {
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_)) | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true, | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true,
_ => false, _ => false,
} }

View file

@ -26,23 +26,27 @@ use super::{
macro_rules! throw_validation_failure { macro_rules! throw_validation_failure {
($where:expr, { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )?) => {{ ($where:expr, { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )?) => {{
let msg = rustc_middle::ty::print::with_no_trimmed_paths(|| { let (path, msg) = rustc_middle::ty::print::with_no_trimmed_paths(|| {
let mut msg = String::new(); let mut msg = String::new();
msg.push_str("encountered "); msg.push_str("encountered ");
write!(&mut msg, $($what_fmt),+).unwrap(); write!(&mut msg, $($what_fmt),+).unwrap();
let where_ = &$where;
if !where_.is_empty() {
msg.push_str(" at ");
write_path(&mut msg, where_);
}
$( $(
msg.push_str(", but expected "); msg.push_str(", but expected ");
write!(&mut msg, $($expected_fmt),+).unwrap(); write!(&mut msg, $($expected_fmt),+).unwrap();
)? )?
msg let where_ = &$where;
let path = if !where_.is_empty() {
let mut path = String::new();
write_path(&mut path, where_);
Some(path)
} else {
None
};
(path, msg)
}); });
throw_ub!(ValidationFailure(msg)) throw_ub!(ValidationFailure { path, msg })
}}; }};
} }