Rollup merge of #85934 - tmiasko:is-union, r=jackh726
Add `Ty::is_union` predicate
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user