mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 18:23:49 +00:00
Dedup some type checks in the MIR validator
This commit is contained in:
parent
3fd8501823
commit
c780e55995
@ -9,29 +9,7 @@ use rustc_middle::mir::interpret::{InterpResult, Scalar};
|
|||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
|
|
||||||
use super::{ImmTy, InterpCx, Machine};
|
use super::{ImmTy, InterpCx, Machine};
|
||||||
|
use crate::util;
|
||||||
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
|
||||||
/// same type as the result.
|
|
||||||
#[inline]
|
|
||||||
fn binop_left_homogeneous(op: mir::BinOp) -> bool {
|
|
||||||
use rustc_middle::mir::BinOp::*;
|
|
||||||
match op {
|
|
||||||
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
|
||||||
| BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
|
|
||||||
Eq | Ne | Lt | Le | Gt | Ge => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
|
|
||||||
/// same type as the LHS.
|
|
||||||
#[inline]
|
|
||||||
fn binop_right_homogeneous(op: mir::BinOp) -> bool {
|
|
||||||
use rustc_middle::mir::BinOp::*;
|
|
||||||
match op {
|
|
||||||
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
|
||||||
| BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
|
|
||||||
Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
/// Returns `true` as long as there are more things to do.
|
/// Returns `true` as long as there are more things to do.
|
||||||
@ -181,9 +159,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BinaryOp(bin_op, box (ref left, ref right)) => {
|
BinaryOp(bin_op, box (ref left, ref right)) => {
|
||||||
let layout = binop_left_homogeneous(bin_op).then_some(dest.layout);
|
let layout = util::binop_left_homogeneous(bin_op).then_some(dest.layout);
|
||||||
let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
|
let left = self.read_immediate(&self.eval_operand(left, layout)?)?;
|
||||||
let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
|
let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
|
||||||
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
||||||
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
|
self.binop_ignore_overflow(bin_op, &left, &right, &dest)?;
|
||||||
}
|
}
|
||||||
@ -191,7 +169,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
|
CheckedBinaryOp(bin_op, box (ref left, ref right)) => {
|
||||||
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
|
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
|
||||||
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
|
let left = self.read_immediate(&self.eval_operand(left, None)?)?;
|
||||||
let layout = binop_right_homogeneous(bin_op).then_some(left.layout);
|
let layout = util::binop_right_homogeneous(bin_op).then_some(left.layout);
|
||||||
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
let right = self.read_immediate(&self.eval_operand(right, layout)?)?;
|
||||||
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
|
self.binop_with_overflow(bin_op, &left, &right, &dest)?;
|
||||||
}
|
}
|
||||||
|
@ -498,8 +498,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
|
|
||||||
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||||
macro_rules! check_kinds {
|
macro_rules! check_kinds {
|
||||||
($t:expr, $text:literal, $($patterns:tt)*) => {
|
($t:expr, $text:literal, $typat:pat) => {
|
||||||
if !matches!(($t).kind(), $($patterns)*) {
|
if !matches!(($t).kind(), $typat) {
|
||||||
self.fail(location, format!($text, $t));
|
self.fail(location, format!($text, $t));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -527,6 +527,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
use BinOp::*;
|
use BinOp::*;
|
||||||
let a = vals.0.ty(&self.body.local_decls, self.tcx);
|
let a = vals.0.ty(&self.body.local_decls, self.tcx);
|
||||||
let b = vals.1.ty(&self.body.local_decls, self.tcx);
|
let b = vals.1.ty(&self.body.local_decls, self.tcx);
|
||||||
|
if crate::util::binop_right_homogeneous(*op) {
|
||||||
|
if let Eq | Lt | Le | Ne | Ge | Gt = op {
|
||||||
|
// The function pointer types can have lifetimes
|
||||||
|
if !self.mir_assign_valid_types(a, b) {
|
||||||
|
self.fail(
|
||||||
|
location,
|
||||||
|
format!("Cannot {op:?} compare incompatible types {a:?} and {b:?}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if a != b {
|
||||||
|
self.fail(
|
||||||
|
location,
|
||||||
|
format!(
|
||||||
|
"Cannot perform binary op {op:?} on unequal types {a:?} and {b:?}"
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
Offset => {
|
Offset => {
|
||||||
check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
|
check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
|
||||||
@ -538,7 +557,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
for x in [a, b] {
|
for x in [a, b] {
|
||||||
check_kinds!(
|
check_kinds!(
|
||||||
x,
|
x,
|
||||||
"Cannot compare type {:?}",
|
"Cannot {op:?} compare type {:?}",
|
||||||
ty::Bool
|
ty::Bool
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::Int(..)
|
| ty::Int(..)
|
||||||
@ -548,19 +567,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
| ty::FnPtr(..)
|
| ty::FnPtr(..)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// The function pointer types can have lifetimes
|
|
||||||
if !self.mir_assign_valid_types(a, b) {
|
|
||||||
self.fail(
|
|
||||||
location,
|
|
||||||
format!("Cannot compare unequal types {:?} and {:?}", a, b),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Shl | ShlUnchecked | Shr | ShrUnchecked => {
|
AddUnchecked | SubUnchecked | MulUnchecked | Shl | ShlUnchecked | Shr
|
||||||
|
| ShrUnchecked => {
|
||||||
for x in [a, b] {
|
for x in [a, b] {
|
||||||
check_kinds!(
|
check_kinds!(
|
||||||
x,
|
x,
|
||||||
"Cannot shift non-integer type {:?}",
|
"Cannot {op:?} non-integer type {:?}",
|
||||||
ty::Uint(..) | ty::Int(..)
|
ty::Uint(..) | ty::Int(..)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -569,55 +582,19 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
|||||||
for x in [a, b] {
|
for x in [a, b] {
|
||||||
check_kinds!(
|
check_kinds!(
|
||||||
x,
|
x,
|
||||||
"Cannot perform bitwise op on type {:?}",
|
"Cannot perform bitwise op {op:?} on type {:?}",
|
||||||
ty::Uint(..) | ty::Int(..) | ty::Bool
|
ty::Uint(..) | ty::Int(..) | ty::Bool
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if a != b {
|
|
||||||
self.fail(
|
|
||||||
location,
|
|
||||||
format!(
|
|
||||||
"Cannot perform bitwise op on unequal types {:?} and {:?}",
|
|
||||||
a, b
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Add | Sub | Mul | Div | Rem => {
|
Add | Sub | Mul | Div | Rem => {
|
||||||
for x in [a, b] {
|
for x in [a, b] {
|
||||||
check_kinds!(
|
check_kinds!(
|
||||||
x,
|
x,
|
||||||
"Cannot perform arithmetic on type {:?}",
|
"Cannot perform arithmetic {op:?} on type {:?}",
|
||||||
ty::Uint(..) | ty::Int(..) | ty::Float(..)
|
ty::Uint(..) | ty::Int(..) | ty::Float(..)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if a != b {
|
|
||||||
self.fail(
|
|
||||||
location,
|
|
||||||
format!(
|
|
||||||
"Cannot perform arithmetic on unequal types {:?} and {:?}",
|
|
||||||
a, b
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AddUnchecked | SubUnchecked | MulUnchecked => {
|
|
||||||
for x in [a, b] {
|
|
||||||
check_kinds!(
|
|
||||||
x,
|
|
||||||
"Cannot perform unchecked arithmetic on type {:?}",
|
|
||||||
ty::Uint(..) | ty::Int(..)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if a != b {
|
|
||||||
self.fail(
|
|
||||||
location,
|
|
||||||
format!(
|
|
||||||
"Cannot perform unchecked arithmetic on unequal types {:?} and {:?}",
|
|
||||||
a, b
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use rustc_middle::mir;
|
||||||
|
|
||||||
mod alignment;
|
mod alignment;
|
||||||
mod check_validity_requirement;
|
mod check_validity_requirement;
|
||||||
mod compare_types;
|
mod compare_types;
|
||||||
@ -7,3 +9,27 @@ pub use self::alignment::is_disaligned;
|
|||||||
pub use self::check_validity_requirement::check_validity_requirement;
|
pub use self::check_validity_requirement::check_validity_requirement;
|
||||||
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
|
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
|
||||||
pub use self::type_name::type_name;
|
pub use self::type_name::type_name;
|
||||||
|
|
||||||
|
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
||||||
|
/// same type as the result.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn binop_left_homogeneous(op: mir::BinOp) -> bool {
|
||||||
|
use rustc_middle::mir::BinOp::*;
|
||||||
|
match op {
|
||||||
|
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||||
|
| BitAnd | BitOr | Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => true,
|
||||||
|
Eq | Ne | Lt | Le | Gt | Ge => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Classify whether an operator is "right-homogeneous", i.e., the RHS has the
|
||||||
|
/// same type as the LHS.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn binop_right_homogeneous(op: mir::BinOp) -> bool {
|
||||||
|
use rustc_middle::mir::BinOp::*;
|
||||||
|
match op {
|
||||||
|
Add | AddUnchecked | Sub | SubUnchecked | Mul | MulUnchecked | Div | Rem | BitXor
|
||||||
|
| BitAnd | BitOr | Eq | Ne | Lt | Le | Gt | Ge => true,
|
||||||
|
Offset | Shl | ShlUnchecked | Shr | ShrUnchecked => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user