Skip to content

Commit dd5927d

Browse files
committed
Correctly handle pattern types in FFI redeclaration lints
1 parent 768363c commit dd5927d

File tree

4 files changed

+64
-88
lines changed

4 files changed

+64
-88
lines changed

compiler/rustc_lint/src/foreign_modules.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,7 @@ fn structurally_same_type_impl<'tcx>(
241241
if let ty::Adt(def, args) = *ty.kind() {
242242
let is_transparent = def.repr().transparent();
243243
let is_non_null = types::nonnull_optimization_guaranteed(tcx, def);
244-
debug!(
245-
"non_transparent_ty({:?}) -- type is transparent? {}, type is non-null? {}",
246-
ty, is_transparent, is_non_null
247-
);
244+
debug!(?ty, is_transparent, is_non_null);
248245
if is_transparent && !is_non_null {
249246
debug_assert_eq!(def.variants().len(), 1);
250247
let v = &def.variant(FIRST_VARIANT);
@@ -378,14 +375,14 @@ fn structurally_same_type_impl<'tcx>(
378375

379376
// An Adt and a primitive or pointer type. This can be FFI-safe if non-null
380377
// enum layout optimisation is being applied.
381-
(Adt(..), _) if is_primitive_or_pointer(b) => {
378+
(Adt(..) | Pat(..), _) if is_primitive_or_pointer(b) => {
382379
if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) {
383380
a_inner == b
384381
} else {
385382
false
386383
}
387384
}
388-
(_, Adt(..)) if is_primitive_or_pointer(a) => {
385+
(_, Adt(..) | Pat(..)) if is_primitive_or_pointer(a) => {
389386
if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) {
390387
b_inner == a
391388
} else {

compiler/rustc_lint/src/types.rs

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -891,9 +891,8 @@ fn get_nullable_type<'tcx>(
891891
};
892892
return get_nullable_type(tcx, typing_env, inner_field_ty);
893893
}
894-
ty::Int(ty) => Ty::new_int(tcx, ty),
895-
ty::Uint(ty) => Ty::new_uint(tcx, ty),
896-
ty::RawPtr(ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
894+
ty::Pat(base, ..) => return get_nullable_type(tcx, typing_env, base),
895+
ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => ty,
897896
// As these types are always non-null, the nullable equivalent of
898897
// `Option<T>` of these types are their raw pointer counterparts.
899898
ty::Ref(_region, ty, mutbl) => Ty::new_ptr(tcx, ty, mutbl),
@@ -949,63 +948,69 @@ pub(crate) fn repr_nullable_ptr<'tcx>(
949948
ckind: CItemKind,
950949
) -> Option<Ty<'tcx>> {
951950
debug!("is_repr_nullable_ptr(tcx, ty = {:?})", ty);
952-
if let ty::Adt(ty_def, args) = ty.kind() {
953-
let field_ty = match &ty_def.variants().raw[..] {
954-
[var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
955-
([], [field]) | ([field], []) => field.ty(tcx, args),
956-
([field1], [field2]) => {
957-
let ty1 = field1.ty(tcx, args);
958-
let ty2 = field2.ty(tcx, args);
959-
960-
if is_niche_optimization_candidate(tcx, typing_env, ty1) {
961-
ty2
962-
} else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
963-
ty1
964-
} else {
965-
return None;
951+
match ty.kind() {
952+
ty::Adt(ty_def, args) => {
953+
let field_ty = match &ty_def.variants().raw[..] {
954+
[var_one, var_two] => match (&var_one.fields.raw[..], &var_two.fields.raw[..]) {
955+
([], [field]) | ([field], []) => field.ty(tcx, args),
956+
([field1], [field2]) => {
957+
let ty1 = field1.ty(tcx, args);
958+
let ty2 = field2.ty(tcx, args);
959+
960+
if is_niche_optimization_candidate(tcx, typing_env, ty1) {
961+
ty2
962+
} else if is_niche_optimization_candidate(tcx, typing_env, ty2) {
963+
ty1
964+
} else {
965+
return None;
966+
}
966967
}
967-
}
968+
_ => return None,
969+
},
968970
_ => return None,
969-
},
970-
_ => return None,
971-
};
971+
};
972972

973-
if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
974-
return None;
975-
}
973+
if !ty_is_known_nonnull(tcx, typing_env, field_ty, ckind) {
974+
return None;
975+
}
976976

977-
// At this point, the field's type is known to be nonnull and the parent enum is Option-like.
978-
// If the computed size for the field and the enum are different, the nonnull optimization isn't
979-
// being applied (and we've got a problem somewhere).
980-
let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
981-
if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
982-
bug!("improper_ctypes: Option nonnull optimization not applied?");
983-
}
977+
// At this point, the field's type is known to be nonnull and the parent enum is Option-like.
978+
// If the computed size for the field and the enum are different, the nonnull optimization isn't
979+
// being applied (and we've got a problem somewhere).
980+
let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, typing_env).ok();
981+
if !compute_size_skeleton(ty)?.same_size(compute_size_skeleton(field_ty)?) {
982+
bug!("improper_ctypes: Option nonnull optimization not applied?");
983+
}
984984

985-
// Return the nullable type this Option-like enum can be safely represented with.
986-
let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
987-
if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
988-
bug!("should be able to compute the layout of non-polymorphic type");
989-
}
985+
// Return the nullable type this Option-like enum can be safely represented with.
986+
let field_ty_layout = tcx.layout_of(typing_env.as_query_input(field_ty));
987+
if field_ty_layout.is_err() && !field_ty.has_non_region_param() {
988+
bug!("should be able to compute the layout of non-polymorphic type");
989+
}
990990

991-
let field_ty_abi = &field_ty_layout.ok()?.backend_repr;
992-
if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi {
993-
match field_ty_scalar.valid_range(&tcx) {
994-
WrappingRange { start: 0, end }
995-
if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
996-
{
997-
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
998-
}
999-
WrappingRange { start: 1, .. } => {
1000-
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
1001-
}
1002-
WrappingRange { start, end } => {
1003-
unreachable!("Unhandled start and end range: ({}, {})", start, end)
1004-
}
1005-
};
991+
let field_ty_abi = &field_ty_layout.ok()?.backend_repr;
992+
if let BackendRepr::Scalar(field_ty_scalar) = field_ty_abi {
993+
match field_ty_scalar.valid_range(&tcx) {
994+
WrappingRange { start: 0, end }
995+
if end == field_ty_scalar.size(&tcx).unsigned_int_max() - 1 =>
996+
{
997+
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
998+
}
999+
WrappingRange { start: 1, .. } => {
1000+
return Some(get_nullable_type(tcx, typing_env, field_ty).unwrap());
1001+
}
1002+
WrappingRange { start, end } => {
1003+
unreachable!("Unhandled start and end range: ({}, {})", start, end)
1004+
}
1005+
};
1006+
}
1007+
None
10061008
}
1009+
ty::Pat(base, pat) => match **pat {
1010+
ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, *base),
1011+
},
1012+
_ => None,
10071013
}
1008-
None
10091014
}
10101015

