Skip to content

Commit 4ca1346

Browse files
committed
lint ImproperCTypes: remove the parts about checking value assumptions
it would be correct to lint on those, but this is deemed too steep a change for now, especially for projects that turn all warnings into errors
1 parent b70eb45 commit 4ca1346

26 files changed

+309
-1431
lines changed

compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ use libc::{c_char, c_uint};
66
use super::MetadataKindId;
77
use super::ffi::{AttributeKind, BasicBlock, Metadata, Module, Type, Value};
88
use crate::llvm::Bool;
9-
use crate::wrap_returns_in_options;
109

11-
wrap_returns_in_options! {
1210
#[link(name = "llvm-wrapper", kind = "static")]
1311
unsafe extern "C" {
1412
// Enzyme
@@ -17,7 +15,7 @@ unsafe extern "C" {
1715
pub(crate) fn LLVMRustGetLastInstruction<'a>(BB: &BasicBlock) -> Option<&'a Value>;
1816
pub(crate) fn LLVMRustDIGetInstMetadata(I: &Value) -> Option<&Metadata>;
1917
pub(crate) fn LLVMRustEraseInstFromParent(V: &Value);
20-
|wrap pub(crate) fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
18+
pub(crate) fn LLVMRustGetTerminator<'a>(B: &BasicBlock) -> &'a Value;
2119
pub(crate) fn LLVMRustVerifyFunction(V: &Value, action: LLVMRustVerifierFailureAction) -> Bool;
2220
pub(crate) fn LLVMRustHasAttributeAtIndex(V: &Value, i: c_uint, Kind: AttributeKind) -> bool;
2321
pub(crate) fn LLVMRustGetArrayNumElements(Ty: &Type) -> u64;
@@ -41,11 +39,10 @@ unsafe extern "C" {
4139
pub(crate) fn LLVMDumpModule(M: &Module);
4240
pub(crate) fn LLVMDumpValue(V: &Value);
4341
pub(crate) fn LLVMGetFunctionCallConv(F: &Value) -> c_uint;
44-
|wrap pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type;
42+
pub(crate) fn LLVMGetReturnType(T: &Type) -> &Type;
4543
pub(crate) fn LLVMGetParams(Fnc: &Value, parms: *mut &Value);
4644
pub(crate) fn LLVMGetNamedFunction(M: &Module, Name: *const c_char) -> Option<&Value>;
4745
}
48-
}
4946

5047
#[repr(C)]
5148
#[derive(Copy, Clone, PartialEq)]

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 191 additions & 273 deletions
Large diffs are not rendered by default.

compiler/rustc_lint/messages.ftl

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -415,16 +415,6 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
415415
416416
lint_improper_ctypes_opaque = opaque types have no C equivalent
417417
418-
lint_improper_ctypes_pat_int1_help = consider using the base type instead, or wrapping `{$ty}` in an `Option<_>`
419-
lint_improper_ctypes_pat_int1_reason = integer-pattern types with one disallowed value and no `Option` wrapping cannot have their value be provided by non-rust code
420-
lint_improper_ctypes_pat_int2_help = consider using the base type instead
421-
lint_improper_ctypes_pat_int2_reason = integer-pattern types with more than one disallowed value cannot have their value be provided by non-rust code
422-
423-
lint_improper_ctypes_ptr_validity_help = consider using a raw pointer, or wrapping `{$ty}` in an `Option<_>`
424-
lint_improper_ctypes_ptr_validity_reason =
425-
boxes, references, and function pointers are assumed to be valid (non-null, non-dangling, aligned) pointers,
426-
which cannot be garanteed if their values are produced by non-rust code
427-
428418
lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead
429419
lint_improper_ctypes_slice_reason = slices have no C equivalent
430420

compiler/rustc_lint/src/foreign_modules.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,14 +366,14 @@ fn structurally_same_type_impl<'tcx>(
366366
// An Adt and a primitive or pointer type. This can be FFI-safe if non-null
367367
// enum layout optimisation is being applied.
368368
(ty::Adt(..) | ty::Pat(..), _) if is_primitive_or_pointer(b) => {
369-
if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, false) {
369+
if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a) {
370370
a_inner == b
371371
} else {
372372
false
373373
}
374374
}
375375
(_, ty::Adt(..) | ty::Pat(..)) if is_primitive_or_pointer(a) => {
376-
if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, false) {
376+
if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b) {
377377
b_inner == a
378378
} else {
379379
false

compiler/rustc_lint/src/types.rs

Lines changed: 13 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_abi::{BackendRepr, Size, TagEncoding, Variants, WrappingRange};
44
use rustc_hir::{Expr, ExprKind, HirId, LangItem};
55
use rustc_middle::bug;
66
use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
7-
use rustc_middle::ty::{self, AdtKind, Const, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
7+
use rustc_middle::ty::{self, Const, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
88
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
99
use rustc_span::{Span, Symbol, sym};
1010
use tracing::debug;
@@ -868,14 +868,13 @@ fn is_niche_optimization_candidate<'tcx>(
868868
}
869869

870870
/// Check if this enum can be safely exported based on the "nullable pointer optimization". If it
871-
/// can, return the type that `ty` can be safely converted to/from, otherwise return `None`.
871+
/// can, return the type that `ty` can be safely converted to, otherwise return `None`.
872872
/// Currently restricted to function pointers, boxes, references, `core::num::NonZero`,
873873
/// `core::ptr::NonNull`, `#[repr(transparent)]` newtypes, and int-range pattern types.
874874
pub(crate) fn repr_nullable_ptr<'tcx>(
875875
tcx: TyCtxt<'tcx>,
876876
typing_env: ty::TypingEnv<'tcx>,
877877
ty: Ty<'tcx>,
878-
checked_conversion_is_from: bool,
879878
) -> Option<Ty<'tcx>> {
880879
debug!("is_repr_nullable_ptr(tcx, ty = {:?})", ty);
881880
match ty.kind() {
@@ -901,17 +900,11 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
901900
};
902901

903902
if let ty::Pat(base, pat) = field_ty.kind() {
904-
return if let Some(disallowed) = get_pat_disallowed_value_count(*pat) {
905-
if disallowed != 1 && checked_conversion_is_from {
906-
// if there are values not taken into account by the optionlike Enum
907-
// then we can't safely convert from the base type, only the pattern type
908-
Some(field_ty)
909-
} else {
910-
get_nullable_type_from_pat(tcx, typing_env, *base, *pat)
911-
}
903+
if pattern_has_disallowed_values(*pat) || matches!(base.kind(), ty::Char) {
904+
return get_nullable_type_from_pat(tcx, typing_env, *base, *pat);
912905
} else {
913-
None
914-
};
906+
return None;
907+
}
915908
}
916909

917910
if !ty_is_known_nonnull(tcx, typing_env, field_ty) {
@@ -950,22 +943,13 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
950943
}
951944
None
952945
}
953-
ty::Pat(base, pat) => {
954-
if checked_conversion_is_from && get_pat_disallowed_value_count(*pat).is_some() {
955-
// if there are values not taken into account by the pattern (the usual case)
956-
// then we can't safely convert from the base type
957-
None
958-
} else {
959-
get_nullable_type_from_pat(tcx, typing_env, *base, *pat)
960-
}
961-
}
946+
ty::Pat(base, pat) => get_nullable_type_from_pat(tcx, typing_env, *base, *pat),
962947
_ => None,
963948
}
964949
}
965950

