Change:
Currently overlong bit shifts are undefined behavior because that's how llvm rolls--. But even when they aren't, we should warn on something like where happens to be , since it's a useless operation that couldn't possibly return anything interesting. There's a and I imagine it'd be a common gotcha since other languages tend to read unadorned integral literals as 32bit s and then promote the in before doing the actual shift.
I think this can be closed, resolved in
Hooray!

Discussion:
use middle::typeck::astconv::ast_ty_to_ty; use middle::typeck::infer; use middle::{typeck, ty, def, pat_util, stability}; <ins> use middle::const_eval::{eval_const_expr_partial, const_int, const_uint}; </ins> use util::ppaux::{ty_to_string}; use util::nodemap::NodeSet; use lint::{Context, LintPass, LintArray};

use std::collections::HashMap; use std::collections::hashmap::{Occupied, Vacant}; use std::slice; <del> use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; </del> <ins> use std::{int, i8, i16, i32, i64, uint, u8, u16, u32, u64, f32, f64}; </ins> use syntax::abi; use syntax::ast_map; <ins> use syntax::ast_util::is_shift_binop; </ins> use syntax::attr::AttrMetaMethods; use syntax::attr; use syntax::codemap::Span; use syntax::parse::token; use syntax::{ast, ast_util, visit}; <ins> use syntax::ast::{TyI, TyU, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64}; </ins> use syntax::ptr::P; use syntax::visit::Visitor;

declare_lint!(OVERFLOWING_LITERALS, Warn, "literal out of range for its type") <ins> declare_lint!(EXCEEDING_BITSHIFTS, Deny, "shift exceeds the type's number of bits") </ins> pub struct TypeLimits { /// Id of the last visited negated expression negated_expr_id: ast::NodeId,

impl LintPass for TypeLimits { fn get_lints(&self) -> LintArray { <del> lint_array!(UNSIGNED_NEGATION, UNUSED_COMPARISONS, OVERFLOWING_LITERALS) </del> <ins> lint_array!(UNSIGNED_NEGATION, UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) </ins> } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {

cx.span_lint(UNUSED_COMPARISONS, e.span, "comparison is useless due to type limits"); } <ins> if is_shift_binop(binop) { let opt_ty_bits = match ty::get(ty::expr_ty(cx.tcx, &**l)).sty { ty::ty_int(t) => Some(int_ty_bits(t)), ty::ty_uint(t) => Some(uint_ty_bits(t)), _ => None }; if let Some(bits) = opt_ty_bits { let exceeding = if let ast::ExprLit(ref lit) = r.node { if let ast::LitInt(shift, _) = lit.node { shift > bits } else { false } } else { match eval_const_expr_partial(cx.tcx, &**r) { Ok(const_int(shift)) => { shift as u64 > bits }, Ok(const_uint(shift)) => { shift > bits }, _ => { false } } }; if exceeding { cx.span_lint(EXCEEDING_BITSHIFTS, e.span, "bitshift exceeds the type's number of bits"); } }; } </ins> }, ast::ExprLit(ref lit) => { match ty::get(ty::expr_ty(cx.tcx, e)).sty {

} } <ins> fn int_ty_bits(int_ty: ast::IntTy) -> u64 { match int_ty { ast::TyI =>    int::BITS as u64, ast::TyI8 =>   i8::BITS  as u64, ast::TyI16 =>  i16::BITS as u64, ast::TyI32 =>  i32::BITS as u64, ast::TyI64 =>  i64::BITS as u64 } } fn uint_ty_bits(uint_ty: ast::UintTy) -> u64 { match uint_ty { ast::TyU =>    uint::BITS as u64, ast::TyU8 =>   u8::BITS  as u64, ast::TyU16 =>  u16::BITS as u64, ast::TyU32 =>  u32::BITS as u64, ast::TyU64 =>  u64::BITS as u64 } } </ins> fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp, l: &ast::Expr, r: &ast::Expr) -> bool { let (lit, expr, swap) = match (&l.node, &r.node) {

// error-pattern: too big for the current fn main() { <del> let fat : [u8, ..(1<<61)+(1<<31)] = [0, ..(1<<61)+(1<<31)]; </del> <ins> let fat : [u8, ..(1<<61)+(1<<31)] = [0, ..(1u64<<61) as uint +(1u64<<31) as uint]; </ins> }

<ins> // Copyright 2014 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. #![deny(exceeding_bitshifts)] #![allow(unused_variables)] fn main() { let n = 1u8 << 8; let n = 1u8 << 9;   //~ ERROR: bitshift exceeds the type's number of bits let n = 1u16 << 16; let n = 1u16 << 17; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u32 << 32; let n = 1u32 << 33; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u64 << 64; let n = 1u64 << 65; //~ ERROR: bitshift exceeds the type's number of bits let n = 1i8 << 8; let n = 1i8 << 9;   //~ ERROR: bitshift exceeds the type's number of bits let n = 1i16 << 16; let n = 1i16 << 17; //~ ERROR: bitshift exceeds the type's number of bits let n = 1i32 << 32; let n = 1i32 << 33; //~ ERROR: bitshift exceeds the type's number of bits let n = 1i64 << 64; let n = 1i64 << 65; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u8 >> 8; let n = 1u8 >> 9;   //~ ERROR: bitshift exceeds the type's number of bits let n = 1u16 >> 16; let n = 1u16 >> 17; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u32 >> 32; let n = 1u32 >> 33; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u64 >> 64; let n = 1u64 >> 65; //~ ERROR: bitshift exceeds the type's number of bits let n = 1i8 >> 8; let n = 1i8 >> 9;   //~ ERROR: bitshift exceeds the type's number of bits let n = 1i16 >> 16; let n = 1i16 >> 17; //~ ERROR: bitshift exceeds the type's number of bits let n = 1i32 >> 32; let n = 1i32 >> 33; //~ ERROR: bitshift exceeds the type's number of bits let n = 1i64 >> 64; let n = 1i64 >> 65; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u8; let n = n << 8; let n = n << 9; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u8 << -9; //~ ERROR: bitshift exceeds the type's number of bits let n = 1u8 << (4+4); let n = 1u8 << (4+5); //~ ERROR: bitshift exceeds the type's number of bits } </ins>