about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2021-06-02 00:00:00 +0000
committerTomasz Miąsko <tomasz.miasko@gmail.com>2021-06-02 17:09:17 +0200
commitc898681a8683fb5622ec77e1d7ecb641e1cd0328 (patch)
treebe13097fbe6dad91b7600dad3470ad34f8cdc5cc
parent012c32346748f7781ff2143e9f4e53d64f2527d2 (diff)
downloadrust-c898681a8683fb5622ec77e1d7ecb641e1cd0328.tar.gz
rust-c898681a8683fb5622ec77e1d7ecb641e1cd0328.zip
Add `Ty::is_union` predicate and use it
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs5
-rw-r--r--compiler/rustc_mir/src/borrow_check/mod.rs12
-rw-r--r--compiler/rustc_mir/src/borrow_check/places_conflict.rs19
-rw-r--r--compiler/rustc_mir/src/dataflow/move_paths/builder.rs6
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs8
-rw-r--r--compiler/rustc_mir/src/transform/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir/src/transform/dest_prop.rs15
-rw-r--r--compiler/rustc_mir/src/transform/promote_consts.rs6
-rw-r--r--compiler/rustc_mir/src/transform/remove_zsts.rs11
-rw-r--r--compiler/rustc_typeck/src/check/place_op.rs2
10 files changed, 31 insertions, 55 deletions
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 1222ed7b4d6..012d9bd82c8 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1841,6 +1841,11 @@ impl<'tcx> TyS<'tcx> {
     }
 
     #[inline]
