Auto merge of #22940 - Manishearth:rollup, r=Manishearth
This commit is contained in:
commit
4b3b02f8f4
32 changed files with 592 additions and 329 deletions
|
@ -39,7 +39,7 @@
|
|||
//! distribution.
|
||||
//!
|
||||
//! * `rust_begin_unwind` - This function takes three arguments, a
|
||||
//! `fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate
|
||||
//! `fmt::Arguments`, a `&str`, and a `usize`. These three arguments dictate
|
||||
//! the panic message, the file at which panic was invoked, and the line.
|
||||
//! It is up to consumers of this core library to define this panic
|
||||
//! function; it is only required to never return.
|
||||
|
@ -88,14 +88,12 @@ mod int_macros;
|
|||
#[macro_use]
|
||||
mod uint_macros;
|
||||
|
||||
#[path = "num/int.rs"] pub mod int;
|
||||
#[path = "num/isize.rs"] pub mod isize;
|
||||
#[path = "num/i8.rs"] pub mod i8;
|
||||
#[path = "num/i16.rs"] pub mod i16;
|
||||
#[path = "num/i32.rs"] pub mod i32;
|
||||
#[path = "num/i64.rs"] pub mod i64;
|
||||
|
||||
#[path = "num/uint.rs"] pub mod uint;
|
||||
#[path = "num/usize.rs"] pub mod usize;
|
||||
#[path = "num/u8.rs"] pub mod u8;
|
||||
#[path = "num/u16.rs"] pub mod u16;
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2012-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.
|
||||
|
||||
//! Deprecated: replaced by `isize`.
|
||||
//!
|
||||
//! The rollout of the new type will gradually take place over the
|
||||
//! alpha cycle along with the development of clearer conventions
|
||||
//! around integer types.
|
||||
|
||||
#![unstable(feature = "core")]
|
||||
#![deprecated(since = "1.0.0", reason = "replaced by isize")]
|
||||
|
||||
#[cfg(target_pointer_width = "32")] int_module! { int, 32 }
|
||||
#[cfg(target_pointer_width = "64")] int_module! { int, 64 }
|
|
@ -1,20 +0,0 @@
|
|||
// Copyright 2012-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.
|
||||
|
||||
//! Deprecated: replaced by `usize`.
|
||||
//!
|
||||
//! The rollout of the new type will gradually take place over the
|
||||
//! alpha cycle along with the development of clearer conventions
|
||||
//! around integer types.
|
||||
|
||||
#![unstable(feature = "core")]
|
||||
#![deprecated(since = "1.0.0", reason = "replaced by usize")]
|
||||
|
||||
uint_module! { uint, int, ::int::BITS }
|
|
@ -12,7 +12,7 @@ use core::iter::*;
|
|||
use core::iter::order::*;
|
||||
use core::iter::MinMaxResult::*;
|
||||
use core::num::SignedInt;
|
||||
use core::uint;
|
||||
use core::usize;
|
||||
use core::cmp;
|
||||
|
||||
use test::Bencher;
|
||||
|
@ -292,7 +292,7 @@ fn test_unfoldr() {
|
|||
fn test_cycle() {
|
||||
let cycle_len = 3;
|
||||
let it = count(0, 1).take(cycle_len).cycle();
|
||||
assert_eq!(it.size_hint(), (uint::MAX, None));
|
||||
assert_eq!(it.size_hint(), (usize::MAX, None));
|
||||
for (i, x) in it.take(100).enumerate() {
|
||||
assert_eq!(i % cycle_len, x);
|
||||
}
|
||||
|
@ -365,19 +365,19 @@ fn test_iterator_size_hint() {
|
|||
let v2 = &[10, 11, 12];
|
||||
let vi = v.iter();
|
||||
|
||||
assert_eq!(c.size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.size_hint(), (usize::MAX, None));
|
||||
assert_eq!(vi.clone().size_hint(), (10, Some(10)));
|
||||
|
||||
assert_eq!(c.clone().take(5).size_hint(), (5, Some(5)));
|
||||
assert_eq!(c.clone().skip(5).size_hint().1, None);
|
||||
assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().enumerate().size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.clone().enumerate().size_hint(), (usize::MAX, None));
|
||||
assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (usize::MAX, None));
|
||||
assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
|
||||
assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
|
||||
assert_eq!(c.clone().map(|_| 0).size_hint(), (uint::MAX, None));
|
||||
assert_eq!(c.clone().map(|_| 0).size_hint(), (usize::MAX, None));
|
||||
assert_eq!(c.filter_map(|_| Some(0)).size_hint(), (0, None));
|
||||
|
||||
assert_eq!(vi.clone().take(5).size_hint(), (5, Some(5)));
|
||||
|
@ -753,7 +753,7 @@ fn test_range() {
|
|||
|
||||
assert_eq!((0..100).size_hint(), (100, Some(100)));
|
||||
// this test is only meaningful when sizeof uint < sizeof u64
|
||||
assert_eq!((uint::MAX - 1..uint::MAX).size_hint(), (1, Some(1)));
|
||||
assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1)));
|
||||
assert_eq!((-10..-1).size_hint(), (9, Some(9)));
|
||||
assert_eq!((-1..-10).size_hint(), (0, Some(0)));
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// 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.
|
||||
|
||||
int_module!(int, int);
|
|
@ -12,7 +12,7 @@ macro_rules! int_module { ($T:ty, $T_i:ident) => (
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::$T_i::*;
|
||||
use core::int;
|
||||
use core::isize;
|
||||
use core::num::{FromStrRadix, Int, SignedInt};
|
||||
use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
|
||||
use num;
|
||||
|
@ -153,7 +153,7 @@ mod tests {
|
|||
fn test_signed_checked_div() {
|
||||
assert!(10.checked_div(2) == Some(5));
|
||||
assert!(5.checked_div(0) == None);
|
||||
assert!(int::MIN.checked_div(-1) == None);
|
||||
assert!(isize::MIN.checked_div(-1) == None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -21,7 +21,6 @@ mod i8;
|
|||
mod i16;
|
||||
mod i32;
|
||||
mod i64;
|
||||
mod int;
|
||||
|
||||
#[macro_use]
|
||||
mod uint_macros;
|
||||
|
@ -30,7 +29,6 @@ mod u8;
|
|||
mod u16;
|
||||
mod u32;
|
||||
mod u64;
|
||||
mod uint;
|
||||
|
||||
/// Helper function for testing numeric operations
|
||||
pub fn test_num<T>(ten: T, two: T) where
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// 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.
|
||||
|
||||
uint_module!(uint, uint);
|
|
@ -963,7 +963,7 @@ fn test_split_within() {
|
|||
"little lamb".to_string(),
|
||||
"Little lamb".to_string()
|
||||
]);
|
||||
t("\nMary had a little lamb\nLittle lamb\n", ::std::uint::MAX,
|
||||
t("\nMary had a little lamb\nLittle lamb\n", ::std::usize::MAX,
|
||||
&["Mary had a little lamb\nLittle lamb".to_string()]);
|
||||
}
|
||||
|
||||
|
|
|
@ -1115,7 +1115,6 @@ pub mod types {
|
|||
pub mod posix88 {
|
||||
pub type off_t = i64;
|
||||
pub type dev_t = u32;
|
||||
pub type ino_t = u32;
|
||||
pub type pid_t = i32;
|
||||
pub type uid_t = u32;
|
||||
pub type gid_t = u32;
|
||||
|
|
|
@ -12,18 +12,18 @@
|
|||
|
||||
use core::prelude::*;
|
||||
use core::char;
|
||||
use core::int;
|
||||
use core::uint;
|
||||
use core::isize;
|
||||
use core::usize;
|
||||
|
||||
use {Rand,Rng};
|
||||
|
||||
impl Rand for int {
|
||||
impl Rand for isize {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> int {
|
||||
if int::BITS == 32 {
|
||||
rng.gen::<i32>() as int
|
||||
fn rand<R: Rng>(rng: &mut R) -> isize {
|
||||
if isize::BITS == 32 {
|
||||
rng.gen::<i32>() as isize
|
||||
} else {
|
||||
rng.gen::<i64>() as int
|
||||
rng.gen::<i64>() as isize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,13 +56,13 @@ impl Rand for i64 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Rand for uint {
|
||||
impl Rand for usize {
|
||||
#[inline]
|
||||
fn rand<R: Rng>(rng: &mut R) -> uint {
|
||||
if uint::BITS == 32 {
|
||||
rng.gen::<u32>() as uint
|
||||
fn rand<R: Rng>(rng: &mut R) -> usize {
|
||||
if usize::BITS == 32 {
|
||||
rng.gen::<u32>() as usize
|
||||
} else {
|
||||
rng.gen::<u64>() as uint
|
||||
rng.gen::<u64>() as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -612,7 +612,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_trait_item(&mut self, m: &ast::TraitItem) {
|
||||
run_lints!(self, check_trait_method, m);
|
||||
run_lints!(self, check_trait_item, m);
|
||||
visit::walk_trait_item(self, m);
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ pub trait LintPass {
|
|||
fn check_fn(&mut self, _: &Context,
|
||||
_: FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
|
||||
fn check_ty_method(&mut self, _: &Context, _: &ast::TypeMethod) { }
|
||||
fn check_trait_method(&mut self, _: &Context, _: &ast::TraitItem) { }
|
||||
fn check_trait_item(&mut self, _: &Context, _: &ast::TraitItem) { }
|
||||
fn check_struct_def(&mut self, _: &Context,
|
||||
_: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
|
||||
fn check_struct_def_post(&mut self, _: &Context,
|
||||
|
|
|
@ -51,8 +51,8 @@
|
|||
//! enclosing function. On the way down the tree, it identifies those AST
|
||||
//! nodes and variable IDs that will be needed for the liveness analysis
|
||||
//! and assigns them contiguous IDs. The liveness id for an AST node is
|
||||
//! called a `live_node` (it's a newtype'd uint) and the id for a variable
|
||||
//! is called a `variable` (another newtype'd uint).
|
||||
//! called a `live_node` (it's a newtype'd usize) and the id for a variable
|
||||
//! is called a `variable` (another newtype'd usize).
|
||||
//!
|
||||
//! On the way back up the tree, as we are about to exit from a function
|
||||
//! declaration we allocate a `liveness` instance. Now that we know
|
||||
|
@ -118,7 +118,7 @@ use middle::ty::ClosureTyper;
|
|||
use lint;
|
||||
use util::nodemap::NodeMap;
|
||||
|
||||
use std::{fmt, old_io, uint};
|
||||
use std::{fmt, old_io, usize};
|
||||
use std::rc::Rc;
|
||||
use std::iter::repeat;
|
||||
use syntax::ast::{self, NodeId, Expr};
|
||||
|
@ -138,17 +138,17 @@ enum LoopKind<'a> {
|
|||
}
|
||||
|
||||
#[derive(Copy, PartialEq)]
|
||||
struct Variable(uint);
|
||||
struct Variable(usize);
|
||||
|
||||
#[derive(Copy, PartialEq)]
|
||||
struct LiveNode(uint);
|
||||
struct LiveNode(usize);
|
||||
|
||||
impl Variable {
|
||||
fn get(&self) -> uint { let Variable(v) = *self; v }
|
||||
fn get(&self) -> usize { let Variable(v) = *self; v }
|
||||
}
|
||||
|
||||
impl LiveNode {
|
||||
fn get(&self) -> uint { let LiveNode(v) = *self; v }
|
||||
fn get(&self) -> usize { let LiveNode(v) = *self; v }
|
||||
}
|
||||
|
||||
impl Clone for LiveNode {
|
||||
|
@ -232,11 +232,11 @@ impl fmt::Debug for Variable {
|
|||
|
||||
impl LiveNode {
|
||||
fn is_valid(&self) -> bool {
|
||||
self.get() != uint::MAX
|
||||
self.get() != usize::MAX
|
||||
}
|
||||
}
|
||||
|
||||
fn invalid_node() -> LiveNode { LiveNode(uint::MAX) }
|
||||
fn invalid_node() -> LiveNode { LiveNode(usize::MAX) }
|
||||
|
||||
struct CaptureInfo {
|
||||
ln: LiveNode,
|
||||
|
@ -260,8 +260,8 @@ enum VarKind {
|
|||
struct IrMaps<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
|
||||
num_live_nodes: uint,
|
||||
num_vars: uint,
|
||||
num_live_nodes: usize,
|
||||
num_vars: usize,
|
||||
live_node_map: NodeMap<LiveNode>,
|
||||
variable_map: NodeMap<Variable>,
|
||||
capture_info_map: NodeMap<Rc<Vec<CaptureInfo>>>,
|
||||
|
@ -540,9 +540,9 @@ struct Specials {
|
|||
clean_exit_var: Variable
|
||||
}
|
||||
|
||||
static ACC_READ: uint = 1;
|
||||
static ACC_WRITE: uint = 2;
|
||||
static ACC_USE: uint = 4;
|
||||
static ACC_READ: u32 = 1;
|
||||
static ACC_WRITE: u32 = 2;
|
||||
static ACC_USE: u32 = 4;
|
||||
|
||||
struct Liveness<'a, 'tcx: 'a> {
|
||||
ir: &'a mut IrMaps<'a, 'tcx>,
|
||||
|
@ -631,7 +631,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
succ
|
||||
}
|
||||
|
||||
fn idx(&self, ln: LiveNode, var: Variable) -> uint {
|
||||
fn idx(&self, ln: LiveNode, var: Variable) -> usize {
|
||||
ln.get() * self.ir.num_vars + var.get()
|
||||
}
|
||||
|
||||
|
@ -670,7 +670,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn indices2<F>(&mut self, ln: LiveNode, succ_ln: LiveNode, mut op: F) where
|
||||
F: FnMut(&mut Liveness<'a, 'tcx>, uint, uint),
|
||||
F: FnMut(&mut Liveness<'a, 'tcx>, usize, usize),
|
||||
{
|
||||
let node_base_idx = self.idx(ln, Variable(0));
|
||||
let succ_base_idx = self.idx(succ_ln, Variable(0));
|
||||
|
@ -684,7 +684,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
ln: LiveNode,
|
||||
mut test: F)
|
||||
-> old_io::IoResult<()> where
|
||||
F: FnMut(uint) -> LiveNode,
|
||||
F: FnMut(usize) -> LiveNode,
|
||||
{
|
||||
let node_base_idx = self.idx(ln, Variable(0));
|
||||
for var_idx in 0..self.ir.num_vars {
|
||||
|
@ -807,7 +807,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// Either read, write, or both depending on the acc bitset
|
||||
fn acc(&mut self, ln: LiveNode, var: Variable, acc: uint) {
|
||||
fn acc(&mut self, ln: LiveNode, var: Variable, acc: u32) {
|
||||
debug!("{:?} accesses[{:x}] {:?}: {}",
|
||||
ln, acc, var, self.ln_str(ln));
|
||||
|
||||
|
@ -1283,7 +1283,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
}
|
||||
|
||||
// see comment on propagate_through_lvalue()
|
||||
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
|
||||
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
|
||||
-> LiveNode {
|
||||
match expr.node {
|
||||
ast::ExprPath(..) => {
|
||||
|
@ -1298,7 +1298,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
|
||||
fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
|
||||
-> LiveNode {
|
||||
match self.ir.tcx.def_map.borrow()[expr.id].full_def() {
|
||||
DefLocal(nid) => {
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
//! Use the former for unit-like structs and the latter for structs with
|
||||
//! a `pub fn new()`.
|
||||
|
||||
use self::MethodContext::*;
|
||||
|
||||
use metadata::{csearch, decoder};
|
||||
use middle::def::*;
|
||||
use middle::subst::Substs;
|
||||
|
@ -228,7 +226,9 @@ impl LintPass for TypeLimits {
|
|||
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
|
||||
let int_type = if let ast::TyIs(_) = t {
|
||||
cx.sess().target.int_type
|
||||
} else { t };
|
||||
} else {
|
||||
t
|
||||
};
|
||||
let (min, max) = int_ty_range(int_type);
|
||||
let negative = self.negated_expr_id == e.id;
|
||||
|
||||
|
@ -245,14 +245,16 @@ impl LintPass for TypeLimits {
|
|||
ty::ty_uint(t) => {
|
||||
let uint_type = if let ast::TyUs(_) = t {
|
||||
cx.sess().target.uint_type
|
||||
} else { t };
|
||||
} else {
|
||||
t
|
||||
};
|
||||
let (min, max) = uint_ty_range(uint_type);
|
||||
let lit_val: u64 = match lit.node {
|
||||
ast::LitByte(_v) => return, // _v is u8, within range by definition
|
||||
ast::LitInt(v, _) => v,
|
||||
_ => panic!()
|
||||
};
|
||||
if lit_val < min || lit_val > max {
|
||||
if lit_val < min || lit_val > max {
|
||||
cx.span_lint(OVERFLOWING_LITERALS, e.span,
|
||||
&*format!("literal out of range for {:?}", t));
|
||||
}
|
||||
|
@ -262,9 +264,9 @@ impl LintPass for TypeLimits {
|
|||
let lit_val: f64 = match lit.node {
|
||||
ast::LitFloat(ref v, _) |
|
||||
ast::LitFloatUnsuffixed(ref v) => {
|
||||
match v.parse().ok() {
|
||||
Some(f) => f,
|
||||
None => return
|
||||
match v.parse() {
|
||||
Ok(f) => f,
|
||||
Err(_) => return
|
||||
}
|
||||
}
|
||||
_ => panic!()
|
||||
|
@ -302,52 +304,52 @@ impl LintPass for TypeLimits {
|
|||
})
|
||||
}
|
||||
|
||||
// for int & uint, be conservative with the warnings, so that the
|
||||
// for isize & usize, be conservative with the warnings, so that the
|
||||
// warnings are consistent between 32- and 64-bit platforms
|
||||
fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
|
||||
match int_ty {
|
||||
ast::TyIs(_) => (i64::MIN, i64::MAX),
|
||||
ast::TyI8 => (i8::MIN as i64, i8::MAX as i64),
|
||||
ast::TyI16 => (i16::MIN as i64, i16::MAX as i64),
|
||||
ast::TyI32 => (i32::MIN as i64, i32::MAX as i64),
|
||||
ast::TyI64 => (i64::MIN, i64::MAX)
|
||||
ast::TyIs(_) => (i64::MIN, i64::MAX),
|
||||
ast::TyI8 => (i8::MIN as i64, i8::MAX as i64),
|
||||
ast::TyI16 => (i16::MIN as i64, i16::MAX as i64),
|
||||
ast::TyI32 => (i32::MIN as i64, i32::MAX as i64),
|
||||
ast::TyI64 => (i64::MIN, i64::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
|
||||
match uint_ty {
|
||||
ast::TyUs(_) => (u64::MIN, u64::MAX),
|
||||
ast::TyU8 => (u8::MIN as u64, u8::MAX as u64),
|
||||
ast::TyU16 => (u16::MIN as u64, u16::MAX as u64),
|
||||
ast::TyU32 => (u32::MIN as u64, u32::MAX as u64),
|
||||
ast::TyU64 => (u64::MIN, u64::MAX)
|
||||
ast::TyUs(_) => (u64::MIN, u64::MAX),
|
||||
ast::TyU8 => (u8::MIN as u64, u8::MAX as u64),
|
||||
ast::TyU16 => (u16::MIN as u64, u16::MAX as u64),
|
||||
ast::TyU32 => (u32::MIN as u64, u32::MAX as u64),
|
||||
ast::TyU64 => (u64::MIN, u64::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
|
||||
match float_ty {
|
||||
ast::TyF32 => (f32::MIN as f64, f32::MAX as f64),
|
||||
ast::TyF64 => (f64::MIN, f64::MAX)
|
||||
ast::TyF32 => (f32::MIN as f64, f32::MAX as f64),
|
||||
ast::TyF64 => (f64::MIN, f64::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 {
|
||||
match int_ty {
|
||||
ast::TyIs(_) => int_ty_bits(target_int_ty, target_int_ty),
|
||||
ast::TyI8 => i8::BITS as u64,
|
||||
ast::TyI16 => i16::BITS as u64,
|
||||
ast::TyI32 => i32::BITS as u64,
|
||||
ast::TyI64 => i64::BITS as u64
|
||||
ast::TyIs(_) => int_ty_bits(target_int_ty, target_int_ty),
|
||||
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, target_uint_ty: ast::UintTy) -> u64 {
|
||||
match uint_ty {
|
||||
ast::TyUs(_) => uint_ty_bits(target_uint_ty, target_uint_ty),
|
||||
ast::TyU8 => u8::BITS as u64,
|
||||
ast::TyU16 => u16::BITS as u64,
|
||||
ast::TyU32 => u32::BITS as u64,
|
||||
ast::TyU64 => u64::BITS as u64
|
||||
ast::TyUs(_) => uint_ty_bits(target_uint_ty, target_uint_ty),
|
||||
ast::TyU8 => u8::BITS as u64,
|
||||
ast::TyU16 => u16::BITS as u64,
|
||||
ast::TyU32 => u32::BITS as u64,
|
||||
ast::TyU64 => u64::BITS as u64
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,7 +362,11 @@ impl LintPass for TypeLimits {
|
|||
};
|
||||
// Normalize the binop so that the literal is always on the RHS in
|
||||
// the comparison
|
||||
let norm_binop = if swap { rev_binop(binop) } else { binop };
|
||||
let norm_binop = if swap {
|
||||
rev_binop(binop)
|
||||
} else {
|
||||
binop
|
||||
};
|
||||
match ty::expr_ty(tcx, expr).sty {
|
||||
ty::ty_int(int_ty) => {
|
||||
let (min, max) = int_ty_range(int_ty);
|
||||
|
@ -432,9 +438,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
|
|||
|
||||
if !ty::is_ffi_safe(self.cx.tcx, tty) {
|
||||
self.cx.span_lint(IMPROPER_CTYPES, sp,
|
||||
"found type without foreign-function-safe
|
||||
representation annotation in foreign module, consider \
|
||||
adding a #[repr(...)] attribute to the type");
|
||||
"found type without foreign-function-safe \
|
||||
representation annotation in foreign module, consider \
|
||||
adding a #[repr(...)] attribute to the type");
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
|
@ -595,7 +601,7 @@ impl LintPass for RawPointerDerive {
|
|||
|
||||
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
|
||||
if !attr::contains_name(&item.attrs, "automatically_derived") {
|
||||
return
|
||||
return;
|
||||
}
|
||||
let did = match item.node {
|
||||
ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
|
||||
|
@ -603,7 +609,7 @@ impl LintPass for RawPointerDerive {
|
|||
if let &Some(ref trait_ref) = t_ref_opt {
|
||||
let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref);
|
||||
if Some(def_id) == cx.tcx.lang_items.copy_trait() {
|
||||
return
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -615,12 +621,16 @@ impl LintPass for RawPointerDerive {
|
|||
}
|
||||
_ => return,
|
||||
};
|
||||
if !ast_util::is_local(did) { return }
|
||||
if !ast_util::is_local(did) {
|
||||
return;
|
||||
}
|
||||
let item = match cx.tcx.map.find(did.node) {
|
||||
Some(ast_map::NodeItem(item)) => item,
|
||||
_ => return,
|
||||
};
|
||||
if !self.checked_raw_pointers.insert(item.id) { return }
|
||||
if !self.checked_raw_pointers.insert(item.id) {
|
||||
return;
|
||||
}
|
||||
match item.node {
|
||||
ast::ItemStruct(..) | ast::ItemEnum(..) => {
|
||||
let mut visitor = RawPtrDeriveVisitor { cx: cx };
|
||||
|
@ -646,6 +656,7 @@ impl LintPass for UnusedAttributes {
|
|||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
|
||||
// Note that check_name() marks the attribute as used if it matches.
|
||||
for &(ref name, ty) in KNOWN_ATTRIBUTES {
|
||||
match ty {
|
||||
AttributeType::Whitelisted
|
||||
|
@ -730,23 +741,24 @@ impl LintPass for UnusedResults {
|
|||
}
|
||||
|
||||
let t = ty::expr_ty(cx.tcx, expr);
|
||||
let mut warned = false;
|
||||
match t.sty {
|
||||
let warned = match t.sty {
|
||||
ty::ty_tup(ref tys) if tys.is_empty() => return,
|
||||
ty::ty_bool => return,
|
||||
ty::ty_struct(did, _) |
|
||||
ty::ty_enum(did, _) => {
|
||||
if ast_util::is_local(did) {
|
||||
if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) {
|
||||
warned |= check_must_use(cx, &it.attrs, s.span);
|
||||
check_must_use(cx, &it.attrs, s.span)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
|
||||
warned |= check_must_use(cx, &attrs[..], s.span);
|
||||
check_must_use(cx, &attrs[..], s.span)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if !warned {
|
||||
cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
|
||||
}
|
||||
|
@ -785,7 +797,9 @@ impl NonCamelCaseTypes {
|
|||
fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
|
||||
fn is_camel_case(ident: ast::Ident) -> bool {
|
||||
let ident = token::get_ident(ident);
|
||||
if ident.is_empty() { return true; }
|
||||
if ident.is_empty() {
|
||||
return true;
|
||||
}
|
||||
let ident = ident.trim_matches('_');
|
||||
|
||||
// start with a non-lowercase letter rather than non-uppercase
|
||||
|
@ -795,8 +809,11 @@ impl NonCamelCaseTypes {
|
|||
|
||||
fn to_camel_case(s: &str) -> String {
|
||||
s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
|
||||
if i == 0 { c.to_uppercase() }
|
||||
else { c }
|
||||
if i == 0 {
|
||||
c.to_uppercase()
|
||||
} else {
|
||||
c
|
||||
}
|
||||
)).collect()
|
||||
}
|
||||
|
||||
|
@ -820,11 +837,13 @@ impl LintPass for NonCamelCaseTypes {
|
|||
}
|
||||
|
||||
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
|
||||
let has_extern_repr = it.attrs.iter().map(|attr| {
|
||||
let has_extern_repr = it.attrs.iter().any(|attr| {
|
||||
attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
|
||||
.any(|r| r == &attr::ReprExtern)
|
||||
}).any(|x| x);
|
||||
if has_extern_repr { return }
|
||||
});
|
||||
if has_extern_repr {
|
||||
return;
|
||||
}
|
||||
|
||||
match it.node {
|
||||
ast::ItemTy(..) | ast::ItemStruct(..) => {
|
||||
|
@ -834,7 +853,9 @@ impl LintPass for NonCamelCaseTypes {
|
|||
self.check_case(cx, "trait", it.ident, it.span)
|
||||
}
|
||||
ast::ItemEnum(ref enum_definition, _) => {
|
||||
if has_extern_repr { return }
|
||||
if has_extern_repr {
|
||||
return;
|
||||
}
|
||||
self.check_case(cx, "type", it.ident, it.span);
|
||||
for variant in &enum_definition.variants {
|
||||
self.check_case(cx, "variant", variant.node.name, variant.span);
|
||||
|
@ -866,32 +887,28 @@ fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
|
|||
|
||||
match cx.tcx.impl_or_trait_items.borrow().get(&did).cloned() {
|
||||
None => cx.sess().span_bug(m.span, "missing method descriptor?!"),
|
||||
Some(md) => {
|
||||
match md {
|
||||
ty::MethodTraitItem(md) => {
|
||||
match md.container {
|
||||
ty::TraitContainer(..) => TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => TraitImpl,
|
||||
None => PlainImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::TypeTraitItem(typedef) => {
|
||||
match typedef.container {
|
||||
ty::TraitContainer(..) => TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => TraitImpl,
|
||||
None => PlainImpl
|
||||
}
|
||||
}
|
||||
Some(ty::MethodTraitItem(md)) => {
|
||||
match md.container {
|
||||
ty::TraitContainer(..) => MethodContext::TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => MethodContext::TraitImpl,
|
||||
None => MethodContext::PlainImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(ty::TypeTraitItem(typedef)) => {
|
||||
match typedef.container {
|
||||
ty::TraitContainer(..) => MethodContext::TraitDefaultImpl,
|
||||
ty::ImplContainer(cid) => {
|
||||
match ty::impl_trait_ref(cx.tcx, cid) {
|
||||
Some(..) => MethodContext::TraitImpl,
|
||||
None => MethodContext::PlainImpl
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -912,12 +929,16 @@ impl NonSnakeCase {
|
|||
if c == '_' {
|
||||
words.push(String::new());
|
||||
true
|
||||
} else { false }
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
for s in str.split('_') {
|
||||
let mut last_upper = false;
|
||||
let mut buf = String::new();
|
||||
if s.is_empty() { continue; }
|
||||
if s.is_empty() {
|
||||
continue;
|
||||
}
|
||||
for ch in s.chars() {
|
||||
if !buf.is_empty() && buf != "'"
|
||||
&& ch.is_uppercase()
|
||||
|
@ -936,7 +957,9 @@ impl NonSnakeCase {
|
|||
fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
|
||||
fn is_snake_case(ident: ast::Ident) -> bool {
|
||||
let ident = token::get_ident(ident);
|
||||
if ident.is_empty() { return true; }
|
||||
if ident.is_empty() {
|
||||
return true;
|
||||
}
|
||||
let ident = ident.trim_left_matches('\'');
|
||||
let ident = ident.trim_matches('_');
|
||||
|
||||
|
@ -979,14 +1002,17 @@ impl LintPass for NonSnakeCase {
|
|||
_: &ast::Block, span: Span, _: ast::NodeId) {
|
||||
match fk {
|
||||
visit::FkMethod(ident, _, m) => match method_context(cx, m) {
|
||||
PlainImpl
|
||||
=> self.check_snake_case(cx, "method", ident, span),
|
||||
TraitDefaultImpl
|
||||
=> self.check_snake_case(cx, "trait method", ident, span),
|
||||
MethodContext::PlainImpl => {
|
||||
self.check_snake_case(cx, "method", ident, span)
|
||||
},
|
||||
MethodContext::TraitDefaultImpl => {
|
||||
self.check_snake_case(cx, "trait method", ident, span)
|
||||
},
|
||||
_ => (),
|
||||
},
|
||||
visit::FkItemFn(ident, _, _, _)
|
||||
=> self.check_snake_case(cx, "function", ident, span),
|
||||
visit::FkItemFn(ident, _, _, _) => {
|
||||
self.check_snake_case(cx, "function", ident, span)
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@ -1015,7 +1041,7 @@ impl LintPass for NonSnakeCase {
|
|||
}
|
||||
|
||||
fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef,
|
||||
_: ast::Ident, _: &ast::Generics, _: ast::NodeId) {
|
||||
_: ast::Ident, _: &ast::Generics, _: ast::NodeId) {
|
||||
for sf in &s.fields {
|
||||
if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node {
|
||||
self.check_snake_case(cx, "structure field", ident, sf.span);
|
||||
|
@ -1094,13 +1120,12 @@ pub struct UnusedParens;
|
|||
|
||||
impl UnusedParens {
|
||||
fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str,
|
||||
struct_lit_needs_parens: bool) {
|
||||
struct_lit_needs_parens: bool) {
|
||||
if let ast::ExprParen(ref inner) = value.node {
|
||||
let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner);
|
||||
if !necessary {
|
||||
cx.span_lint(UNUSED_PARENS, value.span,
|
||||
&format!("unnecessary parentheses around {}",
|
||||
msg))
|
||||
&format!("unnecessary parentheses around {}", msg))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1193,26 +1218,17 @@ impl LintPass for UnusedImportBraces {
|
|||
}
|
||||
|
||||
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
|
||||
match item.node {
|
||||
ast::ItemUse(ref view_path) => {
|
||||
match view_path.node {
|
||||
ast::ViewPathList(_, ref items) => {
|
||||
if items.len() == 1 {
|
||||
match items[0].node {
|
||||
ast::PathListIdent {ref name, ..} => {
|
||||
let m = format!("braces around {} is unnecessary",
|
||||
&token::get_ident(*name));
|
||||
cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
|
||||
&m[..]);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
if let ast::ItemUse(ref view_path) = item.node {
|
||||
if let ast::ViewPathList(_, ref items) = view_path.node {
|
||||
if items.len() == 1 {
|
||||
if let ast::PathListIdent {ref name, ..} = items[0].node {
|
||||
let m = format!("braces around {} is unnecessary",
|
||||
&token::get_ident(*name));
|
||||
cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
|
||||
&m[..]);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1234,9 +1250,10 @@ impl LintPass for NonShorthandFieldPatterns {
|
|||
fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
|
||||
let def_map = cx.tcx.def_map.borrow();
|
||||
if let ast::PatStruct(_, ref v, _) = pat.node {
|
||||
let field_pats = v.iter()
|
||||
.filter(|fieldpat| !fieldpat.node.is_shorthand)
|
||||
.filter(|fieldpat| {
|
||||
let field_pats = v.iter().filter(|fieldpat| {
|
||||
if fieldpat.node.is_shorthand {
|
||||
return false;
|
||||
}
|
||||
let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
|
||||
def == Some(def::DefLocal(fieldpat.node.pat.id))
|
||||
});
|
||||
|
@ -1482,10 +1499,14 @@ impl MissingDoc {
|
|||
desc: &'static str) {
|
||||
// If we're building a test harness, then warning about
|
||||
// documentation is probably not really relevant right now.
|
||||
if cx.sess().opts.test { return }
|
||||
if cx.sess().opts.test {
|
||||
return;
|
||||
}
|
||||
|
||||
// `#[doc(hidden)]` disables missing_docs check.
|
||||
if self.doc_hidden() { return }
|
||||
if self.doc_hidden() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only check publicly-visible items, using the result from the privacy pass.
|
||||
// It's an option so the crate root can also use this function (it doesn't
|
||||
|
@ -1504,7 +1525,7 @@ impl MissingDoc {
|
|||
});
|
||||
if !has_doc {
|
||||
cx.span_lint(MISSING_DOCS, sp,
|
||||
&format!("missing documentation for {}", desc));
|
||||
&format!("missing documentation for {}", desc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1528,20 +1549,19 @@ impl LintPass for MissingDoc {
|
|||
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
|
||||
}
|
||||
|
||||
fn check_struct_def(&mut self, _: &Context,
|
||||
_: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
|
||||
fn check_struct_def(&mut self, _: &Context, _: &ast::StructDef,
|
||||
_: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
|
||||
self.struct_def_stack.push(id);
|
||||
}
|
||||
|
||||
fn check_struct_def_post(&mut self, _: &Context,
|
||||
_: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
|
||||
fn check_struct_def_post(&mut self, _: &Context, _: &ast::StructDef,
|
||||
_: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
|
||||
let popped = self.struct_def_stack.pop().expect("empty struct_def_stack");
|
||||
assert!(popped == id);
|
||||
}
|
||||
|
||||
fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) {
|
||||
self.check_missing_docs_attrs(cx, None, &krate.attrs,
|
||||
krate.span, "crate");
|
||||
self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate");
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
|
||||
|
@ -1554,30 +1574,28 @@ impl LintPass for MissingDoc {
|
|||
ast::ItemTy(..) => "a type alias",
|
||||
_ => return
|
||||
};
|
||||
self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs,
|
||||
it.span, desc);
|
||||
self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc);
|
||||
}
|
||||
|
||||
fn check_fn(&mut self, cx: &Context,
|
||||
fk: visit::FnKind, _: &ast::FnDecl,
|
||||
_: &ast::Block, _: Span, _: ast::NodeId) {
|
||||
fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl,
|
||||
_: &ast::Block, _: Span, _: ast::NodeId) {
|
||||
if let visit::FkMethod(_, _, m) = fk {
|
||||
// If the method is an impl for a trait, don't doc.
|
||||
if method_context(cx, m) == TraitImpl { return; }
|
||||
if method_context(cx, m) == MethodContext::TraitImpl {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, doc according to privacy. This will also check
|
||||
// doc for default methods defined on traits.
|
||||
self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs,
|
||||
m.span, "a method");
|
||||
self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs, m.span, "a method");
|
||||
}
|
||||
}
|
||||
|
||||
fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) {
|
||||
self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs,
|
||||
tm.span, "a type method");
|
||||
self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs, tm.span, "a type method");
|
||||
}
|
||||
|
||||
fn check_trait_method(&mut self, cx: &Context, it: &ast::TraitItem) {
|
||||
fn check_trait_item(&mut self, cx: &Context, it: &ast::TraitItem) {
|
||||
if let ast::TraitItem::TypeTraitItem(ref ty) = *it {
|
||||
let assoc_ty = &ty.ty_param;
|
||||
self.check_missing_docs_attrs(cx, Some(assoc_ty.id), &ty.attrs,
|
||||
|
@ -1598,8 +1616,7 @@ impl LintPass for MissingDoc {
|
|||
}
|
||||
|
||||
fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) {
|
||||
self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs,
|
||||
v.span, "a variant");
|
||||
self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs, v.span, "a variant");
|
||||
assert!(!self.in_variant);
|
||||
self.in_variant = true;
|
||||
}
|
||||
|
@ -1626,18 +1643,18 @@ impl LintPass for MissingCopyImplementations {
|
|||
|
||||
fn check_item(&mut self, cx: &Context, item: &ast::Item) {
|
||||
if !cx.exported_items.contains(&item.id) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if cx.tcx
|
||||
.destructor_for_type
|
||||
.borrow()
|
||||
.contains_key(&ast_util::local_def(item.id)) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
let ty = match item.node {
|
||||
ast::ItemStruct(_, ref ast_generics) => {
|
||||
if ast_generics.is_parameterized() {
|
||||
return
|
||||
return;
|
||||
}
|
||||
ty::mk_struct(cx.tcx,
|
||||
ast_util::local_def(item.id),
|
||||
|
@ -1645,7 +1662,7 @@ impl LintPass for MissingCopyImplementations {
|
|||
}
|
||||
ast::ItemEnum(_, ref ast_generics) => {
|
||||
if ast_generics.is_parameterized() {
|
||||
return
|
||||
return;
|
||||
}
|
||||
ty::mk_enum(cx.tcx,
|
||||
ast_util::local_def(item.id),
|
||||
|
@ -1655,7 +1672,7 @@ impl LintPass for MissingCopyImplementations {
|
|||
};
|
||||
let parameter_environment = ty::empty_parameter_environment(cx.tcx);
|
||||
if !ty::type_moves_by_default(¶meter_environment, item.span, ty) {
|
||||
return
|
||||
return;
|
||||
}
|
||||
if ty::can_type_implement_copy(¶meter_environment, item.span, ty).is_ok() {
|
||||
cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
|
||||
|
@ -1709,10 +1726,10 @@ impl LintPass for MissingDebugImplementations {
|
|||
let impls = match impls.get(&debug) {
|
||||
Some(impls) => {
|
||||
impls.borrow().iter()
|
||||
.filter(|d| d.krate == ast::LOCAL_CRATE)
|
||||
.filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)))
|
||||
.map(|d| d.node)
|
||||
.collect()
|
||||
.filter(|d| d.krate == ast::LOCAL_CRATE)
|
||||
.filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)))
|
||||
.map(|d| d.node)
|
||||
.collect()
|
||||
}
|
||||
None => NodeSet(),
|
||||
};
|
||||
|
@ -1741,8 +1758,7 @@ pub struct Stability;
|
|||
|
||||
impl Stability {
|
||||
fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option<attr::Stability>) {
|
||||
|
||||
// deprecated attributes apply in-crate and cross-crate
|
||||
// Deprecated attributes apply in-crate and cross-crate.
|
||||
let (lint, label) = match *stability {
|
||||
Some(attr::Stability { deprecated_since: Some(_), .. }) =>
|
||||
(DEPRECATED, "deprecated"),
|
||||
|
@ -1857,25 +1873,27 @@ impl LintPass for UnconditionalRecursion {
|
|||
let mut visited = BitSet::new();
|
||||
|
||||
while let Some(idx) = work_queue.pop() {
|
||||
let cfg_id = idx.node_id();
|
||||
if idx == cfg.exit {
|
||||
// found a path!
|
||||
reached_exit_without_self_call = true;
|
||||
break
|
||||
} else if visited.contains(&cfg_id) {
|
||||
break;
|
||||
}
|
||||
|
||||
let cfg_id = idx.node_id();
|
||||
if visited.contains(&cfg_id) {
|
||||
// already done
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
visited.insert(cfg_id);
|
||||
|
||||
let node_id = cfg.graph.node_data(idx).id();
|
||||
|
||||
// is this a recursive call?
|
||||
if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {
|
||||
|
||||
self_call_spans.push(cx.tcx.map.span(node_id));
|
||||
// this is a self call, so we shouldn't explore past
|
||||
// this node in the CFG.
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
// add the successors of this node to explore the graph further.
|
||||
cfg.graph.each_outgoing_edge(idx, |_, edge| {
|
||||
|
@ -1888,7 +1906,7 @@ impl LintPass for UnconditionalRecursion {
|
|||
});
|
||||
}
|
||||
|
||||
// check the number of sell calls because a function that
|
||||
// Check the number of self calls because a function that
|
||||
// doesn't return (e.g. calls a `-> !` function or `loop { /*
|
||||
// no break */ }`) shouldn't be linted unless it actually
|
||||
// recurs.
|
||||
|
@ -1920,7 +1938,7 @@ impl LintPass for UnconditionalRecursion {
|
|||
_: ast::Ident,
|
||||
id: ast::NodeId) -> bool {
|
||||
tcx.def_map.borrow().get(&id)
|
||||
.map_or(false, |def| def.def_id() == ast_util::local_def(fn_id))
|
||||
.map_or(false, |def| def.def_id() == ast_util::local_def(fn_id))
|
||||
}
|
||||
|
||||
// check if the method call `id` refers to method `method_id`
|
||||
|
@ -1962,7 +1980,7 @@ impl LintPass for UnconditionalRecursion {
|
|||
tcx.map.span(id),
|
||||
"non-method call expr behaving like a method call?")
|
||||
};
|
||||
// it matches if it comes from the same impl,
|
||||
// It matches if it comes from the same impl,
|
||||
// and has the same method name.
|
||||
return ast_util::is_local(impl_def_id)
|
||||
&& impl_def_id.node == impl_id
|
||||
|
@ -2013,7 +2031,7 @@ impl LintPass for PluginAsLibrary {
|
|||
|
||||
if decoder::get_plugin_registrar_fn(md.data()).is_some() {
|
||||
cx.span_lint(PLUGIN_AS_LIBRARY, it.span,
|
||||
"compiler plugin used as an ordinary library");
|
||||
"compiler plugin used as an ordinary library");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2069,7 +2087,7 @@ impl LintPass for InvalidNoMangleItems {
|
|||
// Const items do not refer to a particular location in memory, and therefore
|
||||
// don't have anything to attach a symbol to
|
||||
let msg = "const items should never be #[no_mangle], consider instead using \
|
||||
`pub static`";
|
||||
`pub static`";
|
||||
cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
|
||||
}
|
||||
}
|
||||
|
@ -2082,15 +2100,17 @@ impl LintPass for InvalidNoMangleItems {
|
|||
#[derive(Copy)]
|
||||
pub struct UnstableFeatures;
|
||||
|
||||
declare_lint!(UNSTABLE_FEATURES, Allow,
|
||||
"enabling unstable features");
|
||||
declare_lint! {
|
||||
UNSTABLE_FEATURES,
|
||||
Allow,
|
||||
"enabling unstable features"
|
||||
}
|
||||
|
||||
impl LintPass for UnstableFeatures {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(UNSTABLE_FEATURES)
|
||||
}
|
||||
fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) {
|
||||
use syntax::attr;
|
||||
if attr::contains_name(&[attr.node.value.clone()], "feature") {
|
||||
ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature");
|
||||
}
|
||||
|
|
|
@ -789,7 +789,7 @@ fn pick_column_to_specialize(def_map: &DefMap, m: &[Match]) -> Option<uint> {
|
|||
|
||||
// Irrefutable columns always go first, they'd only be duplicated in the branches.
|
||||
if total_score == 0 {
|
||||
std::uint::MAX
|
||||
std::usize::MAX
|
||||
} else {
|
||||
total_score
|
||||
}
|
||||
|
|
|
@ -2435,21 +2435,19 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
|
|||
use middle::ty::{BrAnon, ReLateBound};
|
||||
|
||||
let function_type;
|
||||
let (fn_sig, abi, has_env) = match fn_ty.sty {
|
||||
ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, false),
|
||||
let (fn_sig, abi, env_ty) = match fn_ty.sty {
|
||||
ty::ty_bare_fn(_, ref f) => (&f.sig, f.abi, None),
|
||||
ty::ty_closure(closure_did, _, substs) => {
|
||||
let typer = common::NormalizingClosureTyper::new(ccx.tcx());
|
||||
function_type = typer.closure_type(closure_did, substs);
|
||||
(&function_type.sig, RustCall, true)
|
||||
let self_type = self_type_for_closure(ccx, closure_did, fn_ty);
|
||||
(&function_type.sig, RustCall, Some(self_type))
|
||||
}
|
||||
_ => ccx.sess().bug("expected closure or function.")
|
||||
};
|
||||
|
||||
let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
|
||||
|
||||
// Since index 0 is the return value of the llvm func, we start
|
||||
// at either 1 or 2 depending on whether there's an env slot or not
|
||||
let mut first_arg_offset = if has_env { 2 } else { 1 };
|
||||
let mut attrs = llvm::AttrBuilder::new();
|
||||
let ret_ty = fn_sig.output;
|
||||
|
||||
|
@ -2460,7 +2458,11 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
|
|||
assert!(abi == RustCall);
|
||||
|
||||
match fn_sig.inputs[0].sty {
|
||||
ty::ty_tup(ref inputs) => inputs.clone(),
|
||||
ty::ty_tup(ref inputs) => {
|
||||
let mut full_inputs = vec![env_ty.expect("Missing closure environment")];
|
||||
full_inputs.push_all(inputs);
|
||||
full_inputs
|
||||
}
|
||||
_ => ccx.sess().bug("expected tuple'd inputs")
|
||||
}
|
||||
},
|
||||
|
@ -2478,6 +2480,8 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
|
|||
_ => fn_sig.inputs.clone()
|
||||
};
|
||||
|
||||
// Index 0 is the return value of the llvm func, so we start at 1
|
||||
let mut first_arg_offset = 1;
|
||||
if let ty::FnConverging(ret_ty) = ret_ty {
|
||||
// A function pointer is called without the declaration
|
||||
// available, so we have to apply any attributes with ABI
|
||||
|
|
|
@ -603,7 +603,18 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
let _icx = push_ctxt("trans_method_call");
|
||||
debug!("trans_method_call(call_expr={})", call_expr.repr(bcx.tcx()));
|
||||
let method_call = MethodCall::expr(call_expr.id);
|
||||
let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty;
|
||||
let method_ty = match bcx.tcx().method_map.borrow().get(&method_call) {
|
||||
Some(method) => match method.origin {
|
||||
ty::MethodTraitObject(_) => match method.ty.sty {
|
||||
ty::ty_bare_fn(_, ref fty) => {
|
||||
ty::mk_bare_fn(bcx.tcx(), None, meth::opaque_method_ty(bcx.tcx(), fty))
|
||||
}
|
||||
_ => method.ty
|
||||
},
|
||||
_ => method.ty
|
||||
},
|
||||
None => panic!("method not found in trans_method_call")
|
||||
};
|
||||
trans_call_inner(
|
||||
bcx,
|
||||
call_expr.debug_loc(),
|
||||
|
@ -927,20 +938,21 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
|
|||
tuple_expr.id));
|
||||
let repr = adt::represent_type(bcx.ccx(), tuple_type);
|
||||
let repr_ptr = &*repr;
|
||||
for i in 0..field_types.len() {
|
||||
llargs.extend(field_types.iter().enumerate().map(|(i, field_type)| {
|
||||
let arg_datum = tuple_lvalue_datum.get_element(
|
||||
bcx,
|
||||
field_types[i],
|
||||
field_type,
|
||||
|srcval| {
|
||||
adt::trans_field_ptr(bcx, repr_ptr, srcval, 0, i)
|
||||
});
|
||||
let arg_datum = arg_datum.to_expr_datum();
|
||||
let arg_datum =
|
||||
unpack_datum!(bcx, arg_datum.to_rvalue_datum(bcx, "arg"));
|
||||
let arg_datum =
|
||||
unpack_datum!(bcx, arg_datum.to_appropriate_datum(bcx));
|
||||
llargs.push(arg_datum.add_clean(bcx.fcx, arg_cleanup_scope));
|
||||
}
|
||||
}).to_expr_datum();
|
||||
unpack_result!(bcx, trans_arg_datum(
|
||||
bcx,
|
||||
field_type,
|
||||
arg_datum,
|
||||
arg_cleanup_scope,
|
||||
DontAutorefArg)
|
||||
)
|
||||
}));
|
||||
}
|
||||
_ => {
|
||||
bcx.sess().span_bug(tuple_expr.span,
|
||||
|
|
|
@ -589,15 +589,16 @@ pub fn trans_object_shim<'a, 'tcx>(
|
|||
};
|
||||
let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty);
|
||||
let fty = tcx.mk_bare_fn(fty);
|
||||
debug!("trans_object_shim: fty={}", fty.repr(tcx));
|
||||
let method_ty = opaque_method_ty(tcx, fty);
|
||||
debug!("trans_object_shim: fty={} method_ty={}", fty.repr(tcx), method_ty.repr(tcx));
|
||||
|
||||
//
|
||||
let method_bare_fn_ty =
|
||||
ty::mk_bare_fn(tcx, None, fty);
|
||||
let shim_fn_ty = ty::mk_bare_fn(tcx, None, fty);
|
||||
let method_bare_fn_ty = ty::mk_bare_fn(tcx, None, method_ty);
|
||||
let function_name =
|
||||
link::mangle_internal_name_by_type_and_seq(ccx, method_bare_fn_ty, "object_shim");
|
||||
link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim");
|
||||
let llfn =
|
||||
decl_internal_rust_fn(ccx, method_bare_fn_ty, &function_name);
|
||||
decl_internal_rust_fn(ccx, shim_fn_ty, &function_name);
|
||||
|
||||
let sig = ty::erase_late_bound_regions(ccx.tcx(), &fty.sig);
|
||||
|
||||
|
@ -866,3 +867,20 @@ pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
|
||||
bcx
|
||||
}
|
||||
|
||||
/// Replace the self type (&Self or Box<Self>) with an opaque pointer.
|
||||
pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
|
||||
-> &'tcx ty::BareFnTy<'tcx> {
|
||||
let mut inputs = method_ty.sig.0.inputs.clone();
|
||||
inputs[0] = ty::mk_mut_ptr(tcx, ty::mk_mach_int(tcx, ast::TyI8));
|
||||
|
||||
tcx.mk_bare_fn(ty::BareFnTy {
|
||||
unsafety: method_ty.unsafety,
|
||||
abi: method_ty.abi,
|
||||
sig: ty::Binder(ty::FnSig {
|
||||
inputs: inputs,
|
||||
output: method_ty.sig.0.output,
|
||||
variadic: method_ty.sig.0.variadic,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ use middle::infer;
|
|||
use middle::region;
|
||||
use middle::subst;
|
||||
use middle::ty::{self, Ty};
|
||||
use util::ppaux::{Repr};
|
||||
use util::ppaux::{Repr, UserString};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
|
||||
|
@ -28,29 +29,98 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
|
|||
// types that have been traversed so far by `traverse_type_if_unseen`
|
||||
let mut breadcrumbs: Vec<Ty<'tcx>> = Vec::new();
|
||||
|
||||
iterate_over_potentially_unsafe_regions_in_type(
|
||||
let result = iterate_over_potentially_unsafe_regions_in_type(
|
||||
rcx,
|
||||
&mut breadcrumbs,
|
||||
TypeContext::Root,
|
||||
typ,
|
||||
span,
|
||||
scope,
|
||||
0,
|
||||
0);
|
||||
match result {
|
||||
Ok(()) => {}
|
||||
Err(Error::Overflow(ref ctxt, ref detected_on_typ)) => {
|
||||
let tcx = rcx.tcx();
|
||||
span_err!(tcx.sess, span, E0320,
|
||||
"overflow while adding drop-check rules for {}",
|
||||
typ.user_string(rcx.tcx()));
|
||||
match *ctxt {
|
||||
TypeContext::Root => {
|
||||
// no need for an additional note if the overflow
|
||||
// was somehow on the root.
|
||||
}
|
||||
TypeContext::EnumVariant { def_id, variant, arg_index } => {
|
||||
// FIXME (pnkfelix): eventually lookup arg_name
|
||||
// for the given index on struct variants.
|
||||
span_note!(
|
||||
rcx.tcx().sess,
|
||||
span,
|
||||
"overflowed on enum {} variant {} argument {} type: {}",
|
||||
ty::item_path_str(tcx, def_id),
|
||||
variant,
|
||||
arg_index,
|
||||
detected_on_typ.user_string(rcx.tcx()));
|
||||
}
|
||||
TypeContext::Struct { def_id, field } => {
|
||||
span_note!(
|
||||
rcx.tcx().sess,
|
||||
span,
|
||||
"overflowed on struct {} field {} type: {}",
|
||||
ty::item_path_str(tcx, def_id),
|
||||
field,
|
||||
detected_on_typ.user_string(rcx.tcx()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Error<'tcx> {
|
||||
Overflow(TypeContext, ty::Ty<'tcx>),
|
||||
}
|
||||
|
||||
enum TypeContext {
|
||||
Root,
|
||||
EnumVariant {
|
||||
def_id: ast::DefId,
|
||||
variant: ast::Name,
|
||||
arg_index: usize,
|
||||
},
|
||||
Struct {
|
||||
def_id: ast::DefId,
|
||||
field: ast::Name,
|
||||
}
|
||||
}
|
||||
|
||||
// The `depth` counts the number of calls to this function;
|
||||
// the `xref_depth` counts the subset of such calls that go
|
||||
// across a `Box<T>` or `PhantomData<T>`.
|
||||
fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
|
||||
rcx: &mut Rcx<'a, 'tcx>,
|
||||
breadcrumbs: &mut Vec<Ty<'tcx>>,
|
||||
context: TypeContext,
|
||||
ty_root: ty::Ty<'tcx>,
|
||||
span: Span,
|
||||
scope: region::CodeExtent,
|
||||
depth: uint)
|
||||
depth: uint,
|
||||
xref_depth: uint) -> Result<(), Error<'tcx>>
|
||||
{
|
||||
// Issue #22443: Watch out for overflow. While we are careful to
|
||||
// handle regular types properly, non-regular ones cause problems.
|
||||
let recursion_limit = rcx.tcx().sess.recursion_limit.get();
|
||||
if xref_depth >= recursion_limit {
|
||||
return Err(Error::Overflow(context, ty_root))
|
||||
}
|
||||
|
||||
let origin = || infer::SubregionOrigin::SafeDestructor(span);
|
||||
let mut walker = ty_root.walk();
|
||||
let opt_phantom_data_def_id = rcx.tcx().lang_items.phantom_data();
|
||||
|
||||
let destructor_for_type = rcx.tcx().destructor_for_type.borrow();
|
||||
|
||||
let xref_depth_orig = xref_depth;
|
||||
|
||||
while let Some(typ) = walker.next() {
|
||||
// Avoid recursing forever.
|
||||
if breadcrumbs.contains(&typ) {
|
||||
|
@ -61,20 +131,33 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
|
|||
// If we encounter `PhantomData<T>`, then we should replace it
|
||||
// with `T`, the type it represents as owned by the
|
||||
// surrounding context, before doing further analysis.
|
||||
let typ = if let ty::ty_struct(struct_did, substs) = typ.sty {
|
||||
if opt_phantom_data_def_id == Some(struct_did) {
|
||||
let item_type = ty::lookup_item_type(rcx.tcx(), struct_did);
|
||||
let tp_def = item_type.generics.types
|
||||
.opt_get(subst::TypeSpace, 0).unwrap();
|
||||
let new_typ = substs.type_for_def(tp_def);
|
||||
debug!("replacing phantom {} with {}",
|
||||
typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx()));
|
||||
new_typ
|
||||
} else {
|
||||
typ
|
||||
let (typ, xref_depth) = match typ.sty {
|
||||
ty::ty_struct(struct_did, substs) => {
|
||||
if opt_phantom_data_def_id == Some(struct_did) {
|
||||
let item_type = ty::lookup_item_type(rcx.tcx(), struct_did);
|
||||
let tp_def = item_type.generics.types
|
||||
.opt_get(subst::TypeSpace, 0).unwrap();
|
||||
let new_typ = substs.type_for_def(tp_def);
|
||||
debug!("replacing phantom {} with {}",
|
||||
typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx()));
|
||||
(new_typ, xref_depth_orig + 1)
|
||||
} else {
|
||||
(typ, xref_depth_orig)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: When ty_uniq is removed from compiler, the
|
||||
// definition of `Box<T>` must carry a PhantomData that
|
||||
// puts us into the previous case.
|
||||
ty::ty_uniq(new_typ) => {
|
||||
debug!("replacing ty_uniq {} with {}",
|
||||
typ.repr(rcx.tcx()), new_typ.repr(rcx.tcx()));
|
||||
(new_typ, xref_depth_orig + 1)
|
||||
}
|
||||
|
||||
_ => {
|
||||
(typ, xref_depth_orig)
|
||||
}
|
||||
} else {
|
||||
typ
|
||||
};
|
||||
|
||||
let opt_type_did = match typ.sty {
|
||||
|
@ -87,9 +170,9 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
|
|||
opt_type_did.and_then(|did| destructor_for_type.get(&did));
|
||||
|
||||
debug!("iterate_over_potentially_unsafe_regions_in_type \
|
||||
{}typ: {} scope: {:?} opt_dtor: {:?}",
|
||||
{}typ: {} scope: {:?} opt_dtor: {:?} xref: {}",
|
||||
(0..depth).map(|_| ' ').collect::<String>(),
|
||||
typ.repr(rcx.tcx()), scope, opt_dtor);
|
||||
typ.repr(rcx.tcx()), scope, opt_dtor, xref_depth);
|
||||
|
||||
// If `typ` has a destructor, then we must ensure that all
|
||||
// borrowed data reachable via `typ` must outlive the parent
|
||||
|
@ -228,6 +311,8 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
|
|||
|
||||
match typ.sty {
|
||||
ty::ty_struct(struct_did, substs) => {
|
||||
debug!("typ: {} is struct; traverse structure and not type-expression",
|
||||
typ.repr(rcx.tcx()));
|
||||
// Don't recurse; we extract type's substructure,
|
||||
// so do not process subparts of type expression.
|
||||
walker.skip_current_subtree();
|
||||
|
@ -240,17 +325,24 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
|
|||
struct_did,
|
||||
field.id,
|
||||
substs);
|
||||
iterate_over_potentially_unsafe_regions_in_type(
|
||||
try!(iterate_over_potentially_unsafe_regions_in_type(
|
||||
rcx,
|
||||
breadcrumbs,
|
||||
TypeContext::Struct {
|
||||
def_id: struct_did,
|
||||
field: field.name,
|
||||
},
|
||||
field_type,
|
||||
span,
|
||||
scope,
|
||||
depth+1)
|
||||
depth+1,
|
||||
xref_depth))
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_enum(enum_did, substs) => {
|
||||
debug!("typ: {} is enum; traverse structure and not type-expression",
|
||||
typ.repr(rcx.tcx()));
|
||||
// Don't recurse; we extract type's substructure,
|
||||
// so do not process subparts of type expression.
|
||||
walker.skip_current_subtree();
|
||||
|
@ -260,14 +352,20 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
|
|||
enum_did,
|
||||
substs);
|
||||
for variant_info in all_variant_info.iter() {
|
||||
for argument_type in variant_info.args.iter() {
|
||||
iterate_over_potentially_unsafe_regions_in_type(
|
||||
for (i, arg_type) in variant_info.args.iter().enumerate() {
|
||||
try!(iterate_over_potentially_unsafe_regions_in_type(
|
||||
rcx,
|
||||
breadcrumbs,
|
||||
*argument_type,
|
||||
TypeContext::EnumVariant {
|
||||
def_id: enum_did,
|
||||
variant: variant_info.name,
|
||||
arg_index: i,
|
||||
},
|
||||
*arg_type,
|
||||
span,
|
||||
scope,
|
||||
depth+1)
|
||||
depth+1,
|
||||
xref_depth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,4 +388,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
|
|||
// is done.
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
@ -174,7 +174,8 @@ register_diagnostics! {
|
|||
E0249, // expected constant expr for array length
|
||||
E0250, // expected constant expr for array length
|
||||
E0318, // can't create default impls for traits outside their crates
|
||||
E0319 // trait impls for defaulted traits allowed just for structs/enums
|
||||
E0319, // trait impls for defaulted traits allowed just for structs/enums
|
||||
E0320 // recursive overflow during dropck
|
||||
}
|
||||
|
||||
__build_diagnostic_array! { DIAGNOSTICS }
|
||||
|
|
|
@ -109,7 +109,7 @@
|
|||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(hash)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(libc)]
|
||||
#![feature(linkage, thread_local, asm)]
|
||||
|
@ -221,14 +221,12 @@ mod int_macros;
|
|||
mod uint_macros;
|
||||
|
||||
#[path = "num/isize.rs"] pub mod isize;
|
||||
pub use isize as int;
|
||||
#[path = "num/i8.rs"] pub mod i8;
|
||||
#[path = "num/i16.rs"] pub mod i16;
|
||||
#[path = "num/i32.rs"] pub mod i32;
|
||||
#[path = "num/i64.rs"] pub mod i64;
|
||||
|
||||
#[path = "num/usize.rs"] pub mod usize;
|
||||
pub use usize as uint;
|
||||
#[path = "num/u8.rs"] pub mod u8;
|
||||
#[path = "num/u16.rs"] pub mod u16;
|
||||
#[path = "num/u32.rs"] pub mod u32;
|
||||
|
|
37
src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs
Normal file
37
src/test/compile-fail/dropck_no_diverge_on_nonregular_1.rs
Normal file
|
@ -0,0 +1,37 @@
|
|||
// 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.
|
||||
|
||||
// Issue 22443: Reject code using non-regular types that would
|
||||
// otherwise cause dropck to loop infinitely.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Digit<T> {
|
||||
elem: T
|
||||
}
|
||||
|
||||
struct Node<T:'static> { m: PhantomData<&'static T> }
|
||||
|
||||
|
||||
enum FingerTree<T:'static> {
|
||||
Single(T),
|
||||
// Bug report said Digit after Box would stack overflow (versus
|
||||
// Digit before Box; see dropck_no_diverge_on_nonregular_2).
|
||||
Deep(
|
||||
Box<FingerTree<Node<T>>>,
|
||||
Digit<T>,
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
|
||||
FingerTree::Single(1);
|
||||
//~^ ERROR overflow while adding drop-check rules for FingerTree
|
||||
}
|
36
src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs
Normal file
36
src/test/compile-fail/dropck_no_diverge_on_nonregular_2.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
// 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.
|
||||
|
||||
// Issue 22443: Reject code using non-regular types that would
|
||||
// otherwise cause dropck to loop infinitely.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Digit<T> {
|
||||
elem: T
|
||||
}
|
||||
|
||||
struct Node<T:'static> { m: PhantomData<&'static T> }
|
||||
|
||||
enum FingerTree<T:'static> {
|
||||
Single(T),
|
||||
// Bug report said Digit before Box would infinite loop (versus
|
||||
// Digit after Box; see dropck_no_diverge_on_nonregular_1).
|
||||
Deep(
|
||||
Digit<T>,
|
||||
Box<FingerTree<Node<T>>>,
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
|
||||
FingerTree::Single(1);
|
||||
//~^ ERROR overflow while adding drop-check rules for FingerTree
|
||||
}
|
46
src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs
Normal file
46
src/test/compile-fail/dropck_no_diverge_on_nonregular_3.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
// 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.
|
||||
|
||||
// Issue 22443: Reject code using non-regular types that would
|
||||
// otherwise cause dropck to loop infinitely.
|
||||
//
|
||||
// This version is just checking that we still sanely handle a trivial
|
||||
// wrapper around the non-regular type. (It also demonstrates how the
|
||||
// error messages will report different types depending on which type
|
||||
// dropck is analyzing.)
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct Digit<T> {
|
||||
elem: T
|
||||
}
|
||||
|
||||
struct Node<T:'static> { m: PhantomData<&'static T> }
|
||||
|
||||
enum FingerTree<T:'static> {
|
||||
Single(T),
|
||||
// According to the bug report, Digit before Box would infinite loop.
|
||||
Deep(
|
||||
Digit<T>,
|
||||
Box<FingerTree<Node<T>>>,
|
||||
)
|
||||
}
|
||||
|
||||
enum Wrapper<T:'static> {
|
||||
Simple,
|
||||
Other(FingerTree<T>),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let w = //~ ERROR overflow while adding drop-check rules for core::option
|
||||
Some(Wrapper::Simple::<u32>);
|
||||
//~^ ERROR overflow while adding drop-check rules for core::option::Option
|
||||
//~| ERROR overflow while adding drop-check rules for Wrapper
|
||||
}
|
|
@ -8,11 +8,11 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::{int, i8, i16, i32, i64};
|
||||
use std::{isize, i8, i16, i32, i64};
|
||||
use std::thread;
|
||||
|
||||
fn main() {
|
||||
assert!(thread::spawn(move|| { int::MIN / -1; }).join().is_err());
|
||||
assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
|
||||
//~^ ERROR attempted to divide with overflow in a constant expression
|
||||
assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
|
||||
//~^ ERROR attempted to divide with overflow in a constant expression
|
||||
|
@ -32,7 +32,7 @@ fn main() {
|
|||
//~^ ERROR attempted to divide by zero in a constant expression
|
||||
assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
|
||||
//~^ ERROR attempted to divide by zero in a constant expression
|
||||
assert!(thread::spawn(move|| { int::MIN % -1; }).join().is_err());
|
||||
assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
|
||||
//~^ ERROR attempted remainder with overflow in a constant expression
|
||||
assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
|
||||
//~^ ERROR attempted remainder with overflow in a constant expression
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
pub use std::uint; //~ ERROR: visibility has no effect
|
||||
pub use std::usize; //~ ERROR: visibility has no effect
|
||||
pub struct A; //~ ERROR: visibility has no effect
|
||||
pub enum B {} //~ ERROR: visibility has no effect
|
||||
pub trait C { //~ ERROR: visibility has no effect
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
// error-pattern:index out of bounds: the len is 3 but the index is
|
||||
|
||||
use std::uint;
|
||||
use std::usize;
|
||||
use std::mem::size_of;
|
||||
|
||||
fn main() {
|
||||
let xs = [1, 2, 3];
|
||||
xs[uint::MAX / size_of::<int>() + 1];
|
||||
xs[usize::MAX / size_of::<isize>() + 1];
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
// error-pattern:capacity overflow
|
||||
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::uint;
|
||||
use std::usize;
|
||||
use std::mem::size_of;
|
||||
|
||||
fn main() {
|
||||
let threshold = uint::MAX / size_of::<(u64, u64, u64)>();
|
||||
let threshold = usize::MAX / size_of::<(u64, u64, u64)>();
|
||||
let mut h = HashMap::<u64, u64>::with_capacity(threshold + 100);
|
||||
h.insert(0, 0);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// DON'T REENABLE THIS UNLESS YOU'VE ACTUALLY FIXED THE UNDERLYING ISSUE
|
||||
// ignore-android seems to block forever
|
||||
|
||||
#![forbid(warnings)]
|
||||
|
||||
|
|
55
src/test/run-pass/issue-22777.rs
Normal file
55
src/test/run-pass/issue-22777.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// 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.
|
||||
|
||||
// This test is reduced from libsyntax. It is just checking that we
|
||||
// can successfully deal with a "deep" structure, which the drop-check
|
||||
// was hitting a recursion limit on at one point.
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
pub fn noop_fold_impl_item() -> SmallVector<ImplItem> {
|
||||
loop { }
|
||||
}
|
||||
|
||||
pub struct SmallVector<T>(P<T>);
|
||||
pub struct ImplItem(P<S01_Method>);
|
||||
|
||||
struct P<T>(Box<T>);
|
||||
|
||||
struct S01_Method(P<S02_Generics>);
|
||||
struct S02_Generics(P<S03_TyParam>);
|
||||
struct S03_TyParam(P<S04_TyParamBound>);
|
||||
struct S04_TyParamBound(S05_PolyTraitRef);
|
||||
struct S05_PolyTraitRef(S06_TraitRef);
|
||||
struct S06_TraitRef(S07_Path);
|
||||
struct S07_Path(Vec<S08_PathSegment>);
|
||||
struct S08_PathSegment(S09_PathParameters);
|
||||
struct S09_PathParameters(P<S10_ParenthesizedParameterData>);
|
||||
struct S10_ParenthesizedParameterData(Option<P<S11_Ty>>);
|
||||
struct S11_Ty(P<S12_Expr>);
|
||||
struct S12_Expr(P<S13_Block>);
|
||||
struct S13_Block(Vec<P<S14_Stmt>>);
|
||||
struct S14_Stmt(P<S15_Decl>);
|
||||
struct S15_Decl(P<S16_Local>);
|
||||
struct S16_Local(P<S17_Pat>);
|
||||
struct S17_Pat(P<S18_Mac>);
|
||||
struct S18_Mac(Vec<P<S19_TokenTree>>);
|
||||
struct S19_TokenTree(P<S20_Token>);
|
||||
struct S20_Token(P<S21_Nonterminal>);
|
||||
struct S21_Nonterminal(P<S22_Item>);
|
||||
struct S22_Item(P<S23_EnumDef>);
|
||||
struct S23_EnumDef(Vec<P<S24_Variant>>);
|
||||
struct S24_Variant(P<S25_VariantKind>);
|
||||
struct S25_VariantKind(P<S26_StructDef>);
|
||||
struct S26_StructDef(Vec<P<S27_StructField>>);
|
||||
struct S27_StructField(P<S28_StructFieldKind>);
|
||||
struct S28_StructFieldKind;
|
||||
|
||||
pub fn main() {}
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
// ignore-pretty - token trees can't pretty print
|
||||
|
||||
#![feature(custom_attribute)]
|
||||
|
||||
macro_rules! compiles_fine {
|
||||
(#[$at:meta]) => {
|
||||
// test that the different types of attributes work
|
||||
|
|
Loading…
Add table
Reference in a new issue