summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2020-07-14 19:26:34 +0100
committerMark Rousskov <mark.simulacrum@gmail.com>2020-08-07 11:54:30 -0400
commit34c9ac319282f93e148df27db030a99f5a9402f0 (patch)
tree04fc459d7571a98cfe2a7a1988ecf8128dca2db1
parent1a2f6d5d6fd46054f59852c052d12f2f3711e5b8 (diff)
downloadrust-34c9ac319282f93e148df27db030a99f5a9402f0.tar.gz
rust-34c9ac319282f93e148df27db030a99f5a9402f0.zip
lint: use `transparent_newtype_field` to avoid ICE
This commit re-uses the `transparent_newtype_field` function instead of
manually calling `is_zst` on normalized fields to determine which field
in a transparent type is the non-zero-sized field, thus avoiding an ICE.

Signed-off-by: David Wood <david@davidtw.co>
-rw-r--r--src/librustc_lint/types.rs32
-rw-r--r--src/test/ui/lint/lint-ctypes-73747.rs14
2 files changed, 30 insertions, 16 deletions
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index b3015dcc2ae..46741fcf2ba 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -531,23 +531,23 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         match ty.kind {
             ty::FnPtr(_) => true,
             ty::Ref(..) => true,
-            ty::Adt(field_def, substs) if field_def.repr.transparent() && !field_def.is_union() => {
-                for field in field_def.all_fields() {
-                    let field_ty = self.cx.tcx.normalize_erasing_regions(
-                        self.cx.param_env,
-                        field.ty(self.cx.tcx, substs),
-                    );
-                    if field_ty.is_zst(self.cx.tcx, field.did) {
-                        continue;
-                    }
+            ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => {
+                let guaranteed_nonnull_optimization = self
+                    .cx
+                    .tcx
+                    .get_attrs(def.did)
+                    .iter()
+                    .any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed));
+
+                if guaranteed_nonnull_optimization {
+                    return true;
+                }
 
-                    let attrs = self.cx.tcx.get_attrs(field_def.did);
-                    if attrs
-                        .iter()
-                        .any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed))
-                        || self.ty_is_known_nonnull(field_ty)
-                    {
-                        return true;
+                for variant in &def.variants {
+                    if let Some(field) = variant.transparent_newtype_field(self.cx.tcx) {
+                        if self.ty_is_known_nonnull(field.ty(self.cx.tcx, substs)) {
+                            return true;
+                        }
                     }
                 }
 
diff --git a/src/test/ui/lint/lint-ctypes-73747.rs b/src/test/ui/lint/lint-ctypes-73747.rs
new file mode 100644
index 00000000000..293ffd5c28e
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes-73747.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#[repr(transparent)]
+struct NonNullRawComPtr<T: ComInterface> {
+    inner: std::ptr::NonNull<<T as ComInterface>::VTable>,
+}
+
+trait ComInterface {
+    type VTable;
+}
+
+extern "C" fn invoke<T: ComInterface>(_: Option<NonNullRawComPtr<T>>) {}
+
+fn main() {}