Skip to content

Commit bbbdb5b

Browse files
committed
Auto merge of #39812 - larsluthman:const-eval-bugfix, r=nrc
Fix type hint bug in eval_const_expr_partial() (issue #39548) When evaluating const expressions for things like array lengths, rustc assumes that the operands in comparison expressions (a < b, a == b, a >= b etc) are booleans and sets their type hints accordingly, causing an incorrect compilation error in the case "(FOO < 4)" with "const FOO: i32 = 3" and a compiler panic in the case "(3 < 4)". This fix makes sure that rustc does not assume anything about the types of those operands.
2 parents fc6f092 + 3a209dd commit bbbdb5b

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

src/librustc_const_eval/eval.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -519,15 +519,23 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
519519
}
520520
hir::ExprUnary(hir::UnDeref, _) => signal!(e, UnimplementedConstVal("deref operation")),
521521
hir::ExprBinary(op, ref a, ref b) => {
522-
let b_ty = match op.node {
523-
hir::BiShl | hir::BiShr => ty_hint.erase_hint(),
524-
_ => ty_hint
522+
// Use the same type hint for the operands as for the whole
523+
// expression, except when the operation is a shift, in which
524+
// case we use no type hint for the RHS, and when the operation
525+
// is a comparison, in which case we use no type hint for
526+
// either operand.
527+
let (a_ty, b_ty) = match op.node {
528+
hir::BiShl | hir::BiShr => (ty_hint, ty_hint.erase_hint()),
529+
hir::BiEq | hir::BiLe | hir::BiLt |
530+
hir::BiNe | hir::BiGe | hir::BiGt =>
531+
(ty_hint.erase_hint(), ty_hint.erase_hint()),
532+
_ => (ty_hint, ty_hint)
525533
};
526534
// technically, if we don't have type hints, but integral eval
527535
// gives us a type through a type-suffix, cast or const def type
528536
// we need to re-eval the other value of the BinOp if it was
529537
// not inferred
530-
match (cx.eval(a, ty_hint)?,
538+
match (cx.eval(a, a_ty)?,
531539
cx.eval(b, b_ty)?) {
532540
(Float(a), Float(b)) => {
533541
use std::cmp::Ordering::*;

src/test/run-pass/issue-39548.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
fn main() {
13+
let _ : [(); ((1 < 2) == false) as usize] = [];
14+
}

0 commit comments

Comments
 (0)