Skip to content

Commit 5036d7f

Browse files
committed
lint ImproperCTypes: add considerations for which values can be sourced from non-rust code
1 parent 2a24fc9 commit 5036d7f

17 files changed

+909
-634
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,13 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
400400
401401
lint_improper_ctypes_opaque = opaque types have no C equivalent
402402
403-
lint_improper_ctypes_pat_help = consider using the base type instead
403+
lint_improper_ctypes_pat_intrange_help = consider using the base type instead
404+
lint_improper_ctypes_pat_intrange_reason = integers constrained to a given range cannot have their value be provided by non-rust code
404405
405-
lint_improper_ctypes_pat_reason = pattern types have no C equivalent
406+
lint_improper_ctypes_ptr_validity_help = consider using a raw pointer, or wrapping `{$ty}` in an `Option<_>`
407+
lint_improper_ctypes_ptr_validity_reason =
408+
boxes and references are assumed to be valid (non-null, non-dangling, aligned) pointers,
409+
which cannot be garanteed if their values are produced by non-rust code
406410
407411
lint_improper_ctypes_sized_ptr_to_unsafe_type =
408412
this reference (`{$ty}`) is ABI-compatible with a C pointer, but `{$inner_ty}` itself does not have a C layout

compiler/rustc_lint/src/types.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_abi::{BackendRepr, TagEncoding, Variants, WrappingRange};
44
use rustc_hir::{Expr, ExprKind, LangItem};
55
use rustc_middle::bug;
66
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
7-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
7+
use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeVisitableExt};
88
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
99
use rustc_span::{Span, Symbol, source_map, sym};
1010
use tracing::debug;
@@ -863,6 +863,38 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
863863
None
864864
}
865865

866+
/// determines wether or not `outer_ty` is an option-like enum, with the same size as its contained type, `ty`.
867+
/// this ASSUMES that `ty` is a type that is already 'inside' of `outer_ty`.
868+
fn is_outer_optionlike_around_ty<'tcx>(
869+
cx: &LateContext<'tcx>,
870+
outer_ty: Ty<'tcx>,
871+
ty: Ty<'tcx>,
872+
) -> bool {
873+
// three things to check to be sure outer_ty is option-like (since we know we reached the current ty from there)
874+
// That outer_ty is an enum, that this enum doesn't have a defined discriminant representation,
875+
// and the the outer_ty's size is that of ty.
876+
if let ty::Adt(def, _) = outer_ty.kind() {
877+
if !matches!(def.adt_kind(), AdtKind::Enum)
878+
|| def.repr().c()
879+
|| def.repr().transparent()
880+
|| def.repr().int.is_none()
881+
{
882+
false
883+
} else {
884+
let (tcx, typing_env) = (cx.tcx, cx.typing_env());
885+
886+
// see the insides of super::repr_nullable_ptr()
887+
let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
888+
match (compute_size_skeleton(ty), compute_size_skeleton(outer_ty)) {
889+
(Some(sk1), Some(sk2)) => sk1.same_size(sk2),
890+
_ => false,
891+
}
892+
}
893+
} else {
894+
false
895+
}
896+
}
897+
866898
declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
867899

868900
impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {

0 commit comments

Comments
 (0)