Add some more specific checks to the MIR validator

None of the `PointerCoercion`s had any, so while there's probably more that could be done here, hopefully these are better than the previous nothing.
This commit is contained in:
Scott McMurray 2024-06-01 02:36:55 -07:00
parent 0038c02103
commit 11d6f18bf6

View File

@ -8,6 +8,7 @@
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{
self, CoroutineArgsExt, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance,
};
@ -1134,9 +1135,76 @@ macro_rules! check_kinds {
// FIXME(dyn-star): make sure nothing needs to be done here.
}
// FIXME: Add Checks for these
CastKind::PointerWithExposedProvenance
| CastKind::PointerExposeProvenance
| CastKind::PointerCoercion(_) => {}
CastKind::PointerWithExposedProvenance | CastKind::PointerExposeProvenance => {}
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
// FIXME: check signature compatibility.
check_kinds!(
op_ty,
"CastKind::{kind:?} input must be a fn item, not {:?}",
ty::FnDef(..)
);
check_kinds!(
target_type,
"CastKind::{kind:?} output must be a fn pointer, not {:?}",
ty::FnPtr(..)
);
}
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
// FIXME: check safety and signature compatibility.
check_kinds!(
op_ty,
"CastKind::{kind:?} input must be a fn pointer, not {:?}",
ty::FnPtr(..)
);
check_kinds!(
target_type,
"CastKind::{kind:?} output must be a fn pointer, not {:?}",
ty::FnPtr(..)
);
}
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..)) => {
// FIXME: check safety, captures, and signature compatibility.
check_kinds!(
op_ty,
"CastKind::{kind:?} input must be a closure, not {:?}",
ty::Closure(..)
);
check_kinds!(
target_type,
"CastKind::{kind:?} output must be a fn pointer, not {:?}",
ty::FnPtr(..)
);
}
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
// FIXME: check same pointee?
check_kinds!(
op_ty,
"CastKind::{kind:?} input must be a raw mut pointer, not {:?}",
ty::RawPtr(_, Mutability::Mut)
);
check_kinds!(
target_type,
"CastKind::{kind:?} output must be a raw const pointer, not {:?}",
ty::RawPtr(_, Mutability::Not)
);
}
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
// FIXME: Check pointee types
check_kinds!(
op_ty,
"CastKind::{kind:?} input must be a raw pointer, not {:?}",
ty::RawPtr(..)
);
check_kinds!(
target_type,
"CastKind::{kind:?} output must be a raw pointer, not {:?}",
ty::RawPtr(..)
);
}
CastKind::PointerCoercion(PointerCoercion::Unsize) => {
// This is used for all `CoerceUnsized` types,
// not just pointers/references, so is hard to check.
}
CastKind::IntToInt | CastKind::IntToFloat => {
let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
let target_valid = target_type.is_numeric() || target_type.is_char();
@ -1147,10 +1215,29 @@ macro_rules! check_kinds {
);
}
}
CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
if !(op_ty.is_any_ptr() && target_type.is_unsafe_ptr()) {
self.fail(location, "Can't cast {op_ty} into 'Ptr'");
}
CastKind::FnPtrToPtr => {
check_kinds!(
op_ty,
"CastKind::{kind:?} input must be a fn pointer, not {:?}",
ty::FnPtr(..)
);
check_kinds!(
target_type,
"CastKind::{kind:?} output must be a raw pointer, not {:?}",
ty::RawPtr(..)
);
}
CastKind::PtrToPtr => {
check_kinds!(
op_ty,
"CastKind::{kind:?} input must be a raw pointer, not {:?}",
ty::RawPtr(..)
);
check_kinds!(
target_type,
"CastKind::{kind:?} output must be a raw pointer, not {:?}",
ty::RawPtr(..)
);
}
CastKind::FloatToFloat | CastKind::FloatToInt => {
if !op_ty.is_floating_point() || !target_type.is_numeric() {