use num::Zero;
use ops::{Div, Rem, Sub};
use str;
+use slice;
+use ptr;
+use mem;
#[doc(hidden)]
trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
Sub<Output=Self> + Copy {
fn from_u8(u: u8) -> Self;
fn to_u8(&self) -> u8;
+ fn to_u32(&self) -> u32;
+ fn to_u64(&self) -> u64;
}
macro_rules! doit {
($($t:ident)*) => ($(impl Int for $t {
fn from_u8(u: u8) -> $t { u as $t }
fn to_u8(&self) -> u8 { *self as u8 }
+ fn to_u32(&self) -> u32 { *self as u32 }
+ fn to_u64(&self) -> u64 { *self as u64 }
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
}
}
}
+
macro_rules! int_base {
($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
}
}
}
+
macro_rules! integer {
($Int:ident, $Uint:ident) => {
- int_base! { Display for $Int as $Int -> Decimal }
int_base! { Binary for $Int as $Uint -> Binary }
int_base! { Octal for $Int as $Uint -> Octal }
int_base! { LowerHex for $Int as $Uint -> LowerHex }
radix_fmt! { $Int as $Int, fmt_int }
debug! { $Int }
- int_base! { Display for $Uint as $Uint -> Decimal }
int_base! { Binary for $Uint as $Uint -> Binary }
int_base! { Octal for $Uint as $Uint -> Octal }
int_base! { LowerHex for $Uint as $Uint -> LowerHex }
integer! { i16, u16 }
integer! { i32, u32 }
integer! { i64, u64 }
+
+const DEC_DIGITS_LUT: &'static[u8] =
+ b"0001020304050607080910111213141516171819\
+ 2021222324252627282930313233343536373839\
+ 4041424344454647484950515253545556575859\
+ 6061626364656667686970717273747576777879\
+ 8081828384858687888990919293949596979899";
+
+macro_rules! impl_Display {
+ ($($t:ident),*: $conv_fn:ident) => ($(
+ impl fmt::Display for $t {
+ #[allow(unused_comparisons)]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let is_positive = *self >= 0;
+ let mut n = if is_positive {
+ self.$conv_fn()
+ } else {
+ // convert the negative num to positive by summing 1 to it's 2 complement
+ (!self.$conv_fn()).wrapping_add(1)
+ };
+ let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
+ let mut curr = buf.len() as isize;
+ let buf_ptr = buf.as_mut_ptr();
+ let lut_ptr = DEC_DIGITS_LUT.as_ptr();
+
+ unsafe {
+ // eagerly decode 4 characters at a time
+ if <$t>::max_value() as u64 >= 10000 {
+ while n >= 10000 {
+ let rem = (n % 10000) as isize;
+ n /= 10000;
+
+ let d1 = (rem / 100) << 1;
+ let d2 = (rem % 100) << 1;
+ curr -= 4;
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+ ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
+ }
+ }
+
+ // if we reach here numbers are <= 9999, so at most 4 chars long
+ let mut n = n as isize; // possibly reduce 64bit math
+
+ // decode 2 more chars, if > 2 chars
+ if n >= 100 {
+ let d1 = (n % 100) << 1;
+ n /= 100;
+ curr -= 2;
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+ }
+
+ // decode last 1 or 2 chars
+ if n < 10 {
+ curr -= 1;
+ *buf_ptr.offset(curr) = (n as u8) + 48;
+ } else {
+ let d1 = n << 1;
+ curr -= 2;
+ ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+ }
+ }
+
+ let buf_slice = unsafe {
+ str::from_utf8_unchecked(
+ slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
+ };
+ f.pad_integral(is_positive, "", buf_slice)
+ }
+ })*);
+}
+
+impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
+impl_Display!(i64, u64: to_u64);
+#[cfg(target_pointer_width = "32")]
+impl_Display!(isize, usize: to_u32);
+#[cfg(target_pointer_width = "64")]
+impl_Display!(isize, usize: to_u64);
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use str::{FromStr, StrExt};
+use slice::SliceExt;
/// Provides intentionally-wrapped arithmetic on `T`.
///
-> Result<T, ParseIntError> {
use self::IntErrorKind::*;
use self::ParseIntError as PIE;
+
assert!(radix >= 2 && radix <= 36,
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
radix);
+ if src.is_empty() {
+ return Err(PIE { kind: Empty });
+ }
+
let is_signed_ty = T::from_u32(0) > T::min_value();
- match src.slice_shift_char() {
- Some(('-', "")) => Err(PIE { kind: Empty }),
- Some(('-', src)) if is_signed_ty => {
+ // all valid digits are ascii, so we will just iterate over the utf8 bytes
+ // and cast them to chars. .to_digit() will safely return None for anything
+ // other than a valid ascii digit for a the given radix, including the first-byte
+ // of multi-byte sequences
+ let src = src.as_bytes();
+
+ match (src[0], &src[1..]) {
+ (b'-', digits) if digits.is_empty() => Err(PIE { kind: Empty }),
+ (b'-', digits) if is_signed_ty => {
// The number is negative
let mut result = T::from_u32(0);
- for c in src.chars() {
- let x = match c.to_digit(radix) {
+ for &c in digits {
+ let x = match (c as char).to_digit(radix) {
Some(x) => x,
None => return Err(PIE { kind: InvalidDigit }),
};
}
Ok(result)
},
- Some((_, _)) => {
+ (c, digits) => {
// The number is signed
- let mut result = T::from_u32(0);
- for c in src.chars() {
- let x = match c.to_digit(radix) {
+ let mut result = match (c as char).to_digit(radix) {
+ Some(x) => T::from_u32(x),
+ None => return Err(PIE { kind: InvalidDigit }),
+ };
+ for &c in digits {
+ let x = match (c as char).to_digit(radix) {
Some(x) => x,
None => return Err(PIE { kind: InvalidDigit }),
};
};
}
Ok(result)
- },
- None => Err(ParseIntError { kind: Empty }),
+ }
}
}
}
#[test]
- fn test_int_from_minus_sign() {
- assert_eq!("-".parse::<i32>().ok(), None);
+ fn test_invalid() {
+ assert_eq!("--129".parse::<i8>().ok(), None);
+ assert_eq!("Съешь".parse::<u8>().ok(), None);
+ }
+
+ #[test]
+ fn test_empty() {
+ assert_eq!("-".parse::<i8>().ok(), None);
+ assert_eq!("".parse::<u8>().ok(), None);
}
}
E0432, // unresolved import
E0433, // failed to resolve
E0434, // can't capture dynamic environment in a fn item
- E0435 // attempt to use a non-constant value in a constant
+ E0435, // attempt to use a non-constant value in a constant
+ E0437, // type is not a member of trait
+ E0438, // const is not a member of trait
}
UndeclaredAssociatedType,
/// error E0407: method is not a member of trait
MethodNotMemberOfTrait(Name, &'a str),
+ /// error E0437: type is not a member of trait
+ TypeNotMemberOfTrait(Name, &'a str),
+ /// error E0438: const is not a member of trait
+ ConstNotMemberOfTrait(Name, &'a str),
/// error E0408: variable `{}` from pattern #1 is not bound in pattern
VariableNotBoundInPattern(Name, usize),
/// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
method,
trait_);
},
+ ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
+ span_err!(resolver.session, span, E0437,
+ "type `{}` is not a member of trait `{}`",
+ type_,
+ trait_);
+ },
+ ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
+ span_err!(resolver.session, span, E0438,
+ "const `{}` is not a member of trait `{}`",
+ const_,
+ trait_);
+ },
ResolutionError::VariableNotBoundInPattern(variable_name, pattern_number) => {
span_err!(resolver.session, span, E0408,
"variable `{}` from pattern #1 is not bound in pattern #{}",
for impl_item in impl_items {
match impl_item.node {
ConstImplItem(..) => {
- // If this is a trait impl, ensure the method
+ // If this is a trait impl, ensure the const
// exists in trait
this.check_trait_item(impl_item.ident.name,
- impl_item.span);
+ impl_item.span,
+ |n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
this.with_constant_rib(|this| {
visit::walk_impl_item(this, impl_item);
});
// If this is a trait impl, ensure the method
// exists in trait
this.check_trait_item(impl_item.ident.name,
- impl_item.span);
+ impl_item.span,
+ |n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
// We also need a new scope for the method-
// specific type parameters.
});
}
TypeImplItem(ref ty) => {
- // If this is a trait impl, ensure the method
+ // If this is a trait impl, ensure the type
// exists in trait
this.check_trait_item(impl_item.ident.name,
- impl_item.span);
+ impl_item.span,
+ |n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
this.visit_ty(ty);
}
});
}
- fn check_trait_item(&self, name: Name, span: Span) {
+ fn check_trait_item<F>(&self, name: Name, span: Span, err: F)
+ where F: FnOnce(Name, &str) -> ResolutionError {
// If there is a TraitRef in scope for an impl, then the method must be in the trait.
if let Some((did, ref trait_ref)) = self.current_trait_ref {
if !self.trait_item_map.contains_key(&(name, did)) {
let path_str = path_names_to_string(&trait_ref.path, 0);
resolve_error(self,
span,
- ResolutionError::MethodNotMemberOfTrait(name,
- &*path_str));
+ err(name, &*path_str));
}
}
}
return self.parse_if_expr();
}
if try!(self.eat_keyword(keywords::For) ){
- return self.parse_for_expr(None);
+ let lo = self.last_span.lo;
+ return self.parse_for_expr(None, lo);
}
if try!(self.eat_keyword(keywords::While) ){
- return self.parse_while_expr(None);
+ let lo = self.last_span.lo;
+ return self.parse_while_expr(None, lo);
}
if self.token.is_lifetime() {
let lifetime = self.get_lifetime();
+ let lo = self.span.lo;
try!(self.bump());
try!(self.expect(&token::Colon));
if try!(self.eat_keyword(keywords::While) ){
- return self.parse_while_expr(Some(lifetime))
+ return self.parse_while_expr(Some(lifetime), lo)
}
if try!(self.eat_keyword(keywords::For) ){
- return self.parse_for_expr(Some(lifetime))
+ return self.parse_for_expr(Some(lifetime), lo)
}
if try!(self.eat_keyword(keywords::Loop) ){
- return self.parse_loop_expr(Some(lifetime))
+ return self.parse_loop_expr(Some(lifetime), lo)
}
return Err(self.fatal("expected `while`, `for`, or `loop` after a label"))
}
if try!(self.eat_keyword(keywords::Loop) ){
- return self.parse_loop_expr(None);
+ let lo = self.last_span.lo;
+ return self.parse_loop_expr(None, lo);
}
if try!(self.eat_keyword(keywords::Continue) ){
let lo = self.span.lo;
}
/// Parse a 'for' .. 'in' expression ('for' token already eaten)
- pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
+ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>,
+ span_lo: BytePos) -> PResult<P<Expr>> {
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
- let lo = self.last_span.lo;
let pat = try!(self.parse_pat_nopanic());
try!(self.expect_keyword(keywords::In));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let loop_block = try!(self.parse_block());
let hi = self.last_span.hi;
- Ok(self.mk_expr(lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident)))
+ Ok(self.mk_expr(span_lo, hi, ExprForLoop(pat, expr, loop_block, opt_ident)))
}
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
- pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
+ pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>,
+ span_lo: BytePos) -> PResult<P<Expr>> {
if self.token.is_keyword(keywords::Let) {
- return self.parse_while_let_expr(opt_ident);
+ return self.parse_while_let_expr(opt_ident, span_lo);
}
- let lo = self.last_span.lo;
let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let body = try!(self.parse_block());
let hi = body.span.hi;
- return Ok(self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident)));
+ return Ok(self.mk_expr(span_lo, hi, ExprWhile(cond, body, opt_ident)));
}
/// Parse a 'while let' expression ('while' token already eaten)
- pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
- let lo = self.last_span.lo;
+ pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>,
+ span_lo: BytePos) -> PResult<P<Expr>> {
try!(self.expect_keyword(keywords::Let));
let pat = try!(self.parse_pat_nopanic());
try!(self.expect(&token::Eq));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let body = try!(self.parse_block());
let hi = body.span.hi;
- return Ok(self.mk_expr(lo, hi, ExprWhileLet(pat, expr, body, opt_ident)));
+ return Ok(self.mk_expr(span_lo, hi, ExprWhileLet(pat, expr, body, opt_ident)));
}
- pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Expr>> {
- let lo = self.last_span.lo;
+ pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>,
+ span_lo: BytePos) -> PResult<P<Expr>> {
let body = try!(self.parse_block());
let hi = body.span.hi;
- Ok(self.mk_expr(lo, hi, ExprLoop(body, opt_ident)))
+ Ok(self.mk_expr(span_lo, hi, ExprLoop(body, opt_ident)))
}
fn parse_match_expr(&mut self) -> PResult<P<Expr>> {
--- /dev/null
+// 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.
+
+// error-pattern: too big for the current architecture
+
+#[cfg(target_pointer_width = "32")]
+fn main() {
+ let x = [0usize; 0xffff_ffff];
+}
+
+#[cfg(target_pointer_width = "64")]
+fn main() {
+ let x = [0usize; 0xffff_ffff_ffff_ffff];
+}
--- /dev/null
+// 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.
+
+// Regression test for #27042. Test that a loop's label is included in its span.
+
+fn main() {
+ let _: i32 =
+ 'a: //~ ERROR mismatched types
+ loop { break };
+ let _: i32 =
+ 'b: //~ ERROR mismatched types
+ while true { break };
+ let _: i32 =
+ 'c: //~ ERROR mismatched types
+ for _ in None { break };
+ let _: i32 =
+ 'd: //~ ERROR mismatched types
+ while let Some(_) = None { break };
+}
--- /dev/null
+// Copyright 2012 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.
+
+#![feature(associated_consts)]
+
+trait A { }
+
+impl A for isize {
+ const BAR: () = (); //~ ERROR const `BAR` is not a member of trait `A`
+ type Baz = (); //~ ERROR type `Baz` is not a member of trait `A`
+ fn foo(&self) { } //~ ERROR method `foo` is not a member of trait `A`
+}
+
+fn main() { }
+++ /dev/null
-// Copyright 2012 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.
-
-trait A { }
-
-impl A for isize {
- fn foo(&self) { } //~ ERROR method `foo` is not a member of trait `A`
-}
-
-fn main() { }