966-
/// return the number of disallowed values in a pattern type
967-
/// note that Some(0) actually maps to 2^128 rather than 0
968-
pub(crate) fn get_pat_disallowed_value_count<'tcx>(pat: ty::Pattern<'tcx>) -> Option<u128> {
951+
/// returns whether a pattern type actually has disallowed values
952+
pub(crate) fn pattern_has_disallowed_values<'tcx>(pat: ty::Pattern<'tcx>) -> bool {
969953
// note the logic in this function assumes that signed ints use one's complement representation,
970954
// which I believe is a requirement for rust
971955

@@ -1028,17 +1012,7 @@ pub(crate) fn get_pat_disallowed_value_count<'tcx>(pat: ty::Pattern<'tcx>) -> Op
10281012
(0, scalar_size.unsigned_int_max())
10291013
};
10301014

1031-
if (start.to_bits(scalar_size), end.to_bits(scalar_size)) == (scalar_min, scalar_max) {
1032-
return None;
1033-
}
1034-
1035-
// note: allow overflow here because negative values are allowed in the scalars represented here
1036-
let allowed_value_count_minus1 =
1037-
u128::overflowing_sub(end.to_bits(scalar_size), start.to_bits(scalar_size)).0
1038-
& scalar_size.unsigned_int_max();
1039-
let disallowed_value_count =
1040-
u128::overflowing_sub(scalar_size.unsigned_int_max(), allowed_value_count_minus1).0;
1041-
Some(disallowed_value_count)
1015+
(start.to_bits(scalar_size), end.to_bits(scalar_size)) != (scalar_min, scalar_max)
10421016
}
10431017
ty::PatternKind::Or(patterns) => {
10441018
// first, get a simplified an sorted view of the ranges
@@ -1077,8 +1051,6 @@ pub(crate) fn get_pat_disallowed_value_count<'tcx>(pat: ty::Pattern<'tcx>) -> Op
10771051
// (`prev_tail` is the highest value currently accounted for by the ranges,
10781052
// unless the first range has not been dealt with yet)
10791053
let mut prev_tail = scalar_max;
1080-
let mut disallowed_value_count = 0_u128;
1081-
let mut only_had_overlaps = true;
10821054

