about summary refs log tree commit diff
diff options
context:
space:
mode:
authorErik Desjardins <erikdesjardins@users.noreply.github.com>2021-03-19 22:25:56 -0400
committerErik Desjardins <erikdesjardins@users.noreply.github.com>2021-03-19 22:25:56 -0400
commit46fd49cdc366ebf74c1b2bcb3a0e3d22585f267f (patch)
tree183c6d0b2eb2c8f0b60f294411ff39184e0e0174
parent93c1380e0bbbc4939df7e25d888755f68aaf64f6 (diff)
downloadrust-46fd49cdc366ebf74c1b2bcb3a0e3d22585f267f.tar.gz
rust-46fd49cdc366ebf74c1b2bcb3a0e3d22585f267f.zip
avoid calling for types which can't be ZSTs
-rw-r--r--compiler/rustc_mir/src/transform/remove_zsts.rs42
1 files changed, 30 insertions, 12 deletions
diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir/src/transform/remove_zsts.rs
index 4c9dc43df9b..f0393853030 100644
--- a/compiler/rustc_mir/src/transform/remove_zsts.rs
+++ b/compiler/rustc_mir/src/transform/remove_zsts.rs
@@ -2,7 +2,7 @@
 
 use crate::transform::MirPass;
 use rustc_middle::mir::{Body, StatementKind};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, Ty, TyCtxt};
 
 pub struct RemoveZsts;
 
@@ -15,17 +15,23 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
                 match statement.kind {
                     StatementKind::Assign(box (place, _)) => {
                         let place_ty = place.ty(local_decls, tcx).ty;
-                        if let Ok(layout) = tcx.layout_of(param_env.and(place_ty)) {
-                            if layout.is_zst() {
-                                if tcx.consider_optimizing(|| {
-                                    format!(
-                                        "RemoveZsts - Place: {:?} SourceInfo: {:?}",
-                                        place, statement.source_info
-                                    )
-                                }) {
-                                    statement.make_nop();
-                                }
-                            }
+                        if !maybe_zst(place_ty) {
+                            continue;
+                        }
+                        let layout = match tcx.layout_of(param_env.and(place_ty)) {
+                            Ok(layout) => layout,
+                            Err(_) => continue,
+                        };
+                        if !layout.is_zst() {
+                            continue;
+                        }
+                        if tcx.consider_optimizing(|| {
+                            format!(
+                                "RemoveZsts - Place: {:?} SourceInfo: {:?}",
+                                place, statement.source_info
+                            )
+                        }) {
+                            statement.make_nop();
                         }
                     }
                     _ => {}
@@ -34,3 +40,15 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
         }
     }
 }
+
+/// A cheap, approximate check to avoid unnecessary `layout_of` calls.
+fn maybe_zst(ty: Ty<'_>) -> bool {
+    match ty.kind() {
+        // maybe ZST (could be more precise)
+        ty::Adt(..) | ty::Array(..) | ty::Closure(..) | ty::Tuple(..) | ty::Opaque(..) => true,
+        // definitely ZST
+        ty::FnDef(..) | ty::Never => true,
+        // unreachable or can't be ZST
+        _ => false,
+    }
+}