From 20744c6b855956eb3d39f5afda332480546f9e28 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 8 Jan 2015 10:28:59 -0500 Subject: [PATCH] Allow shift operator to take any integral type (and add a test). --- src/librustc_typeck/check/mod.rs | 20 ++++++- .../compile-fail/shift-various-bad-types.rs | 39 +++++++++++++ src/test/run-pass/shift-various-types.rs | 56 +++++++++++++++++++ 3 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/shift-various-bad-types.rs create mode 100644 src/test/run-pass/shift-various-types.rs 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 or the MIT license +// , 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 or the MIT license +// , 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) +}