Skip to content

Commit d68f0df

Browse files
committed
fix rust-lang#106138, extend Infer ty for binary operators
1 parent 04a41f8 commit d68f0df

File tree

3 files changed

+69
-16
lines changed

3 files changed

+69
-16
lines changed

compiler/rustc_const_eval/src/transform/validate.rs

+2-16
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::mir::{
1111
traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping,
1212
Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef,
1313
ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
14-
Terminator, TerminatorKind, UnOp, START_BLOCK,
14+
Terminator, TerminatorKind, START_BLOCK,
1515
};
1616
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitable};
1717
use rustc_mir_dataflow::impls::MaybeStorageLive;
@@ -573,21 +573,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
573573
_ => self.fail(location, format!("There is no checked version of {:?}", op)),
574574
}
575575
}
576-
Rvalue::UnaryOp(op, operand) => {
577-
let a = operand.ty(&self.body.local_decls, self.tcx);
578-
match op {
579-
UnOp::Neg => {
580-
check_kinds!(a, "Cannot negate type {:?}", ty::Int(..) | ty::Float(..))
581-
}
582-
UnOp::Not => {
583-
check_kinds!(
584-
a,
585-
"Cannot binary not type {:?}",
586-
ty::Int(..) | ty::Uint(..) | ty::Bool
587-
);
588-
}
589-
}
590-
}
576+
Rvalue::UnaryOp(..) => {}
591577
Rvalue::ShallowInitBox(operand, _) => {
592578
let a = operand.ty(&self.body.local_decls, self.tcx);
593579
check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..));

compiler/rustc_hir_typeck/src/expr.rs

+7
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
383383
let mut oprnd_t = self.check_expr_with_expectation(&oprnd, expected_inner);
384384

385385
if !oprnd_t.references_error() {
386+
match (unop, oprnd_t.kind()) {
387+
(hir::UnOp::Not | hir::UnOp::Neg, ty::Infer(ty::TyVar(_))) => {
388+
return oprnd_t;
389+
}
390+
_ => {}
391+
}
392+
386393
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
387394
match unop {
388395
hir::UnOp::Deref => {

tests/ui/inference/issue-106138.rs

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// check-pass
2+
3+
fn myfunction(x: &Vec<bool>, y: &Vec<i32> ) {
4+
let one = |i, a: &Vec<bool>| {
5+
a[i] // ok
6+
};
7+
8+
let two = |i, a: &Vec<bool>| {
9+
!a[i] // cannot infer type
10+
};
11+
12+
let three = |i, b: &Vec<i32>| {
13+
-b[i] // ok
14+
};
15+
16+
let r = one(0, x);
17+
assert_eq!(r, x[0]);
18+
let r = two(0, x);
19+
assert_eq!(r, !x[0]);
20+
let r = three(0, y);
21+
assert_eq!(r, -y[0]);
22+
}
23+
24+
fn bools(x: &Vec<bool>) {
25+
let binary = |i, a: &Vec<bool>| {
26+
a[i] && a[i+1] // ok
27+
};
28+
29+
let unary = |i, a: &Vec<bool>| {
30+
!a[i] // cannot infer type
31+
};
32+
33+
let r = binary(0, x);
34+
assert_eq!(r, x[0] && x[1]);
35+
36+
let r = unary(0, x);
37+
assert_eq!(r, !x[0]);
38+
}
39+
40+
fn ints(x: &Vec<i32>) {
41+
let binary = |i, a: &Vec<i32>| {
42+
a[i] + a[i+1] // ok
43+
};
44+
let unary = |i, a: &Vec<i32>| {
45+
-a[i] // cannot infer type
46+
};
47+
48+
let r = binary(0, x);
49+
assert_eq!(r, x[0] + x[1]);
50+
let r = unary(0, x);
51+
assert_eq!(r, -x[0]);
52+
}
53+
54+
fn main() {
55+
let x = vec![true, false];
56+
let y = vec![1, 2, 3];
57+
myfunction(&x, &y);
58+
bools(&x);
59+
ints(&y);
60+
}

0 commit comments

Comments
 (0)