about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-01-08 10:28:59 -0500
committerNiko Matsakis <niko@alum.mit.edu>2015-01-08 11:02:24 -0500
commit20744c6b855956eb3d39f5afda332480546f9e28 (patch)
tree9e4412387cec6875e1cdb9852672d68c024244c1
parenta0f53b0a5b5a2e0320689885ee606ea4b61f4c56 (diff)
downloadrust-20744c6b855956eb3d39f5afda332480546f9e28.tar.gz
rust-20744c6b855956eb3d39f5afda332480546f9e28.zip
Allow shift operator to take any integral type (and add a test).
-rw-r--r--src/librustc_typeck/check/mod.rs20
-rw-r--r--src/test/compile-fail/shift-various-bad-types.rs39
-rw-r--r--src/test/run-pass/shift-various-types.rs56
3 files changed, 113 insertions, 2 deletions
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f3778eb0540..a6df676e63c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3208,8 +3208,24 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
             // Shift is a special case: rhs must be uint, no matter what lhs is
-            check_expr_has_type(fcx, &**rhs, fcx.tcx().types.uint);
-            fcx.write_ty(expr.id, lhs_t);
+            check_expr(fcx, &**rhs);
+            let rhs_ty = fcx.expr_ty(&**rhs);
+            let rhs_ty = fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
+            if ty::type_is_integral(rhs_ty) {
+                fcx.write_ty(expr.id, lhs_t);
+            } else {
+                fcx.type_error_message(
+                    expr.span,
+                    |actual| {
+                        format!(
+                            "right-hand-side of a shift operation must have integral type, \
+                             not `{}`",
+                            actual)
+                    },
+                    rhs_ty,
+                    None);
+                fcx.write_ty(expr.id, fcx.tcx().types.err);
+            }
             return;
         }
 
diff --git a/src/test/compile-fail/shift-various-bad-types.rs b/src/test/compile-fail/shift-various-bad-types.rs
new file mode 100644
index 00000000000..6287d79e15d
--- /dev/null
+++ b/src/test/compile-fail/shift-various-bad-types.rs
@@ -0,0 +1,39 @@
+// Copyright 2015 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we can do shifts by any integral type.
+
+struct Panolpy {
+    char: char,
+    str: &'static str,
+}
+
+fn foo(p: &Panolpy) {
+    22 >> p.char;
+    //~^ ERROR right-hand-side of a shift operation must have integral type
+
+    22 >> p.str;
+    //~^ ERROR right-hand-side of a shift operation must have integral type
+
+    22 >> p;
+    //~^ ERROR right-hand-side of a shift operation must have integral type
+
+    // We could be more accepting in the case of a type not yet inferred, but not
+    // known to be an integer, but meh.
+    let x;
+    22 >> x;
+    //~^ ERROR right-hand-side of a shift operation must have integral type
+
+    22 >> 1;
+    // Integer literal types are OK
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/shift-various-types.rs b/src/test/run-pass/shift-various-types.rs
new file mode 100644
index 00000000000..3482dd4921b
--- /dev/null
+++ b/src/test/run-pass/shift-various-types.rs
@@ -0,0 +1,56 @@
+// Copyright 2015 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we can do shifts by any integral type.
+
+struct Panolpy {
+    i8: i8,
+    i16: i16,
+    i32: i32,
+    i64: i64,
+    isize: isize,
+
+    u8: u8,
+    u16: u16,
+    u32: u32,
+    u64: u64,
+    usize: usize,
+}
+
+fn foo(p: &Panolpy) {
+    assert_eq!(22 >> p.i8, 11_i8);
+    assert_eq!(22 >> p.i16, 11_i16);
+    assert_eq!(22 >> p.i32, 11_i32);
+    assert_eq!(22 >> p.i64, 11_i64);
+    assert_eq!(22 >> p.isize, 11_is);
+
+    assert_eq!(22 >> p.u8, 11_u8);
+    assert_eq!(22 >> p.u16, 11_u16);
+    assert_eq!(22 >> p.u32, 11_u32);
+    assert_eq!(22 >> p.u64, 11_u64);
+    assert_eq!(22 >> p.usize, 11_us);
+}
+
+fn main() {
+    let p = Panolpy {
+        i8: 1,
+        i16: 1,
+        i32: 1,
+        i64: 1,
+        isize: 1,
+
+        u8: 1,
+        u16: 1,
+        u32: 1,
+        u64: 1,
+        usize: 1,
+    };
+    foo(&p)
+}