Skip to content

Commit d857bc8

Browse files
committed
lint: polish code from the last few commits
1 parent 7962a2d commit d857bc8

File tree

1 file changed

+60
-25
lines changed

1 file changed

+60
-25
lines changed

compiler/rustc_lint/src/types.rs

+60-25
Original file line numberDiff line numberDiff line change
@@ -740,35 +740,49 @@ enum FfiResult<'tcx> {
740740
},
741741
}
742742

743-
pub(crate) fn is_unsized_because_foreign<'tcx, 'a>(
744-
cx: &'a LateContext<'tcx>,
745-
ty: Ty<'tcx>,
746-
) -> Result<bool, ()> {
743+
/// Determine if a type is sized or not, and wether it affects references/pointers/boxes to it
744+
#[derive(Clone, Copy)]
745+
enum TypeSizedness {
746+
/// sized type (pointers are C-compatible)
747+
Sized,
748+
/// unsized type because it includes an opaque/foreign type (pointers are C-compatible)
749+
UnsizedBecauseForeign,
750+
/// unsized type for other reasons (slice, string, dyn Trait, closure, ...) (pointers are not C-compatible)
751+
UnsizedWithMetadata,
752+
}
753+
754+
/// Is this type unsized because it contains (or is) a foreign type?
755+
/// (Returns Err if the type happens to be sized after all)
756+
fn get_type_sizedness<'tcx, 'a>(cx: &'a LateContext<'tcx>, ty: Ty<'tcx>) -> TypeSizedness {
747757
let tcx = cx.tcx;
748758

749759
if ty.is_sized(tcx, cx.typing_env()) {
750-
Err(())
760+
TypeSizedness::Sized
751761
} else {
752-
Ok(match ty.kind() {
753-
ty::Slice(_) => false,
754-
ty::Str => false,
755-
ty::Dynamic(..) => false,
756-
ty::Foreign(..) => true,
757-
ty::Alias(ty::Opaque, ..) => todo!("why"),
762+
match ty.kind() {
763+
ty::Slice(_) => TypeSizedness::UnsizedWithMetadata,
764+
ty::Str => TypeSizedness::UnsizedWithMetadata,
765+
ty::Dynamic(..) => TypeSizedness::UnsizedWithMetadata,
766+
ty::Foreign(..) => TypeSizedness::UnsizedBecauseForeign,
767+
// While opaque types are checked for earlier, if a projection in a struct field
768+
// normalizes to an opaque type, then it will reach this branch.
769+
ty::Alias(ty::Opaque, ..) => todo!("We... don't know enough about this type yet?"),
758770
ty::Adt(def, args) => {
759771
// for now assume: boxes and phantoms don't mess with this
760772
match def.adt_kind() {
761-
AdtKind::Union | AdtKind::Enum => true,
773+
AdtKind::Union | AdtKind::Enum => {
774+
bug!("unions and enums are necessarily sized")
775+
}
762776
AdtKind::Struct => {
763777
if let Some(sym::cstring_type | sym::cstr_type) =
764778
tcx.get_diagnostic_name(def.did())
765779
{
766-
return Ok(false);
780+
return TypeSizedness::UnsizedWithMetadata;
767781
}
768782
// FIXME: how do we deal with non-exhaustive unsized structs/unions?
769783

770784
if def.non_enum_variant().fields.is_empty() {
771-
bug!("empty unsized struct/union. what?");
785+
bug!("an empty struct is necessarily sized");
772786
}
773787

774788
let variant = def.non_enum_variant();
@@ -781,7 +795,13 @@ pub(crate) fn is_unsized_because_foreign<'tcx, 'a>(
781795
.tcx
782796
.try_normalize_erasing_regions(cx.typing_env(), field_ty)
783797
.unwrap_or(field_ty);
784-
return Ok(is_unsized_because_foreign(cx, field_ty).unwrap());
798+
match get_type_sizedness(cx, field_ty) {
799+
s @ (TypeSizedness::UnsizedWithMetadata
800+
| TypeSizedness::UnsizedBecauseForeign) => s,
801+
TypeSizedness::Sized => {
802+
bug!("failed to find the reason why struct `{:?}` is unsized", ty)
803+
}
804+
}
785805
}
786806
}
787807
}
@@ -794,12 +814,21 @@ pub(crate) fn is_unsized_because_foreign<'tcx, 'a>(
794814
.tcx
795815
.try_normalize_erasing_regions(cx.typing_env(), field_ty)
796816
.unwrap_or(field_ty);
797-
is_unsized_because_foreign(cx, field_ty).unwrap()
817+
match get_type_sizedness(cx, field_ty) {
818+
s @ (TypeSizedness::UnsizedWithMetadata
819+
| TypeSizedness::UnsizedBecauseForeign) => s,
820+
TypeSizedness::Sized => {
821+
bug!("failed to find the reason why tuple `{:?}` is unsized", ty)
822+
}
823+
}
798824
}
799825
t => {
800-
bug!("we shouldn't be looking if this is unsized for a reason or another: {:?}", t)
826+
bug!(
827+
"we shouldn't be trying to determine if this is unsized for a reason or another: `{:?}`",
828+
t
829+
)
801830
}
802-
})
831+
}
803832
}
804833
}
805834

@@ -1106,8 +1135,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
11061135
match *ty.kind() {
11071136
ty::Adt(def, args) => {
11081137
if let Some(inner_ty) = ty.boxed_ty() {
1109-
if inner_ty.is_sized(tcx, self.cx.typing_env())
1110-
|| is_unsized_because_foreign(self.cx, inner_ty).unwrap()
1138+
if let TypeSizedness::UnsizedBecauseForeign | TypeSizedness::Sized =
1139+
get_type_sizedness(self.cx, inner_ty)
11111140
{
11121141
// discussion on declaration vs definition:
11131142
// see the `ty::RawPtr(inner_ty, _) | ty::Ref(_, inner_ty, _)` arm
@@ -1311,13 +1340,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13111340
}
13121341

13131342
ty::RawPtr(inner_ty, _) | ty::Ref(_, inner_ty, _) => {
1314-
if inner_ty.is_sized(tcx, self.cx.typing_env())
1315-
|| is_unsized_because_foreign(self.cx, inner_ty).unwrap()
1343+
if let TypeSizedness::UnsizedBecauseForeign | TypeSizedness::Sized =
1344+
get_type_sizedness(self.cx, inner_ty)
13161345
{
13171346
// there's a nuance on what this lint should do for function definitions
1318-
// (touched upon in https://github.com/rust-lang/rust/issues/66220 and https://github.com/rust-lang/rust/pull/72700)
1319-
//
13201347
// (`extern "C" fn fn_name(...) {...}`) versus declarations (`extern "C" {fn fn_name(...);}`).
1348+
// (this is touched upon in https://github.com/rust-lang/rust/issues/66220
1349+
// and https://github.com/rust-lang/rust/pull/72700)
1350+
//
13211351
// The big question is: what does "ABI safety" mean? if you have something translated to a C pointer
13221352
// (which has a stable layout) but points to FFI-unsafe type, is it safe?
13231353
// on one hand, the function's ABI will match that of a similar C-declared function API,
@@ -1609,7 +1639,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
16091639
}
16101640
};
16111641
}
1612-
let last_ty = last_ty.unwrap(); // populated by any run of the `while` block
1642+
let last_ty = match last_ty {
1643+
Some(last_ty) => last_ty,
1644+
None => bug!(
1645+
"This option should definitely have been filled by the loop that just finished"
1646+
),
1647+
};
16131648
self.emit_ffi_unsafe_type_lint(last_ty, sp, cimproper_layers);
16141649
}
16151650
}

0 commit comments

Comments
 (0)