10831055
for (range_i, (start, end)) in ranges.into_iter().enumerate() {
10841056
let (start, end) = (start.to_bits(scalar_size), end.to_bits(scalar_size));
@@ -1109,28 +1081,11 @@ pub(crate) fn get_pat_disallowed_value_count<'tcx>(pat: ty::Pattern<'tcx>) -> Op
11091081
prev_tail = u128::max(prev_tail, end)
11101082
}
11111083
} else {
1112-
// no range overlap: first, add the newfound disallowed values to the count
1113-
only_had_overlaps = false;
1114-
let new_gap = u128::overflowing_sub(
1115-
start,
1116-
u128::overflowing_add(prev_tail, 1).0 & scalar_size.unsigned_int_max(),
1117-
)
1118-
.0 & scalar_size.unsigned_int_max();
1119-
disallowed_value_count =
1120-
u128::overflowing_add(disallowed_value_count, new_gap).0;
1121-
prev_tail = end;
1084+
// no range overlap: there are disallowed values
1085+
return true;
11221086
}
11231087
}
1124-
if prev_tail != scalar_max {
1125-
disallowed_value_count = u128::overflowing_add(
1126-
disallowed_value_count,
1127-
u128::overflowing_sub(scalar_max, prev_tail).0,
1128-
)
1129-
.0;
1130-
only_had_overlaps = false;
1131-
}
1132-
1133-
if only_had_overlaps { None } else { Some(disallowed_value_count) }
1088+
prev_tail != scalar_max
11341089
}
11351090
}
11361091
}
@@ -1153,38 +1108,6 @@ fn get_nullable_type_from_pat<'tcx>(
11531108
}
11541109
}
11551110

1156-
/// determines wether or not `outer_ty` is an option-like enum, with the same size as its contained type, `ty`.
1157-
/// this ASSUMES that `ty` is a type that is already 'inside' of `outer_ty`.
1158-
fn is_outer_optionlike_around_ty<'tcx>(
1159-
cx: &LateContext<'tcx>,
1160-
outer_ty: Ty<'tcx>,
1161-
ty: Ty<'tcx>,
1162-
) -> bool {
1163-
// three things to check to be sure outer_ty is option-like (since we know we reached the current ty from there)
1164-
// That outer_ty is an enum, that this enum doesn't have a defined discriminant representation,
1165-
// and the the outer_ty's size is that of ty.
1166-
if let ty::Adt(def, _) = outer_ty.kind() {
1167-
if (!matches!(def.adt_kind(), AdtKind::Enum))
1168-
|| def.repr().c()
1169-
|| def.repr().transparent()
1170-
|| def.repr().int.is_some()
1171-
{
1172-
false
1173-
} else {
1174-
let (tcx, typing_env) = (cx.tcx, cx.typing_env());
1175-
1176-
// see the insides of super::repr_nullable_ptr()
1177-
let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env);
1178-
match (compute_size_skeleton(ty), compute_size_skeleton(outer_ty)) {
1179-
(Ok(sk1), Ok(sk2)) => sk1.same_size(sk2),
1180-
_ => false,
1181-
}
1182-
}
1183-
} else {
1184-
false
1185-
}
1186-
}
1187-
11881111
declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
11891112

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

0 commit comments

Comments
 (0)