Skip to content

Commit 20744c6

Browse files
committed
Allow shift operator to take any integral type (and add a test).
1 parent a0f53b0 commit 20744c6

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed

src/librustc_typeck/check/mod.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -3208,8 +3208,24 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
32083208

32093209
if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
32103210
// Shift is a special case: rhs must be uint, no matter what lhs is
3211-
check_expr_has_type(fcx, &**rhs, fcx.tcx().types.uint);
3212-
fcx.write_ty(expr.id, lhs_t);
3211+
check_expr(fcx, &**rhs);
3212+
let rhs_ty = fcx.expr_ty(&**rhs);
3213+
let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
3214+
if ty::type_is_integral(rhs_ty) {
3215+
fcx.write_ty(expr.id, lhs_t);
3216+
} else {
3217+
fcx.type_error_message(
3218+
expr.span,
3219+
|actual| {
3220+
format!(
3221+
"right-hand-side of a shift operation must have integral type, \
3222+
not `{}`",
3223+
actual)
3224+
},
3225+
rhs_ty,
3226+
None);
3227+
fcx.write_ty(expr.id, fcx.tcx().types.err);
3228+
}
32133229
return;
32143230
}
32153231

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 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+
// Test that we can do shifts by any integral type.
12+
13+
struct Panolpy {
14+
char: char,
15+
str: &'static str,
16+
}
17+
18+
fn foo(p: &Panolpy) {
19+
22 >> p.char;
20+
//~^ ERROR right-hand-side of a shift operation must have integral type
21+
22+
22 >> p.str;
23+
//~^ ERROR right-hand-side of a shift operation must have integral type
24+
25+
22 >> p;
26+
//~^ ERROR right-hand-side of a shift operation must have integral type
27+
28+
// We could be more accepting in the case of a type not yet inferred, but not
29+
// known to be an integer, but meh.
30+
let x;
31+
22 >> x;
32+
//~^ ERROR right-hand-side of a shift operation must have integral type
33+
34+
22 >> 1;
35+
// Integer literal types are OK
36+
}
37+
38+
fn main() {
39+
}
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2015 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+
// Test that we can do shifts by any integral type.
12+
13+
struct Panolpy {
14+
i8: i8,
15+
i16: i16,
16+
i32: i32,
17+
i64: i64,
18+
isize: isize,
19+
20+
u8: u8,
21+
u16: u16,
22+
u32: u32,
23+
u64: u64,
24+
usize: usize,
25+
}
26+
27+
fn foo(p: &Panolpy) {
28+
assert_eq!(22 >> p.i8, 11_i8);
29+
assert_eq!(22 >> p.i16, 11_i16);
30+
assert_eq!(22 >> p.i32, 11_i32);
31+
assert_eq!(22 >> p.i64, 11_i64);
32+
assert_eq!(22 >> p.isize, 11_is);
33+
34+
assert_eq!(22 >> p.u8, 11_u8);
35+
assert_eq!(22 >> p.u16, 11_u16);
36+
assert_eq!(22 >> p.u32, 11_u32);
37+
assert_eq!(22 >> p.u64, 11_u64);
38+
assert_eq!(22 >> p.usize, 11_us);
39+
}
40+
41+
fn main() {
42+
let p = Panolpy {
43+
i8: 1,
44+
i16: 1,
45+
i32: 1,
46+
i64: 1,
47+
isize: 1,
48+
49+
u8: 1,
50+
u16: 1,
51+
u32: 1,
52+
u64: 1,
53+
usize: 1,
54+
};
55+
foo(&p)
56+
}

0 commit comments

Comments
 (0)