about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee <46493976+workingjubilee@users.noreply.github.com>2024-06-02 05:06:48 -0700
committerGitHub <noreply@github.com>2024-06-02 05:06:48 -0700
commit30dc2bafc878eec948cdc4c8bf992708719f1d16 (patch)
tree9463d69e1338e1be2de56584c34de7b76f5b562a
parent0722c9439e92ed5900180afc752bd70e1739dcf3 (diff)
parent11d6f18bf6a853ccae06371b67a43a41a4dd8af2 (diff)
downloadrust-30dc2bafc878eec948cdc4c8bf992708719f1d16.tar.gz
rust-30dc2bafc878eec948cdc4c8bf992708719f1d16.zip
Rollup merge of #125851 - scottmcm:moar-validate, r=compiler-errors
Add some more specific checks to the MIR validator

None of the `PointerCoercion`s had any checks, so while there's probably more that could be done here, hopefully these are better than the previous nothing.

r? mir
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs101
1 files changed, 94 insertions, 7 deletions
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 5e83a6f373a..3b4d4c93877 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -8,6 +8,7 @@ use rustc_middle::mir::coverage::CoverageKind;
 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 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         // 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 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             );
                         }
                     }
-                    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() {