Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Ty::is_union predicate #85934

Merged
merged 2 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -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);
}
}
}
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