10111016
impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {

tests/ui/lint/clashing-extern-fn.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,13 +512,11 @@ mod pattern_types {
512512
// invariant that the value is non-zero, or you're missing out on that invariant. Both
513513
// cases are warning for, from both a caller-convenience and optimisation perspective.
514514
fn pt_non_zero_usize() -> usize;
515-
//~^ WARN `pt_non_zero_usize` redeclared with a different signature
516515
fn pt_non_zero_usize_opt() -> usize;
517516
//~^ WARN `pt_non_zero_usize_opt` redeclared with a different signature
518517
fn pt_non_null_ptr() -> *const ();
519518
//~^ WARN `pt_non_null_ptr` redeclared with a different signature
520519
fn pt_non_zero_usize_wrapper() -> usize;
521-
//~^ WARN `pt_non_zero_usize_wrapper` redeclared with a different signature
522520
fn pt_non_zero_usize_wrapper_opt() -> usize;
523521
//~^ WARN `pt_non_zero_usize_wrapper_opt` redeclared with a different signature
524522
}

tests/ui/lint/clashing-extern-fn.stderr

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -276,20 +276,8 @@ LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usiz
276276
= note: expected `unsafe extern "C" fn() -> usize`
277277
found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>`
278278

279-
warning: `pt_non_zero_usize` redeclared with a different signature
280-
--> $DIR/clashing-extern-fn.rs:514:13
281-
|
282-
LL | fn pt_non_zero_usize() -> pattern_type!(usize is 1..);
283-
| ------------------------------------------------------ `pt_non_zero_usize` previously declared here
284-
...
285-
LL | fn pt_non_zero_usize() -> usize;
286-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
287-
|
288-
= note: expected `unsafe extern "C" fn() -> (usize) is 1..=`
289-
found `unsafe extern "C" fn() -> usize`
290-
291279
warning: `pt_non_zero_usize_opt` redeclared with a different signature
292-
--> $DIR/clashing-extern-fn.rs:516:13
280+
--> $DIR/clashing-extern-fn.rs:515:13
293281
|
294282
LL | fn pt_non_zero_usize_opt() -> Option<pattern_type!(usize is 1..)>;
295283
| ------------------------------------------------------------------ `pt_non_zero_usize_opt` previously declared here
@@ -301,7 +289,7 @@ LL | fn pt_non_zero_usize_opt() -> usize;
301289
found `unsafe extern "C" fn() -> usize`
302290

303291
warning: `pt_non_null_ptr` redeclared with a different signature
304-
--> $DIR/clashing-extern-fn.rs:518:13
292+
--> $DIR/clashing-extern-fn.rs:517:13
305293
|
306294
LL | fn pt_non_null_ptr() -> pattern_type!(usize is 1..);
307295
| ---------------------------------------------------- `pt_non_null_ptr` previously declared here
@@ -312,20 +300,8 @@ LL | fn pt_non_null_ptr() -> *const ();
312300
= note: expected `unsafe extern "C" fn() -> (usize) is 1..=`
313301
found `unsafe extern "C" fn() -> *const ()`
314302

315-
warning: `pt_non_zero_usize_wrapper` redeclared with a different signature
316-
--> $DIR/clashing-extern-fn.rs:520:13
317-
|
318-
LL | fn pt_non_zero_usize_wrapper() -> NonZeroUsize;
319-
| ----------------------------------------------- `pt_non_zero_usize_wrapper` previously declared here
320-
...
321-
LL | fn pt_non_zero_usize_wrapper() -> usize;
322-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
323-
|
324-
= note: expected `unsafe extern "C" fn() -> NonZeroUsize`
325-
found `unsafe extern "C" fn() -> usize`
326-
327303
warning: `pt_non_zero_usize_wrapper_opt` redeclared with a different signature
328-
--> $DIR/clashing-extern-fn.rs:522:13
304+
--> $DIR/clashing-extern-fn.rs:520:13
329305
|
330306
LL | fn pt_non_zero_usize_wrapper_opt() -> Option<NonZeroUsize>;
331307
| ----------------------------------------------------------- `pt_non_zero_usize_wrapper_opt` previously declared here
@@ -336,5 +312,5 @@ LL | fn pt_non_zero_usize_wrapper_opt() -> usize;
336312
= note: expected `unsafe extern "C" fn() -> Option<NonZeroUsize>`
337313
found `unsafe extern "C" fn() -> usize`
338314

339-
warning: 29 warnings emitted
315+
warning: 27 warnings emitted
340316

0 commit comments

Comments
 (0)