Skip to content

Commit 9182910

Browse files
committed
Handle structs with zst members.
1 parent bc4819d commit 9182910

File tree

1 file changed

+28
-23
lines changed

1 file changed

+28
-23
lines changed

src/librustc_lint/types.rs

+28-23
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_index::vec::Idx;
1111
use rustc_middle::mir::interpret::{sign_extend, truncate};
1212
use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
1313
use rustc_middle::ty::subst::SubstsRef;
14-
use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
14+
use rustc_middle::ty::{self, AdtKind, Ty, TypeFoldable};
1515
use rustc_span::source_map;
1616
use rustc_span::symbol::sym;
1717
use rustc_span::{Span, DUMMY_SP};
@@ -550,25 +550,26 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
550550
_ => false,
551551
}
552552
}
553-
/// Given a potentially non-null type `ty`, return its default, nullable type.
554-
fn get_nullable_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
555-
match ty.kind {
553+
/// Given a non-null scalar (or transparent) type `ty`, return the nullable version of that type.
554+
/// If the type passed in was not scalar, returns None.
555+
fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
556+
let tcx = cx.tcx;
557+
Some(match ty.kind {
556558
ty::Adt(field_def, field_substs) => {
557-
let field_variants = &field_def.variants;
558-
// We hit this case for #[repr(transparent)] structs with a single
559-
// field.
560-
debug_assert!(
561-
field_variants.len() == 1 && field_variants[VariantIdx::new(0)].fields.len() == 1,
562-
"inner ty not a newtype struct"
563-
);
564-
debug_assert!(field_def.repr.transparent(), "inner ty not transparent");
565-
// As it's easy to get this wrong, it's worth noting that
566-
// `inner_field_ty` is not the same as `field_ty`: Given Option<S>,
567-
// where S is a transparent newtype of some type T, `field_ty`
568-
// gives us S, while `inner_field_ty` is T.
569-
let inner_field_ty =
570-
field_def.variants[VariantIdx::new(0)].fields[0].ty(tcx, field_substs);
571-
get_nullable_type(tcx, inner_field_ty)
559+
let inner_field_ty = {
560+
let mut first_non_zst_ty = field_def.all_fields().filter_map(|f| {
561+
let field_ty =
562+
tcx.normalize_erasing_regions(cx.param_env, f.ty(tcx, field_substs));
563+
if !field_ty.is_zst(tcx, f.did) { Some(field_ty) } else { None }
564+
});
565+
debug_assert_eq!(
566+
first_non_zst_ty.clone().count(),
567+
1,
568+
"Wrong number of fields for transparent type"
569+
);
570+
first_non_zst_ty.next().expect("No non-zst fields in transparent type.")
571+
};
572+
return get_nullable_type(cx, inner_field_ty);
572573
}
573574
ty::Int(ty) => tcx.mk_mach_int(ty),
574575
ty::Uint(ty) => tcx.mk_mach_uint(ty),
@@ -585,9 +586,13 @@ fn get_nullable_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
585586
// We should only ever reach this case if ty_is_known_nonnull is extended
586587
// to other types.
587588
ref unhandled => {
588-
unreachable!("Unhandled scalar kind: {:?} while checking {:?}", unhandled, ty)
589+
debug!(
590+
"get_nullable_type: Unhandled scalar kind: {:?} while checking {:?}",
591+
unhandled, ty
592+
);
593+
return None;
589594
}
590-
}
595+
})
591596
}
592597

593598
/// Check if this `ty` can be safely exported based on the "nullable pointer optimization".
@@ -633,9 +638,9 @@ crate fn repr_nullable_ptr<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option
633638
let field_ty_abi = &cx.layout_of(field_ty).unwrap().abi;
634639
if let Abi::Scalar(field_ty_scalar) = field_ty_abi {
635640
match (field_ty_scalar.valid_range.start(), field_ty_scalar.valid_range.end()) {
636-
(0, _) => bug!("Non-null optimisation extended to a non-zero value."),
641+
(0, _) => unreachable!("Non-null optimisation extended to a non-zero value."),
637642
(1, _) => {
638-
return Some(get_nullable_type(cx.tcx, field_ty));
643+
return Some(get_nullable_type(cx, field_ty).unwrap());
639644
}
640645
(start, end) => unreachable!("Unhandled start and end range: ({}, {})", start, end),
641646
};

0 commit comments

Comments
 (0)