Skip to content

Commit

Permalink
Rollup merge of rust-lang#85934 - tmiasko:is-union, r=jackh726
Browse files Browse the repository at this point in the history
Add `Ty::is_union` predicate
  • Loading branch information
Dylan-DPC committed Jun 3, 2021
2 parents c11e324 + c898681 commit 2390917
Show file tree
Hide file tree
Showing 10 changed files with 32 additions and 59 deletions.
10 changes: 6 additions & 4 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1837,10 +1837,12 @@ impl<'tcx> TyS<'tcx> {

#[inline]
pub fn is_enum(&self) -> bool {
match self.kind() {
Adt(adt_def, _) => adt_def.is_enum(),
_ => false,
}
matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
}

#[inline]
pub fn is_union(&self) -> bool {
matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union())
}

#[inline]
Expand Down
12 changes: 5 additions & 7 deletions compiler/rustc_mir/src/borrow_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
19 changes: 8 additions & 11 deletions compiler/rustc_mir/src/borrow_check/places_conflict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_mir/src/dataflow/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_mir/src/transform/check_consts/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,12 +752,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);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir/src/transform/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 3 additions & 12 deletions compiler/rustc_mir/src/transform/dest_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
}
}
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_mir/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
11 changes: 2 additions & 9 deletions compiler/rustc_mir/src/transform/remove_zsts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/place_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2390917

Please sign in to comment.