Auto merge of #14705 - HKalbasi:mir, r=lnicola
Fix some mir related bugs fix #14701 fix #14704
This commit is contained in:
commit
86b14c2458
@ -505,6 +505,7 @@ impl ExprCollector<'_> {
|
|||||||
.map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it)));
|
.map(|it| Interned::new(TypeRef::from_ast(&this.ctx(), it)));
|
||||||
|
|
||||||
let prev_is_lowering_generator = mem::take(&mut this.is_lowering_generator);
|
let prev_is_lowering_generator = mem::take(&mut this.is_lowering_generator);
|
||||||
|
let prev_try_block_label = this.current_try_block_label.take();
|
||||||
|
|
||||||
let body = this.collect_expr_opt(e.body());
|
let body = this.collect_expr_opt(e.body());
|
||||||
|
|
||||||
@ -520,11 +521,11 @@ impl ExprCollector<'_> {
|
|||||||
} else {
|
} else {
|
||||||
ClosureKind::Closure
|
ClosureKind::Closure
|
||||||
};
|
};
|
||||||
this.is_lowering_generator = prev_is_lowering_generator;
|
|
||||||
let capture_by =
|
let capture_by =
|
||||||
if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref };
|
if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref };
|
||||||
this.is_lowering_generator = prev_is_lowering_generator;
|
this.is_lowering_generator = prev_is_lowering_generator;
|
||||||
this.current_binding_owner = prev_binding_owner;
|
this.current_binding_owner = prev_binding_owner;
|
||||||
|
this.current_try_block_label = prev_try_block_label;
|
||||||
this.body.exprs[result_expr_id] = Expr::Closure {
|
this.body.exprs[result_expr_id] = Expr::Closure {
|
||||||
args: args.into(),
|
args: args.into(),
|
||||||
arg_types: arg_types.into(),
|
arg_types: arg_types.into(),
|
||||||
|
@ -97,8 +97,22 @@ fn bit_op() {
|
|||||||
check_number(r#"const GOAL: u8 = !0 & !(!0 >> 1)"#, 128);
|
check_number(r#"const GOAL: u8 = !0 & !(!0 >> 1)"#, 128);
|
||||||
check_number(r#"const GOAL: i8 = !0 & !(!0 >> 1)"#, 0);
|
check_number(r#"const GOAL: i8 = !0 & !(!0 >> 1)"#, 0);
|
||||||
check_number(r#"const GOAL: i8 = 1 << 7"#, (1i8 << 7) as i128);
|
check_number(r#"const GOAL: i8 = 1 << 7"#, (1i8 << 7) as i128);
|
||||||
// FIXME: report panic here
|
check_number(r#"const GOAL: i8 = -1 << 2"#, (-1i8 << 2) as i128);
|
||||||
check_number(r#"const GOAL: i8 = 1 << 8"#, 0);
|
check_fail(r#"const GOAL: i8 = 1 << 8"#, |e| {
|
||||||
|
e == ConstEvalError::MirEvalError(MirEvalError::Panic("Overflow in Shl".to_string()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn floating_point() {
|
||||||
|
check_number(
|
||||||
|
r#"const GOAL: f64 = 2.0 + 3.0 * 5.5 - 8.;"#,
|
||||||
|
i128::from_le_bytes(pad16(&f64::to_le_bytes(10.5), true)),
|
||||||
|
);
|
||||||
|
check_number(
|
||||||
|
r#"const GOAL: f32 = 2.0 + 3.0 * 5.5 - 8.;"#,
|
||||||
|
i128::from_le_bytes(pad16(&f32::to_le_bytes(10.5), true)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -649,6 +649,20 @@ pub enum BinOp {
|
|||||||
Offset,
|
Offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BinOp {
|
||||||
|
fn run_compare<T: PartialEq + PartialOrd>(&self, l: T, r: T) -> bool {
|
||||||
|
match self {
|
||||||
|
BinOp::Ge => l >= r,
|
||||||
|
BinOp::Gt => l > r,
|
||||||
|
BinOp::Le => l <= r,
|
||||||
|
BinOp::Lt => l < r,
|
||||||
|
BinOp::Eq => l == r,
|
||||||
|
BinOp::Ne => l != r,
|
||||||
|
x => panic!("`run_compare` called on operator {x:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for BinOp {
|
impl Display for BinOp {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.write_str(match self {
|
f.write_str(match self {
|
||||||
|
@ -48,7 +48,7 @@ macro_rules! from_bytes {
|
|||||||
($ty:tt, $value:expr) => {
|
($ty:tt, $value:expr) => {
|
||||||
($ty::from_le_bytes(match ($value).try_into() {
|
($ty::from_le_bytes(match ($value).try_into() {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => return Err(MirEvalError::TypeError("mismatched size")),
|
Err(_) => return Err(MirEvalError::TypeError(stringify!(mismatched size in constructing $ty))),
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -797,21 +797,82 @@ impl Evaluator<'_> {
|
|||||||
lc = self.read_memory(Address::from_bytes(lc)?, size)?;
|
lc = self.read_memory(Address::from_bytes(lc)?, size)?;
|
||||||
rc = self.read_memory(Address::from_bytes(rc)?, size)?;
|
rc = self.read_memory(Address::from_bytes(rc)?, size)?;
|
||||||
}
|
}
|
||||||
|
if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) {
|
||||||
|
match f {
|
||||||
|
chalk_ir::FloatTy::F32 => {
|
||||||
|
let l = from_bytes!(f32, lc);
|
||||||
|
let r = from_bytes!(f32, rc);
|
||||||
|
match op {
|
||||||
|
BinOp::Ge
|
||||||
|
| BinOp::Gt
|
||||||
|
| BinOp::Le
|
||||||
|
| BinOp::Lt
|
||||||
|
| BinOp::Eq
|
||||||
|
| BinOp::Ne => {
|
||||||
|
let r = op.run_compare(l, r) as u8;
|
||||||
|
Owned(vec![r])
|
||||||
|
}
|
||||||
|
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div => {
|
||||||
|
let r = match op {
|
||||||
|
BinOp::Add => l + r,
|
||||||
|
BinOp::Sub => l - r,
|
||||||
|
BinOp::Mul => l * r,
|
||||||
|
BinOp::Div => l / r,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
Owned(r.to_le_bytes().into())
|
||||||
|
}
|
||||||
|
x => not_supported!(
|
||||||
|
"invalid binop {x:?} on floating point operators"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chalk_ir::FloatTy::F64 => {
|
||||||
|
let l = from_bytes!(f64, lc);
|
||||||
|
let r = from_bytes!(f64, rc);
|
||||||
|
match op {
|
||||||
|
BinOp::Ge
|
||||||
|
| BinOp::Gt
|
||||||
|
| BinOp::Le
|
||||||
|
| BinOp::Lt
|
||||||
|
| BinOp::Eq
|
||||||
|
| BinOp::Ne => {
|
||||||
|
let r = op.run_compare(l, r) as u8;
|
||||||
|
Owned(vec![r])
|
||||||
|
}
|
||||||
|
BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div => {
|
||||||
|
let r = match op {
|
||||||
|
BinOp::Add => l + r,
|
||||||
|
BinOp::Sub => l - r,
|
||||||
|
BinOp::Mul => l * r,
|
||||||
|
BinOp::Div => l / r,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
Owned(r.to_le_bytes().into())
|
||||||
|
}
|
||||||
|
x => not_supported!(
|
||||||
|
"invalid binop {x:?} on floating point operators"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_)));
|
let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_)));
|
||||||
let l128 = i128::from_le_bytes(pad16(lc, is_signed));
|
let l128 = i128::from_le_bytes(pad16(lc, is_signed));
|
||||||
let r128 = i128::from_le_bytes(pad16(rc, is_signed));
|
let r128 = i128::from_le_bytes(pad16(rc, is_signed));
|
||||||
|
let check_overflow = |r: i128| {
|
||||||
|
// FIXME: this is not very correct, and only catches the basic cases.
|
||||||
|
let r = r.to_le_bytes();
|
||||||
|
for &k in &r[lc.len()..] {
|
||||||
|
if k != 0 && (k != 255 || !is_signed) {
|
||||||
|
return Err(MirEvalError::Panic(format!("Overflow in {op:?}")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Owned(r[0..lc.len()].into()))
|
||||||
|
};
|
||||||
match op {
|
match op {
|
||||||
BinOp::Ge | BinOp::Gt | BinOp::Le | BinOp::Lt | BinOp::Eq | BinOp::Ne => {
|
BinOp::Ge | BinOp::Gt | BinOp::Le | BinOp::Lt | BinOp::Eq | BinOp::Ne => {
|
||||||
let r = match op {
|
let r = op.run_compare(l128, r128) as u8;
|
||||||
BinOp::Ge => l128 >= r128,
|
|
||||||
BinOp::Gt => l128 > r128,
|
|
||||||
BinOp::Le => l128 <= r128,
|
|
||||||
BinOp::Lt => l128 < r128,
|
|
||||||
BinOp::Eq => l128 == r128,
|
|
||||||
BinOp::Ne => l128 != r128,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let r = r as u8;
|
|
||||||
Owned(vec![r])
|
Owned(vec![r])
|
||||||
}
|
}
|
||||||
BinOp::BitAnd
|
BinOp::BitAnd
|
||||||
@ -837,32 +898,28 @@ impl Evaluator<'_> {
|
|||||||
BinOp::BitXor => l128 ^ r128,
|
BinOp::BitXor => l128 ^ r128,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
let r = r.to_le_bytes();
|
check_overflow(r)?
|
||||||
for &k in &r[lc.len()..] {
|
|
||||||
if k != 0 && (k != 255 || !is_signed) {
|
|
||||||
return Err(MirEvalError::Panic(format!("Overflow in {op:?}")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Owned(r[0..lc.len()].into())
|
|
||||||
}
|
}
|
||||||
BinOp::Shl | BinOp::Shr => {
|
BinOp::Shl | BinOp::Shr => {
|
||||||
let shift_amount = if r128 < 0 {
|
let r = 'b: {
|
||||||
return Err(MirEvalError::Panic(format!("Overflow in {op:?}")));
|
if let Ok(shift_amount) = u32::try_from(r128) {
|
||||||
} else if r128 > 128 {
|
|
||||||
return Err(MirEvalError::Panic(format!("Overflow in {op:?}")));
|
|
||||||
} else {
|
|
||||||
r128 as u8
|
|
||||||
};
|
|
||||||
let r = match op {
|
let r = match op {
|
||||||
BinOp::Shl => l128 << shift_amount,
|
BinOp::Shl => l128.checked_shl(shift_amount),
|
||||||
BinOp::Shr => l128 >> shift_amount,
|
BinOp::Shr => l128.checked_shr(shift_amount),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
Owned(r.to_le_bytes()[0..lc.len()].into())
|
if let Some(r) = r {
|
||||||
|
break 'b r;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Err(MirEvalError::Panic(format!("Overflow in {op:?}")));
|
||||||
|
};
|
||||||
|
check_overflow(r)?
|
||||||
}
|
}
|
||||||
BinOp::Offset => not_supported!("offset binop"),
|
BinOp::Offset => not_supported!("offset binop"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Rvalue::Discriminant(p) => {
|
Rvalue::Discriminant(p) => {
|
||||||
let ty = self.place_ty(p, locals)?;
|
let ty = self.place_ty(p, locals)?;
|
||||||
let bytes = self.eval_place(p, locals)?.get(&self)?;
|
let bytes = self.eval_place(p, locals)?.get(&self)?;
|
||||||
|
@ -132,6 +132,24 @@ fn test() {
|
|||||||
// ^^^^^^^ error: can't break with a value in this position
|
// ^^^^^^^ error: can't break with a value in this position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn try_block_desugaring_inside_closure() {
|
||||||
|
// regression test for #14701
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
//- minicore: option, try
|
||||||
|
fn test() {
|
||||||
|
try {
|
||||||
|
|| {
|
||||||
|
let x = Some(2);
|
||||||
|
Some(x?)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user