diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 34d002d334277..5114cab3f41bb 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -828,93 +828,112 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, } _ => ty_hint }; - match (try!(eval_const_expr_partial(tcx, &**a, ty_hint, fn_args)), - try!(eval_const_expr_partial(tcx, &**b, b_ty, fn_args))) { - (Float(a), Float(b)) => { - match op.node { - hir::BiAdd => Float(a + b), - hir::BiSub => Float(a - b), - hir::BiMul => Float(a * b), - hir::BiDiv => Float(a / b), - hir::BiRem => Float(a % b), - hir::BiEq => fromb(a == b), - hir::BiLt => fromb(a < b), - hir::BiLe => fromb(a <= b), - hir::BiNe => fromb(a != b), - hir::BiGe => fromb(a >= b), - hir::BiGt => fromb(a > b), - _ => signal!(e, InvalidOpForFloats(op.node)) - } - } - (Int(a), Int(b)) => { - match op.node { - hir::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)), - hir::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)), - hir::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)), - hir::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)), - hir::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)), - hir::BiAnd | hir::BiBitAnd => Int(a & b), - hir::BiOr | hir::BiBitOr => Int(a | b), - hir::BiBitXor => Int(a ^ b), - hir::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)), - hir::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)), - hir::BiEq => fromb(a == b), - hir::BiLt => fromb(a < b), - hir::BiLe => fromb(a <= b), - hir::BiNe => fromb(a != b), - hir::BiGe => fromb(a >= b), - hir::BiGt => fromb(a > b) - } - } - (Uint(a), Uint(b)) => { - match op.node { - hir::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)), - hir::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)), - hir::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)), - hir::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)), - hir::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)), - hir::BiAnd | hir::BiBitAnd => Uint(a & b), - hir::BiOr | hir::BiBitOr => Uint(a | b), - hir::BiBitXor => Uint(a ^ b), - hir::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)), - hir::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)), - hir::BiEq => fromb(a == b), - hir::BiLt => fromb(a < b), - hir::BiLe => fromb(a <= b), - hir::BiNe => fromb(a != b), - hir::BiGe => fromb(a >= b), - hir::BiGt => fromb(a > b), + match try!(eval_const_expr_partial(tcx, &**a, ty_hint, fn_args)) { + Bool(a) if op.node == hir::BiAnd => { + if !a { + Bool(a) + } else if let Bool(b) = try!(eval_const_expr_partial(tcx, &**b, b_ty, fn_args)) { + Bool(b) + } else { + signal!(e, MiscBinaryOp) } } - // shifts can have any integral type as their rhs - (Int(a), Uint(b)) => { - match op.node { - hir::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)), - hir::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)), - _ => signal!(e, InvalidOpForIntUint(op.node)), + Bool(a) if op.node == hir::BiOr => { + if a { + Bool(a) + } else if let Bool(b) = try!(eval_const_expr_partial(tcx, &**b, b_ty, fn_args)) { + Bool(b) + } else { + signal!(e, MiscBinaryOp) } } - (Uint(a), Int(b)) => { - match op.node { - hir::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)), - hir::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)), - _ => signal!(e, InvalidOpForUintInt(op.node)), + x => { + match (x, try!(eval_const_expr_partial(tcx, &**b, b_ty, fn_args))) { + (Float(a), Float(b)) => { + match op.node { + hir::BiAdd => Float(a + b), + hir::BiSub => Float(a - b), + hir::BiMul => Float(a * b), + hir::BiDiv => Float(a / b), + hir::BiRem => Float(a % b), + hir::BiEq => fromb(a == b), + hir::BiLt => fromb(a < b), + hir::BiLe => fromb(a <= b), + hir::BiNe => fromb(a != b), + hir::BiGe => fromb(a >= b), + hir::BiGt => fromb(a > b), + _ => signal!(e, InvalidOpForFloats(op.node)) + } + } + (Int(a), Int(b)) => { + match op.node { + hir::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)), + hir::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)), + hir::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)), + hir::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)), + hir::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)), + hir::BiAnd | hir::BiBitAnd => Int(a & b), + hir::BiOr | hir::BiBitOr => Int(a | b), + hir::BiBitXor => Int(a ^ b), + hir::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)), + hir::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)), + hir::BiEq => fromb(a == b), + hir::BiLt => fromb(a < b), + hir::BiLe => fromb(a <= b), + hir::BiNe => fromb(a != b), + hir::BiGe => fromb(a >= b), + hir::BiGt => fromb(a > b) + } + } + (Uint(a), Uint(b)) => { + match op.node { + hir::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)), + hir::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)), + hir::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)), + hir::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)), + hir::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)), + hir::BiAnd | hir::BiBitAnd => Uint(a & b), + hir::BiOr | hir::BiBitOr => Uint(a | b), + hir::BiBitXor => Uint(a ^ b), + hir::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)), + hir::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)), + hir::BiEq => fromb(a == b), + hir::BiLt => fromb(a < b), + hir::BiLe => fromb(a <= b), + hir::BiNe => fromb(a != b), + hir::BiGe => fromb(a >= b), + hir::BiGt => fromb(a > b), + } + } + // shifts can have any integral type as their rhs + (Int(a), Uint(b)) => { + match op.node { + hir::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)), + hir::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)), + _ => signal!(e, InvalidOpForIntUint(op.node)), + } + } + (Uint(a), Int(b)) => { + match op.node { + hir::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)), + hir::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)), + _ => signal!(e, InvalidOpForUintInt(op.node)), + } + } + (Bool(a), Bool(b)) => { + Bool(match op.node { + hir::BiBitXor => a ^ b, + hir::BiBitAnd => a & b, + hir::BiBitOr => a | b, + hir::BiEq => a == b, + hir::BiNe => a != b, + _ => signal!(e, InvalidOpForBools(op.node)), + }) + } + + _ => signal!(e, MiscBinaryOp), } } - (Bool(a), Bool(b)) => { - Bool(match op.node { - hir::BiAnd => a && b, - hir::BiOr => a || b, - hir::BiBitXor => a ^ b, - hir::BiBitAnd => a & b, - hir::BiBitOr => a | b, - hir::BiEq => a == b, - hir::BiNe => a != b, - _ => signal!(e, InvalidOpForBools(op.node)), - }) - } - - _ => signal!(e, MiscBinaryOp), } } hir::ExprCast(ref base, ref target_ty) => { diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 91f17a50e2c41..07057a35fbbfe 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -591,6 +591,21 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let is_float = ty.is_fp(); let signed = ty.is_signed(); + if ty.is_bool() && (b.node == hir::BiOr || b.node == hir::BiAnd) { + match eval_const_expr_partial(cx.tcx(), + &e1, + ExprTypeChecked, + None) { + Ok(ConstVal::Bool(false)) if b.node == hir::BiAnd => { + return Ok(te1) + } + Ok(ConstVal::Bool(true)) if b.node == hir::BiOr => { + return Ok(te1) + } + _ => () + } + } + let (te2, _) = try!(const_expr(cx, &**e2, param_substs, fn_args, trueconst)); try!(check_binary_expr_validity(cx, e, ty, te1, te2, trueconst)); diff --git a/src/test/run-pass/issue-29608.rs b/src/test/run-pass/issue-29608.rs new file mode 100644 index 0000000000000..9f895ce2b2ee7 --- /dev/null +++ b/src/test/run-pass/issue-29608.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Testcase provided by oli-obk + +const X: bool = false && ((1u8 - 5u8) == 42); + +fn main() { +println!("{}", X); +}