+    pub fn is_union(&self) -> bool {
+        matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union())
+    }
+
+    #[inline]
     pub fn is_closure(&self) -> bool {
         matches!(self.kind(), Closure(..))
     }
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs
index 4c35be39a3d..36eb8a4baa8 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/mod.rs
@@ -1965,13 +1965,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
-                if let ty::Adt(def, _) = base.ty(this.body(), tcx).ty.kind() {
-                    if def.is_union() {
-                        if this.move_data.path_map[mpi].iter().any(|moi| {
-                            this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
-                        }) {
-                            return;
-                        }
+                if base.ty(this.body(), tcx).ty.is_union() {
+                    if this.move_data.path_map[mpi].iter().any(|moi| {
+                        this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
+                    }) {
+                        return;
                     }
                 }
 
diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_mir/src/borrow_check/places_conflict.rs
index 3654b51949e..d21550a8e1a 100644
--- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs
+++ b/compiler/rustc_mir/src/borrow_check/places_conflict.rs
@@ -331,17 +331,14 @@ fn place_projection_conflict<'tcx>(
                 Overlap::EqualOrDisjoint
             } else {
                 let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
-                match ty.kind() {
-                    ty::Adt(def, _) if def.is_union() => {
-                        // Different fields of a union, we are basically stuck.
-                        debug!("place_element_conflict: STUCK-UNION");
-                        Overlap::Arbitrary
-                    }
-                    _ => {
-                        // Different fields of a struct (`a.x` vs. `a.y`). Disjoint!
-                        debug!("place_element_conflict: DISJOINT-FIELD");
-                        Overlap::Disjoint
-                    }
+                if ty.is_union() {
+                    // Different fields of a union, we are basically stuck.
+                    debug!("place_element_conflict: STUCK-UNION");
+                    Overlap::Arbitrary
+                } else {
+                    // Different fields of a struct (`a.x` vs. `a.y`). Disjoint!
+                    debug!("place_element_conflict: DISJOINT-FIELD");
+                    Overlap::Disjoint
                 }
             }
         }
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index 1bfbb843114..cea465ea1ed 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -519,10 +519,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
         // Check if we are assigning into a field of a union, if so, lookup the place
         // of the union so it is marked as initialized again.
         if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() {
-            if let ty::Adt(def, _) = place_base.ty(self.builder.body, self.builder.tcx).ty.kind() {
-                if def.is_union() {
-                    place = place_base;
-                }
+            if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() {
+                place = place_base;
             }
         }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 41d9d0d04b5..bff02efc49d 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -753,12 +753,8 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {
                 let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
-                match base_ty.ty_adt_def() {
-                    Some(def) if def.is_union() => {
-                        self.check_op(ops::UnionAccess);
-                    }
-
-                    _ => {}
+                if base_ty.is_union() {
+                    self.check_op(ops::UnionAccess);
                 }
             }
         }
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index 955be8cc81e..8d4316c30b3 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -221,7 +221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
             }
 
             let base_ty = base.ty(self.body, self.tcx).ty;
-            if base_ty.ty_adt_def().map_or(false, |adt| adt.is_union()) {
+            if base_ty.is_union() {
                 // If we did not hit a `Deref` yet and the overall place use is an assignment, the
                 // rules are different.
                 let assign_to_field = !saw_deref
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 29df86ca6cd..4f5a467a6ee 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -114,7 +114,7 @@ use rustc_middle::mir::{
     traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, PlaceElem,
     Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 
 // Empirical measurements have resulted in some observations:
 // - Running on a body with a single block and 500 locals takes barely any time
@@ -910,17 +910,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
 
             // Handle the "subtle case" described above by rejecting any `dest` that is or
             // projects through a union.
-            let is_union = |ty: Ty<'_>| {
-                if let ty::Adt(def, _) = ty.kind() {
-                    if def.is_union() {
-                        return true;
-                    }
-                }
-
-                false
-            };
             let mut place_ty = PlaceTy::from_ty(self.body.local_decls[dest.local].ty);
-            if is_union(place_ty.ty) {
+            if place_ty.ty.is_union() {
                 return;
             }
             for elem in dest.projection {
@@ -930,7 +921,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
                 }
 
                 place_ty = place_ty.projection_ty(self.tcx, elem);
-                if is_union(place_ty.ty) {
+                if place_ty.ty.is_union() {
                     return;
                 }
             }
diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index f6b1323e107..78e84419c62 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -415,11 +415,9 @@ impl<'tcx> Validator<'_, 'tcx> {
 
                     ProjectionElem::Field(..) => {
                         let base_ty = place_base.ty(self.body, self.tcx).ty;
-                        if let Some(def) = base_ty.ty_adt_def() {
+                        if base_ty.is_union() {
                             // No promotion of union field accesses.
-                            if def.is_union() {
-                                return Err(Unpromotable);
-                            }
+                            return Err(Unpromotable);
                         }
                     }
                 }
diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir/src/transform/remove_zsts.rs
index 70f7538dd57..a0f225e6de6 100644
--- a/compiler/rustc_mir/src/transform/remove_zsts.rs
+++ b/compiler/rustc_mir/src/transform/remove_zsts.rs
@@ -69,21 +69,14 @@ fn involves_a_union<'tcx>(
     tcx: TyCtxt<'tcx>,
 ) -> bool {
     let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty);
-    if is_union(place_ty.ty) {
+    if place_ty.ty.is_union() {
         return true;
     }
     for elem in place.projection {
         place_ty = place_ty.projection_ty(tcx, elem);
-        if is_union(place_ty.ty) {
+        if place_ty.ty.is_union() {
             return true;
         }
     }
     return false;
 }
-
-fn is_union(ty: Ty<'_>) -> bool {
-    match ty.kind() {
-        ty::Adt(def, _) if def.is_union() => true,
-        _ => false,
-    }
-}
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs
index a63aec07ad1..652b82f1063 100644
--- a/compiler/rustc_typeck/src/check/place_op.rs
+++ b/compiler/rustc_typeck/src/check/place_op.rs
@@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Clear previous flag; after a pointer indirection it does not apply any more.
                 inside_union = false;
             }
-            if source.ty_adt_def().map_or(false, |adt| adt.is_union()) {
+            if source.is_union() {
                 inside_union = true;
             }
             // Fix up the autoderefs. Autorefs can only occur immediately preceding