Rollup merge of #85934 - tmiasko:is-union, r=jackh726

Add `Ty::is_union` predicate
This commit is contained in:
Yuki Okushi
2021-06-03 14:35:41 +09:00
committed by GitHub
10 changed files with 32 additions and 59 deletions

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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,
}
}